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
13 struct usb_pipe *keyboard_pipe VAR16VISIBLE;
16 /****************************************************************
18 ****************************************************************/
21 set_protocol(struct usb_pipe *pipe, u16 val)
23 struct usb_ctrlrequest req;
24 req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
25 req.bRequest = HID_REQ_SET_PROTOCOL;
29 return send_default_control(pipe, &req, NULL);
33 set_idle(struct usb_pipe *pipe, int ms)
35 struct usb_ctrlrequest req;
36 req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
37 req.bRequest = HID_REQ_SET_IDLE;
38 req.wValue = (ms/4)<<8;
41 return send_default_control(pipe, &req, NULL);
44 #define KEYREPEATWAITMS 500
45 #define KEYREPEATMS 33
48 usb_keyboard_init(struct usb_pipe *pipe
49 , struct usb_interface_descriptor *iface, int imax)
51 if (! CONFIG_USB_KEYBOARD)
54 // XXX - this enables the first found keyboard (could be random)
56 dprintf(2, "usb_keyboard_setup %x\n", pipe->endp);
58 // Find intr in endpoint.
59 struct usb_endpoint_descriptor *epdesc = findEndPointDesc(
60 iface, imax, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
61 if (!epdesc || epdesc->wMaxPacketSize != 8) {
62 dprintf(1, "No keyboard intr in?\n");
66 // Enable "boot" protocol.
67 int ret = set_protocol(pipe, 1);
70 // Periodically send reports to enable key repeat.
71 ret = set_idle(pipe, KEYREPEATMS);
75 u32 inendp = mkendpFromDesc(pipe, epdesc);
76 keyboard_pipe = alloc_intr_pipe(inendp, epdesc->bInterval);
80 dprintf(1, "USB keyboard initialized\n");
85 usb_keyboard_setup(void)
87 if (! CONFIG_USB_KEYBOARD)
93 /****************************************************************
95 ****************************************************************/
97 static u16 KeyToScanCode[] VAR16 = {
98 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
99 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
100 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
101 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
102 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
103 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
104 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
105 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
106 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
107 0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
108 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
109 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
110 0x0048, 0x0049, 0x0052, 0x0053
113 static u16 ModifierToScanCode[] VAR16 = {
114 //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
115 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
118 #define RELEASEBIT 0x80
134 process_key(0x1d | (keys & RELEASEBIT));
135 process_key(0x45 | (keys & RELEASEBIT));
144 procscankey(u8 key, u8 flags)
146 if (key >= ARRAY_SIZE(KeyToScanCode))
148 u16 keys = GET_GLOBAL(KeyToScanCode[key]);
150 prockeys(keys | flags);
154 procmodkey(u8 mods, u8 flags)
159 // Modifier key change.
160 prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
166 handle_key(struct keyevent *data)
168 dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
171 u16 ebda_seg = get_ebda_seg();
172 struct usbkeyinfo old;
173 old.data = GET_EBDA2(ebda_seg, usbkey_last.data);
175 // Check for keys no longer pressed.
178 for (i=0; i<ARRAY_SIZE(old.keys); i++) {
179 u8 key = old.keys[i];
184 if (j>=ARRAY_SIZE(data->keys)) {
186 procscankey(key, RELEASEBIT);
187 if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
188 // Last pressed key released - disable repeat.
189 old.repeatcount = 0xff;
192 if (data->keys[j] == key) {
193 // Key still pressed.
195 old.keys[addpos++] = key;
200 procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
203 procmodkey(data->modifiers & ~old.modifiers, 0);
204 old.modifiers = data->modifiers;
205 for (i=0; i<ARRAY_SIZE(data->keys); i++) {
206 u8 key = data->keys[i];
211 old.keys[addpos++] = key;
212 old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
214 if (addpos < ARRAY_SIZE(old.keys))
215 old.keys[addpos] = 0;
217 // Check for key repeat event.
219 if (!old.repeatcount)
220 procscankey(old.keys[addpos-1], 0);
221 else if (old.repeatcount != 0xff)
226 SET_EBDA2(ebda_seg, usbkey_last.data, old.data);
232 if (! CONFIG_USB_KEYBOARD)
234 struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
239 struct keyevent data;
240 int ret = usb_poll_intr(pipe, &data);