1 // Code for handling USB Human Interface Devices (HID).
3 // Copyright (C) 2009 Kevin O'Connor <kevin@koconnor.net>
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
7 #include "util.h" // dprintf
8 #include "usb-hid.h" // usb_keyboard_setup
9 #include "config.h" // CONFIG_*
10 #include "usb.h" // usb_ctrlrequest
11 #include "biosvar.h" // GET_GLOBAL
12 #include "ps2port.h" // ATKBD_CMD_GETID
14 struct usb_pipe *keyboard_pipe VAR16VISIBLE;
17 /****************************************************************
19 ****************************************************************/
21 // Send USB HID protocol message.
23 set_protocol(struct usb_pipe *pipe, u16 val)
25 struct usb_ctrlrequest req;
26 req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
27 req.bRequest = HID_REQ_SET_PROTOCOL;
31 return send_default_control(pipe, &req, NULL);
34 // Send USB HID SetIdle request.
36 set_idle(struct usb_pipe *pipe, int ms)
38 struct usb_ctrlrequest req;
39 req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
40 req.bRequest = HID_REQ_SET_IDLE;
41 req.wValue = (ms/4)<<8;
44 return send_default_control(pipe, &req, NULL);
47 #define KEYREPEATWAITMS 500
48 #define KEYREPEATMS 33
51 usb_keyboard_init(struct usb_pipe *pipe
52 , struct usb_interface_descriptor *iface, int imax)
54 if (! CONFIG_USB_KEYBOARD)
57 // XXX - this enables the first found keyboard (could be random)
59 dprintf(2, "usb_keyboard_setup %p\n", pipe);
61 // Find intr in endpoint.
62 struct usb_endpoint_descriptor *epdesc = findEndPointDesc(
63 iface, imax, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
64 if (!epdesc || epdesc->wMaxPacketSize != 8) {
65 dprintf(1, "No keyboard intr in?\n");
69 // Enable "boot" protocol.
70 int ret = set_protocol(pipe, 1);
73 // Periodically send reports to enable key repeat.
74 ret = set_idle(pipe, KEYREPEATMS);
78 keyboard_pipe = alloc_intr_pipe(pipe, epdesc);
82 dprintf(1, "USB keyboard initialized\n");
87 usb_keyboard_setup(void)
89 if (! CONFIG_USB_KEYBOARD)
95 /****************************************************************
97 ****************************************************************/
99 // Mapping from USB key id to ps2 key sequence.
100 static u16 KeyToScanCode[] VAR16 = {
101 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
102 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
103 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
104 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
105 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
106 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
107 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
108 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
109 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
110 0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
111 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
112 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
113 0x0048, 0x0049, 0x0052, 0x0053
116 // Mapping from USB modifier id to ps2 key sequence.
117 static u16 ModifierToScanCode[] VAR16 = {
118 //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
119 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
122 #define RELEASEBIT 0x80
124 // Format of USB event data
131 // Translate data from KeyToScanCode[] to calls to process_key().
140 process_key(0x1d | (keys & RELEASEBIT));
141 process_key(0x45 | (keys & RELEASEBIT));
149 // Handle a USB key press/release event.
151 procscankey(u8 key, u8 flags)
153 if (key >= ARRAY_SIZE(KeyToScanCode))
155 u16 keys = GET_GLOBAL(KeyToScanCode[key]);
157 prockeys(keys | flags);
160 // Handle a USB modifier press/release event.
162 procmodkey(u8 mods, u8 flags)
167 // Modifier key change.
168 prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
173 // Process USB keyboard data.
175 handle_key(struct keyevent *data)
177 dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
180 u16 ebda_seg = get_ebda_seg();
181 struct usbkeyinfo old;
182 old.data = GET_EBDA2(ebda_seg, usbkey_last.data);
184 // Check for keys no longer pressed.
187 for (i=0; i<ARRAY_SIZE(old.keys); i++) {
188 u8 key = old.keys[i];
193 if (j>=ARRAY_SIZE(data->keys)) {
195 procscankey(key, RELEASEBIT);
196 if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
197 // Last pressed key released - disable repeat.
198 old.repeatcount = 0xff;
201 if (data->keys[j] == key) {
202 // Key still pressed.
204 old.keys[addpos++] = key;
209 procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
212 procmodkey(data->modifiers & ~old.modifiers, 0);
213 old.modifiers = data->modifiers;
214 for (i=0; i<ARRAY_SIZE(data->keys); i++) {
215 u8 key = data->keys[i];
220 old.keys[addpos++] = key;
221 old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
223 if (addpos < ARRAY_SIZE(old.keys))
224 old.keys[addpos] = 0;
226 // Check for key repeat event.
228 if (!old.repeatcount)
229 procscankey(old.keys[addpos-1], 0);
230 else if (old.repeatcount != 0xff)
235 SET_EBDA2(ebda_seg, usbkey_last.data, old.data);
238 // Check for USB events pending - called periodically from timer interrupt.
242 if (! CONFIG_USB_KEYBOARD)
244 struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
249 struct keyevent data;
250 int ret = usb_poll_intr(pipe, &data);
257 // Test if USB keyboard is active.
261 return GET_GLOBAL(keyboard_pipe) != NULL;
264 // Handle a ps2 style keyboard command.
266 usb_kbd_command(int command, u8 *param)
269 case ATKBD_CMD_GETID:
270 // Return the id of a standard AT keyboard.