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 ****************************************************************/
20 // Send USB HID protocol message.
22 set_protocol(struct usb_pipe *pipe, u16 val)
24 struct usb_ctrlrequest req;
25 req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
26 req.bRequest = HID_REQ_SET_PROTOCOL;
30 return send_default_control(pipe, &req, NULL);
33 // Send USB HID SetIdle request.
35 set_idle(struct usb_pipe *pipe, int ms)
37 struct usb_ctrlrequest req;
38 req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
39 req.bRequest = HID_REQ_SET_IDLE;
40 req.wValue = (ms/4)<<8;
43 return send_default_control(pipe, &req, NULL);
46 #define KEYREPEATWAITMS 500
47 #define KEYREPEATMS 33
50 usb_keyboard_init(struct usb_pipe *pipe
51 , struct usb_interface_descriptor *iface, int imax)
53 if (! CONFIG_USB_KEYBOARD)
56 // XXX - this enables the first found keyboard (could be random)
58 dprintf(2, "usb_keyboard_setup %p\n", pipe);
60 // Find intr in endpoint.
61 struct usb_endpoint_descriptor *epdesc = findEndPointDesc(
62 iface, imax, USB_ENDPOINT_XFER_INT, USB_DIR_IN);
63 if (!epdesc || epdesc->wMaxPacketSize != 8) {
64 dprintf(1, "No keyboard intr in?\n");
68 // Enable "boot" protocol.
69 int ret = set_protocol(pipe, 1);
72 // Periodically send reports to enable key repeat.
73 ret = set_idle(pipe, KEYREPEATMS);
77 keyboard_pipe = alloc_intr_pipe(pipe, epdesc);
81 dprintf(1, "USB keyboard initialized\n");
86 usb_keyboard_setup(void)
88 if (! CONFIG_USB_KEYBOARD)
94 /****************************************************************
96 ****************************************************************/
98 // Mapping from USB key id to ps2 key sequence.
99 static u16 KeyToScanCode[] VAR16 = {
100 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
101 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
102 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
103 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
104 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
105 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
106 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
107 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
108 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
109 0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
110 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
111 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
112 0x0048, 0x0049, 0x0052, 0x0053
115 // Mapping from USB modifier id to ps2 key sequence.
116 static u16 ModifierToScanCode[] VAR16 = {
117 //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
118 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
121 #define RELEASEBIT 0x80
123 // Format of USB event data
130 // Translate data from KeyToScanCode[] to calls to process_key().
139 process_key(0x1d | (keys & RELEASEBIT));
140 process_key(0x45 | (keys & RELEASEBIT));
148 // Handle a USB key press/release event.
150 procscankey(u8 key, u8 flags)
152 if (key >= ARRAY_SIZE(KeyToScanCode))
154 u16 keys = GET_GLOBAL(KeyToScanCode[key]);
156 prockeys(keys | flags);
159 // Handle a USB modifier press/release event.
161 procmodkey(u8 mods, u8 flags)
166 // Modifier key change.
167 prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
172 // Process USB keyboard data.
174 handle_key(struct keyevent *data)
176 dprintf(9, "Got key %x %x\n", data->modifiers, data->keys[0]);
179 u16 ebda_seg = get_ebda_seg();
180 struct usbkeyinfo old;
181 old.data = GET_EBDA2(ebda_seg, usbkey_last.data);
183 // Check for keys no longer pressed.
186 for (i=0; i<ARRAY_SIZE(old.keys); i++) {
187 u8 key = old.keys[i];
192 if (j>=ARRAY_SIZE(data->keys)) {
194 procscankey(key, RELEASEBIT);
195 if (i+1 >= ARRAY_SIZE(old.keys) || !old.keys[i+1])
196 // Last pressed key released - disable repeat.
197 old.repeatcount = 0xff;
200 if (data->keys[j] == key) {
201 // Key still pressed.
203 old.keys[addpos++] = key;
208 procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
211 procmodkey(data->modifiers & ~old.modifiers, 0);
212 old.modifiers = data->modifiers;
213 for (i=0; i<ARRAY_SIZE(data->keys); i++) {
214 u8 key = data->keys[i];
219 old.keys[addpos++] = key;
220 old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
222 if (addpos < ARRAY_SIZE(old.keys))
223 old.keys[addpos] = 0;
225 // Check for key repeat event.
227 if (!old.repeatcount)
228 procscankey(old.keys[addpos-1], 0);
229 else if (old.repeatcount != 0xff)
234 SET_EBDA2(ebda_seg, usbkey_last.data, old.data);
237 // Check for USB events pending - called periodically from timer interrupt.
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);