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 %p\n", pipe);
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 keyboard_pipe = alloc_intr_pipe(pipe, epdesc);
79 dprintf(1, "USB keyboard initialized\n");
84 usb_keyboard_setup(void)
86 if (! CONFIG_USB_KEYBOARD)
92 /****************************************************************
94 ****************************************************************/
96 static u16 KeyToScanCode[] VAR16 = {
97 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
98 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
99 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
100 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
101 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
102 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
103 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
104 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
105 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
106 0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
107 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
108 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
109 0x0048, 0x0049, 0x0052, 0x0053
112 static u16 ModifierToScanCode[] VAR16 = {
113 //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
114 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
117 #define RELEASEBIT 0x80
133 process_key(0x1d | (keys & RELEASEBIT));
134 process_key(0x45 | (keys & RELEASEBIT));
143 procscankey(u8 key, u8 flags)
145 if (key >= ARRAY_SIZE(KeyToScanCode))
147 u16 keys = GET_GLOBAL(KeyToScanCode[key]);
149 prockeys(keys | flags);
153 procmodkey(u8 mods, u8 flags)
158 // Modifier key change.
159 prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
165 handle_key(struct keyevent *data)
167 dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
170 u16 ebda_seg = get_ebda_seg();
171 struct usbkeyinfo old;
172 old.data = GET_EBDA2(ebda_seg, usbkey_last.data);
174 // Check for keys no longer pressed.
177 for (i=0; i<ARRAY_SIZE(old.keys); i++) {
178 u8 key = old.keys[i];
183 if (j>=ARRAY_SIZE(data->keys)) {
185 procscankey(key, RELEASEBIT);
186 if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
187 // Last pressed key released - disable repeat.
188 old.repeatcount = 0xff;
191 if (data->keys[j] == key) {
192 // Key still pressed.
194 old.keys[addpos++] = key;
199 procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
202 procmodkey(data->modifiers & ~old.modifiers, 0);
203 old.modifiers = data->modifiers;
204 for (i=0; i<ARRAY_SIZE(data->keys); i++) {
205 u8 key = data->keys[i];
210 old.keys[addpos++] = key;
211 old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
213 if (addpos < ARRAY_SIZE(old.keys))
214 old.keys[addpos] = 0;
216 // Check for key repeat event.
218 if (!old.repeatcount)
219 procscankey(old.keys[addpos-1], 0);
220 else if (old.repeatcount != 0xff)
225 SET_EBDA2(ebda_seg, usbkey_last.data, old.data);
231 if (! CONFIG_USB_KEYBOARD)
233 struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
238 struct keyevent data;
239 int ret = usb_poll_intr(pipe, &data);