Support USB keyboard auto-repeat.
[seabios.git] / src / usb-hid.c
1 // Code for handling USB Human Interface Devices (HID).
2 //
3 // Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
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
12
13 struct usb_pipe *keyboard_pipe VAR16VISIBLE;
14
15
16 /****************************************************************
17  * Setup
18  ****************************************************************/
19
20 static int
21 set_protocol(u32 endp, u16 val)
22 {
23     struct usb_ctrlrequest req;
24     req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
25     req.bRequest = HID_REQ_SET_PROTOCOL;
26     req.wValue = val;
27     req.wIndex = 0;
28     req.wLength = 0;
29     return send_default_control(endp, &req, NULL);
30 }
31
32 static int
33 set_idle(u32 endp, int ms)
34 {
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;
39     req.wIndex = 0;
40     req.wLength = 0;
41     return send_default_control(endp, &req, NULL);
42 }
43
44 #define KEYREPEATWAITMS 500
45 #define KEYREPEATMS 33
46
47 int
48 usb_keyboard_init(u32 endp, struct usb_interface_descriptor *iface, int imax)
49 {
50     if (! CONFIG_USB_KEYBOARD)
51         return -1;
52     if (keyboard_pipe)
53         // XXX - this enables the first found keyboard (could be random)
54         return -1;
55     dprintf(2, "usb_keyboard_setup %x\n", endp);
56
57     struct usb_endpoint_descriptor *epdesc = (void*)&iface[1];
58     for (;;) {
59         if ((void*)epdesc >= (void*)iface + imax
60             || epdesc->bDescriptorType == USB_DT_INTERFACE) {
61             dprintf(1, "No keyboard intr in?\n");
62             return -1;
63         }
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)
69             break;
70         epdesc = (void*)epdesc + epdesc->bLength;
71     }
72     u32 inendp = mkendp(endp2cntl(endp), endp2devaddr(endp)
73                         , epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK
74                         , endp2speed(endp), epdesc->wMaxPacketSize);
75
76     // Enable "boot" protocol.
77     int ret = set_protocol(endp, 1);
78     if (ret)
79         return -1;
80     // Only send reports on a new key event.
81     ret = set_idle(endp, KEYREPEATMS);
82     if (ret)
83         return -1;
84
85     struct usb_pipe *pipe = alloc_intr_pipe(inendp, epdesc->bInterval);
86     if (!pipe)
87         return -1;
88     keyboard_pipe = pipe;
89
90     return 0;
91 }
92
93 void
94 usb_keyboard_setup(void)
95 {
96     if (! CONFIG_USB_KEYBOARD)
97         return;
98     keyboard_pipe = NULL;
99 }
100
101
102 /****************************************************************
103  * Keyboard events
104  ****************************************************************/
105
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
120 };
121
122 static u16 ModifierToScanCode[] VAR16 = {
123     //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
124     0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
125 };
126
127 #define RELEASEBIT 0x80
128
129 struct keyevent {
130     u8 modifiers;
131     u8 reserved;
132     u8 keys[6];
133 };
134
135 static void
136 prockeys(u16 keys)
137 {
138     if (keys > 0xff) {
139         u8 key = keys>>8;
140         if (key == 0xe1) {
141             // Pause key
142             process_key(0xe1);
143             process_key(0x1d | (keys & RELEASEBIT));
144             process_key(0x45 | (keys & RELEASEBIT));
145             return;
146         }
147         process_key(key);
148     }
149     process_key(keys);
150 }
151
152 static void
153 procscankey(u8 key, u8 flags)
154 {
155     if (key >= ARRAY_SIZE(KeyToScanCode))
156         return;
157     u16 keys = GET_GLOBAL(KeyToScanCode[key]);
158     if (keys)
159         prockeys(keys | flags);
160 }
161
162 static void
163 procmodkey(u8 mods, u8 flags)
164 {
165     int i;
166     for (i=0; mods; i++)
167         if (mods & (1<<i)) {
168             // Modifier key change.
169             prockeys(GET_GLOBAL(ModifierToScanCode[i]) | flags);
170             mods &= ~(1<<i);
171         }
172 }
173
174 static void noinline
175 handle_key(struct keyevent *data)
176 {
177     dprintf(5, "Got key %x %x\n", data->modifiers, data->keys[0]);
178
179     // Load old keys.
180     u16 ebda_seg = get_ebda_seg();
181     struct usbkeyinfo old;
182     old.data = GET_EBDA2(ebda_seg, usbkey_last.data);
183
184     // Check for keys no longer pressed.
185     int addpos = 0;
186     int i;
187     for (i=0; i<ARRAY_SIZE(old.keys); i++) {
188         u8 key = old.keys[i];
189         if (!key)
190             break;
191         int j;
192         for (j=0;; j++) {
193             if (j>=ARRAY_SIZE(data->keys)) {
194                 // Key released.
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;
199                 break;
200             }
201             if (data->keys[j] == key) {
202                 // Key still pressed.
203                 data->keys[j] = 0;
204                 old.keys[addpos++] = key;
205                 break;
206             }
207         }
208     }
209     procmodkey(old.modifiers & ~data->modifiers, RELEASEBIT);
210
211     // Process new keys
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];
216         if (!key)
217             continue;
218         // New key pressed.
219         procscankey(key, 0);
220         old.keys[addpos++] = key;
221         old.repeatcount = KEYREPEATWAITMS / KEYREPEATMS + 1;
222     }
223     if (addpos < ARRAY_SIZE(old.keys))
224         old.keys[addpos] = 0;
225
226     // Check for key repeat event.
227     if (addpos) {
228         if (!old.repeatcount)
229             procscankey(old.keys[addpos-1], 0);
230         else if (old.repeatcount != 0xff)
231             old.repeatcount--;
232     }
233
234     // Update old keys
235     SET_EBDA2(ebda_seg, usbkey_last.data, old.data);
236 }
237
238 void
239 usb_check_key(void)
240 {
241     if (! CONFIG_USB_KEYBOARD)
242         return;
243     struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
244     if (!pipe)
245         return;
246
247     for (;;) {
248         struct keyevent data;
249         int ret = usb_poll_intr(pipe, &data);
250         if (ret)
251             break;
252         handle_key(&data);
253     }
254 }