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 void *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, u8 val)
35 struct usb_ctrlrequest req;
36 req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
37 req.bRequest = HID_REQ_SET_IDLE;
41 return send_default_control(endp, &req, NULL);
45 usb_keyboard_init(u32 endp, struct usb_interface_descriptor *iface, int imax)
47 if (! CONFIG_USB_KEYBOARD)
51 dprintf(2, "usb_keyboard_setup %x\n", endp);
53 struct usb_endpoint_descriptor *epdesc = (void*)&iface[1];
55 if ((void*)epdesc >= (void*)iface + imax
56 || epdesc->bDescriptorType == USB_DT_INTERFACE) {
57 dprintf(1, "No keyboard intr in?\n");
60 if (epdesc->bDescriptorType == USB_DT_ENDPOINT
61 && (epdesc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN
62 && ((epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
63 == USB_ENDPOINT_XFER_INT)
64 && epdesc->wMaxPacketSize == 8)
66 epdesc = (void*)epdesc + epdesc->bLength;
68 u32 inendp = mkendp(endp2cntl(endp), endp2devaddr(endp)
69 , epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK
70 , endp2speed(endp), epdesc->wMaxPacketSize);
72 // Enable "boot" protocol.
73 int ret = set_protocol(endp, 1);
76 // Only send reports on a new key event.
77 ret = set_idle(endp, 0);
81 void *pipe = alloc_intr_pipe(inendp, epdesc->bInterval);
92 if (! CONFIG_USB_KEYBOARD)
98 /****************************************************************
100 ****************************************************************/
102 static u16 KeyToScanCode[] VAR16 = {
103 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
104 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
105 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
106 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
107 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
108 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
109 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
110 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
111 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
112 0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
113 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
114 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
115 0x0048, 0x0049, 0x0052, 0x0053
118 static u16 ModifierToScanCode[] VAR16 = {
119 //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
120 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
137 process_key(0x1d | (keys & 0x80));
138 process_key(0x45 | (keys & 0x80));
147 handle_key(struct keyevent *data)
149 dprintf(5, "Got key %x %x\n", data->modifiers, data->keys[0]);
153 if (data->modifiers & (1<<i))
154 prockeys(GET_GLOBAL(ModifierToScanCode[i]));
155 for (i=0; i<ARRAY_SIZE(data->keys); i++) {
156 u8 key = data->keys[i];
157 if (key >= ARRAY_SIZE(KeyToScanCode))
159 key = GET_GLOBAL(KeyToScanCode[key]);
165 if (data->modifiers & (1<<i))
166 prockeys(GET_GLOBAL(ModifierToScanCode[i]) | 0x80);
172 if (! CONFIG_USB_KEYBOARD)
174 void *pipe = GET_GLOBAL(keyboard_pipe);
179 struct keyevent data;
180 int ret = usb_poll_intr(pipe, &data);