KBD Library Overview

Introduction

The KBD library provides an API to interface with USB keyboards connected to the Wii U console. It includes both synchronous (polling) and asynchronous (interrupt callback) methods of retrieving keystrokes. The keystroke API provides access both to generated Unicode (UTF-16) characters and to low-level USB HID key codes.

The KBD library provides support for the following.

Sample demo programs are included that demonstrate how to use the KBD library under the path $CAFE_ROOT/system/src/demo/usb/kbd/.

API function declarations, function types, and constants are in the $CAFE_ROOT/system/include/cafe/kbd.h header file.

The kbd.h header file includes the support header files $CAFE_ROOT/system/include/cafe/kbd/kbd_key_defs.h and $CAFE_ROOT/system/include/cafe/kbd/kbd_hid_codes.h.

Architecture

The following diagram describes the main architecture of the keyboard library.

  1. Starting at the bottom, when a key is pressed or released on the keyboard, the USB HID driver calls the KBD Driver and passes it a HID report.
  2. The KBD Driver module processes the report and turns it into one or more up/down key (KBDHIDCode) events.
  3. For each key event, the KBD Driver module calls the HID-to-Unicode Translate module, the Mod Processing module, and the User Key Callback (in that order).
  4. Given the current keyboard Mod State and country setting, the HID-to-Unicode Translate module converts the KBDHIDCode into a KBDUnicode.
  5. The Mod Processing module looks to see if the KBDUnicode represents a modifier action and changes the current keyboard Mod State accordingly. For example, if the key code 0xE1 (KBD_HID_Left_Shift) is pressed, it is translated into the (private) Unicode value KBK_Mod_Shift, and Mod Processing sees this Unicode value and then makes sure the KBD_MS_SHIFT modifier is turned on in the Mod State.
  6. The KBD Driver handles key repeat processing. Key repeat sets a timer to send additional key down events through the KBD Driver.
  7. The User Key Callback is called with both the KBDHIDCode and the KBDUnicode. In addition, it is also given the key up/down state (KBDKeyMode) as well as the current keyboard Mod State (KBDModState).
  8. The User Key Callback may also use the Translate module as well as access or change the current Mod State. It can even alter the key event fields.
  9. The KBD Driver finally stores the key event in an internal queue for use by the synchronous character API.

Not shown in the diagram are keyboard attach/detach event processing or the synchronous keyboard API.

The KBD library maintains the keyboard LED state when key entries are processed. For legacy source compatibility, the KBDSetLeds, KBSetLedsAsync, and KBDSetLedsRetry functions have been deprecated. These functions will not perform any operations and will print notice on DEBUG builds.

The LEDs may be set to specific state by calling the KBDSetLedsEx, KBSetLedsAsyncEx, or KBDSetLedsRetryEx function if the application wishes to set them for other purpose.

High-Level Unicode Interface

The keyboard driver may be used at a high-level by ignoring the HID codes returned and paying attention only to the Unicode values returned. In addition, the application should ignore key up events and modifier key presses. To simplify this processing, use existing macros. For more information, refer to KBDKeyEvent.

When a synchronous call is made to the KBDGetKey function, all keys pressed since its last invocation are returned. If no keys have been pressed since it was last called, NULL is returned. We also provide a function, KBDSetKeyCallback, to register a callback function that will be called with a pointer to a KBDKeyEvent that contains key event information.

Keyboard modifier HID keys are mapped to special Unicode values that affect the modifier state. Some modifier states, such as KBD_MS_SHIFT and KBD_MS_NUM_LOCK, then affect how other keys are looked up in the keymaps. Other modifier states, such as KBD_MS_ALT and KBD_MS_GUI, are just passed along with the base character. The modifier state KBD_MS_SHIFTED_KEY determines whether the unshifted (base) or shifted key is sent when a combination of modifier keys is pressed (for example, SHIFT and ALT). This is off by default, and the application should set this modifier bit if it requires the shifted key. This bit also overrides the NUM LOCK state when set.

KBDUnicode Values

All keys are provided with a KBDUnicode value. For the function keys, editing keys, arrow keys, and other special keys, custom (private) Unicode values are used. These private Unicode values are all in the range 0xf000-0xf1ff, and they should never be used for external data exchange. They should also not be confused with private Unicode values that may be used elsewhere in the Revolution SDK or other SDKs. The KBD private Unicode values should only be used with keyboard-related functions.

You may use the macro KBD_UC_IS_PRIVATE to determine if a KBDUnicode value is in the 0xf00-0xf1ff range.

#define KBD_UC_IS_PRIVATE(uc) (((uc)>=0xf000 && (uc)<=0xF1FF) || ((uc)==0xFFFF))

For broader application, you may also define macros such as these below (they are not defined in kbd.h).

// Indicate if a generic Unicode value is private (according to Unicode standard) or not
#define UNICODE_IS_PRIVATE(uc) (((uc)>=0xE000 && (uc)<=0xF8FF) || ((uc)>=0xFFF0))
#define UNICODE_IS_REGULAR(uc) (((uc)<0xE000) || ((uc)>0xF8FF && (uc)<0xFFF0))

The KBD private Unicode values are defined in kbd_key_defs.h. Regular Unicode values can be found at the Unicode website (http://www.unicode.org/charts/lastresort.html).

The keys on the numeric keypad (the operator symbols and the numbers when NUM LOCK is on) use Unicode values that are the normal ASCII/Unicode value plus 0xf100. Use the KBD_UC_IS_KP_REG_KEY macro to check if a key is within this range. Also, use the KBD_KP_REG_KEY_TO_ASCII macro to convert it into an ASCII/Unicode value.

#define KBD_UC_IS_KP_REG_KEY(uc) (((uc)>=0xf100) && ((uc)<=0xf13f))
#define KBD_KP_REG_KEY_TO_ASCII(uc) ((uc)&0x3f)

The arrow and editing keys on the keypad are also distinguished from those that are stand-alone keys. The stand-alone keys are in the range 0xf180-0xf1bf, and the keypad versions are in the range 0xf140-0xf17f (a difference of 0x40). For example:

KBK_Insert:        0xf1b0
KBK_Keypad_Insert: 0xf170 (0x40 less)
KBK_Keypad_0:      0xf130 (0x40 less) (KBK_Keypad_0 is same key as KBK_Keypad_Insert)
'0':               0x0030 (0xf100 less)

The keys KBK_Keypad_0 - KBK_Keypad_9 and KBK_Keypad_Period are all mapped in a similar way. Note that while KBK_Keypad_Comma is also defined (for use in country maps where it applies), the code for KBK_Keypad_Delete (on the same key) and KBK_Delete are still based on the ASCII code for period.

The KBD_UC_IS_KP_NUM_NL_KEY macro indicates if a key is on the numeric keypad and was pressed while NUM LOCK was on. Also, KBD_UC_IS_KP_NUM_UL_KEY indicates if a key is on the numeric keypad and was pressed while NUM LOCK was off. The macro KBD_KP_NUM_UL_KEY_TO_KP_NUM_NL_KEY can be used to convert the second to the first.

#define KBD_UC_IS_KP_NUM_NL_KEY(uc) (((uc)>=KBK_Keypad_0 && ((uc)<=KBK_Keypad_9)))
#define KBD_UC_IS_KP_NUM_UL_KEY(uc) (((uc)>=KBK_Keypad_Insert && ((uc)<=KBK_Keypad_Page_Up)))
#define KBD_KP_NUM_UL_KEY_TO_KP_NUM_NL_KEY(uc) ((KBDUnicode)((uc)-0x40))

The Backspace, Tab, and Escape keys are assigned to private Unicode values. These values are the standard ASCII/Unicode values plus 0xf1c0. KBD_UC_IS_CTRL_KEY indicates whether a given key is such a value. Additionally, KBD_CTRL_KEY_TO_ASCII converts values into ASCII/Unicode.

#define KBD_UC_IS_CTRL_KEY  (((uc)>=0xf1c0) && ((uc)<=0xf1df))
#define KBD_CTRL_KEY_TO_ASCII(uc) ((uc)&0x1f)

Low-Level USB HID Key Code Interface

For applications that would like to deal with the keyboard at a lower-level and access individual physical key presses and release, this can also be performed, since all events are passed through using the APIs described above.

The application can take over some functions normally done by the KBD Driver. It can interpret the HID codes (either by using its own maps or by calling KBDTranslateHidCode). It can also independently track and alter the modifier state. (Call the KBDSetLockProcessing function to disable modifier key processing for the driver.) When key event information has been changed by a callback, the changed information will be placed in the internal queue and used by the synchronous API.

USB HID codes are intended to be mostly device-independent, meaning that the key in a given position should return the same code regardless of what is printed on that key, but there are some exceptions. The following diagram and table summarize the differences between these codes and a normal keyboard. However, be aware that exceptions not included here may occur.



Keyboard Model HID codes unique to this keyboard HID codes missing from this keyboard
US 0x31 (backslash/vertical bar) 0x32, 0x64, 0x66-0xDF
European 0x32 (near ENTER key; symbols vary)
0x64 (near left SHIFT key; symbols vary)
0x31, 0x66-0xDF
Japanese 0x32 (right bracket/right brace)
0x87 (backslash/underline/ro/broken bar)
0x88 (katakana/hiragana)
0x89 (yen/vertical bar)
0x8A (henkan)
0x8B (muhenkan)
0x94 (see Note below)
0x31 (see note below)
0x64

Notes:

For a description of individual HID codes, refer to kbd_hid_codes.h or to the HID Usage Table for keyboards at http://www.usb.org/developers/hidpage/.

To avoid these irregularities, an application key callback should perhaps immediately translate HID key codes into KBKUnicode values using the function KBDTranslateHidCode. There are few situations in which raw HID key codes are absolutely required.

When mapping user input to key presses, an application designer must consider whether multiple keys may be pressed simultaneously and whether a keyboard can recognize such key presses without problems. A problem known as "ghosting" will occasionally occur when three or more keys are pressed at the same time. This problem will cause the keyboard to recognize key presses that are not made by the user. Also, some multiple key combinations may be undetectable by the keyboard electronics. Different keyboards will have different issues with multiple key presses. For most normal keyboard input, this should not be a problem. However, this can be a problem when you attempt to use the keyboard as a controller pad, or when you try to detect an unsupported combination of modifier keys.

Library Flow

The HID and KBD RPL is initialized automatically, call the KBDSetup function to prepare the KBD API for runtime use. You must call this function before using the KBD API. The KBD RPL carries all key mappings. There is no need to call any of the region initialization functions ( KBDInitRegionUS, KBDInitRegionJP, or KBDInitRegionEU) to incrementally link key maps. These functions exist for legacy source compatibility and will print notice on DEBUG builds.

After callbacks have been registered, keyboard events will result in interrupts and the appropriate application callback will be called. Note that because callbacks run in height priority driver thread, they should not do anything that requires a significant amount of time. If necessary, they can trigger a thread to handle any lengthy procedures.

Alternatively, you may call a synchronous API to examine keyboard input. The synchronous API should be called frequently enough to prevent queue overflow. It may be good practice to call this API in a loop until it returns with a null key value.

When KBD is no longer needed, the KBDTeardown function should be called. Calling this function will disable the registered callback functions, and keyboard events will be ignored.

The KBDInit and KBDExit functions are for legacy source compatibility and will print message on DEBUG builds.

Notes

You must be careful when using the KBD library to avoid sending too many USB messages. If you saturate the USB bus, you may prevent other devices (such as the Wii Remote) from using USB, and you may also prevent key presses from getting through.

The following functions may result in a call that sends an LED message over USB:

Additionally, the KBSSetLedsEx function is not recommended because it will block if the keyboard fails to ACK on the USB bus. For more information, refer to the documentation for these commands.

Limitations

These are the current limitations for keyboard support.

Revision History

2014/06/24 Reworked external link.
2013/06/20 Deprecated KBDInitRegion*, KBDInit, KBDExit, KBDSetLeds*. Added KBDSetup, KBDTeardown, KBDSetLeds*Ex. KBD lib sets LEDs per key entry.
2013/05/08 Automated cleanup pass.
2012/08/21 Cleanup Pass.
2011/12/21 Moved to Cafe.
2009/11/02 The standard firmware and the extended firmware were integrated in Revolution SDK 3.3, so text relating to them was deleted.
2008/09/26 Changed the library flow so the functions are called in the order of HIDOpenAsync, then KBDInit, and then region initialization functions.


CONFIDENTIAL