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, 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)
50 // XXX - this enables the first found keyboard (could be random)
52 dprintf(2, "usb_keyboard_setup %x\n", endp);
54 struct usb_endpoint_descriptor *epdesc = (void*)&iface[1];
56 if ((void*)epdesc >= (void*)iface + imax
57 || epdesc->bDescriptorType == USB_DT_INTERFACE) {
58 dprintf(1, "No keyboard intr in?\n");
61 if (epdesc->bDescriptorType == USB_DT_ENDPOINT
62 && (epdesc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN
63 && ((epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
64 == USB_ENDPOINT_XFER_INT)
65 && epdesc->wMaxPacketSize == 8)
67 epdesc = (void*)epdesc + epdesc->bLength;
69 u32 inendp = mkendp(endp2cntl(endp), endp2devaddr(endp)
70 , epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK
71 , endp2speed(endp), epdesc->wMaxPacketSize);
73 // Enable "boot" protocol.
74 int ret = set_protocol(endp, 1);
77 // Only send reports on a new key event.
78 ret = set_idle(endp, 0);
82 struct usb_pipe *pipe = alloc_intr_pipe(inendp, epdesc->bInterval);
93 if (! CONFIG_USB_KEYBOARD)
99 /****************************************************************
101 ****************************************************************/
103 static u16 KeyToScanCode[] VAR16 = {
104 0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
105 0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
106 0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
107 0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
108 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
109 0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
110 0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
111 0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
112 0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
113 0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
114 0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
115 0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
116 0x0048, 0x0049, 0x0052, 0x0053
119 static u16 ModifierToScanCode[] VAR16 = {
120 //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
121 0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
138 process_key(0x1d | (keys & 0x80));
139 process_key(0x45 | (keys & 0x80));
148 handle_key(struct keyevent *data)
150 dprintf(5, "Got key %x %x\n", data->modifiers, data->keys[0]);
154 if (data->modifiers & (1<<i))
155 prockeys(GET_GLOBAL(ModifierToScanCode[i]));
156 for (i=0; i<ARRAY_SIZE(data->keys); i++) {
157 u8 key = data->keys[i];
158 if (key >= ARRAY_SIZE(KeyToScanCode))
160 key = GET_GLOBAL(KeyToScanCode[key]);
166 if (data->modifiers & (1<<i))
167 prockeys(GET_GLOBAL(ModifierToScanCode[i]) | 0x80);
173 if (! CONFIG_USB_KEYBOARD)
175 struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
180 struct keyevent data;
181 int ret = usb_poll_intr(pipe, &data);