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(u32 endp, 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(endp, &req, NULL);
33 set_idle(u32 endp, 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(endp, &req, NULL);
44 #define KEYREPEATWAITMS 500
45 #define KEYREPEATMS 33
48 usb_keyboard_init(u32 endp, struct usb_interface_descriptor *iface, int imax)
50 if (! CONFIG_USB_KEYBOARD)
53 // XXX - this enables the first found keyboard (could be random)
55 dprintf(2, "usb_keyboard_setup %x\n", endp);
57 struct usb_endpoint_descriptor *epdesc = (void*)&iface[1];
59 if ((void*)epdesc >= (void*)iface + imax
60 || epdesc->bDescriptorType == USB_DT_INTERFACE) {
61 dprintf(1, "No keyboard intr in?\n");
64 if (epdesc->bDescriptorType == USB_DT_ENDPOINT
65 && (epdesc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN
66 && ((epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
67 == USB_ENDPOINT_XFER_INT)
68 && epdesc->wMaxPacketSize == 8)
70 epdesc = (void*)epdesc + epdesc->bLength;
72 u32 inendp = mkendp(endp2cntl(endp), endp2devaddr(endp)
73 , epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK
74 , endp2speed(endp), epdesc->wMaxPacketSize);
76 // Enable "boot" protocol.
77 int ret = set_protocol(endp, 1);
80 // Only send reports on a new key event.
81 ret = set_idle(endp, KEYREPEATMS);
85 struct usb_pipe *pipe = alloc_intr_pipe(inendp, epdesc->bInterval);
94 usb_keyboard_setup(void)
96 if (! CONFIG_USB_KEYBOARD)
102 /****************************************************************
104 ****************************************************************/
106 static u16 KeyToScanCode[] VAR16 = {
107 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
108 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
109 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
110 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
111 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
112 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
113 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
114 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
115 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
116 0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
117 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
118 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
119 0x0048, 0x0049, 0x0052, 0x0053
122 static u16 ModifierToScanCode[] VAR16 = {
123 //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
124 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
127 #define RELEASEBIT 0x80
143 process_key(0x1d | (keys & RELEASEBIT));
144 process_key(0x45 | (keys & RELEASEBIT));
153 procscankey(u8 key, u8 flags)
155 if (key >= ARRAY_SIZE(KeyToScanCode))
157 u16 keys = GET_GLOBAL(KeyToScanCode[key]);
159 prockeys(keys | flags);
163 procmodkey(u8 mods, u8 flags)
168 // Modifier key change.
169 prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
175 handle_key(struct keyevent *data)
177 dprintf(5, "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);
241 if (! CONFIG_USB_KEYBOARD)
243 struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
248 struct keyevent data;
249 int ret = usb_poll_intr(pipe, &data);