blob: 7c638298da8b0d94882e8ad956cbfbed134630bd [file] [log] [blame]
Patrick Georgid21f68b2008-09-02 16:06:22 +00001/*
2 * This file is part of the libpayload project.
3 *
Stefan Reinauerb56f2d02010-03-25 22:17:36 +00004 * Copyright (C) 2008-2010 coresystems GmbH
Patrick Georgid21f68b2008-09-02 16:06:22 +00005 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000030// #define USB_DEBUG
31
Jordan Crouse29061a52008-09-11 17:29:00 +000032#include <usb/usb.h>
Patrick Georgi4727c072008-10-16 19:20:51 +000033#include <curses.h>
Patrick Georgid21f68b2008-09-02 16:06:22 +000034
35enum { hid_subclass_none = 0, hid_subclass_boot = 1 };
Patrick Georgi4727c072008-10-16 19:20:51 +000036typedef enum { hid_proto_boot = 0, hid_proto_report = 1 } hid_proto;
Patrick Georgid21f68b2008-09-02 16:06:22 +000037enum { hid_boot_proto_none = 0, hid_boot_proto_keyboard =
38 1, hid_boot_proto_mouse = 2
39};
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000040#ifdef USB_DEBUG
Patrick Georgid21f68b2008-09-02 16:06:22 +000041static const char *boot_protos[3] = { "(none)", "keyboard", "mouse" };
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000042#endif
Patrick Georgid21f68b2008-09-02 16:06:22 +000043enum { GET_REPORT = 0x1, GET_IDLE = 0x2, GET_PROTOCOL = 0x3, SET_REPORT =
44 0x9, SET_IDLE = 0xa, SET_PROTOCOL = 0xb
45};
46
47static void
48usb_hid_destroy (usbdev_t *dev)
49{
Patrick Georgi4727c072008-10-16 19:20:51 +000050 free (dev->data);
Patrick Georgid21f68b2008-09-02 16:06:22 +000051}
52
Patrick Georgi4727c072008-10-16 19:20:51 +000053typedef struct {
54 void* queue;
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000055 hid_descriptor_t *descriptor;
Patrick Georgi4727c072008-10-16 19:20:51 +000056} usbhid_inst_t;
57
58#define HID_INST(dev) ((usbhid_inst_t*)(dev)->data)
59
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000060/* keybuffer is global to all USB keyboards */
61static int keycount;
62#define KEYBOARD_BUFFER_SIZE 16
63static short keybuffer[KEYBOARD_BUFFER_SIZE];
Patrick Georgi4727c072008-10-16 19:20:51 +000064
Stefan Reinauerb56f2d02010-03-25 22:17:36 +000065char *countries[36][2] = {
66 { "not supported", "us" },
67 { "Arabic", "ae" },
68 { "Belgian", "be" },
69 { "Canadian-Bilingual", "ca" },
70 { "Canadian-French", "ca" },
71 { "Czech Republic", "cz" },
72 { "Danish", "dk" },
73 { "Finnish", "fi" },
74 { "French", "fr" },
75 { "German", "de" },
76 { "Greek", "gr" },
77 { "Hebrew", "il" },
78 { "Hungary", "hu" },
79 { "International (ISO)", "iso" },
80 { "Italian", "it" },
81 { "Japan (Katakana)", "jp" },
82 { "Korean", "us" },
83 { "Latin American", "us" },
84 { "Netherlands/Dutch", "nl" },
85 { "Norwegian", "no" },
86 { "Persian (Farsi)", "ir" },
87 { "Poland", "pl" },
88 { "Portuguese", "pt" },
89 { "Russia", "ru" },
90 { "Slovakia", "sl" },
91 { "Spanish", "es" },
92 { "Swedish", "se" },
93 { "Swiss/French", "ch" },
94 { "Swiss/German", "ch" },
95 { "Switzerland", "ch" },
96 { "Taiwan", "tw" },
97 { "Turkish-Q", "tr" },
98 { "UK", "uk" },
99 { "US", "us" },
100 { "Yugoslavia", "yu" },
101 { "Turkish-F", "tr" },
102 /* 36 - 255: Reserved */
Patrick Georgid21f68b2008-09-02 16:06:22 +0000103};
104
105
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000106
107struct layout_maps {
108 char *country;
109 short map[4][0x80];
110};
111
112static struct layout_maps *map;
113
114static struct layout_maps keyboard_layouts[] = {
115// #ifdef CONFIG_PC_KEYBOARD_LAYOUT_US
116{ .country = "us", .map = {
117 { /* No modifier */
118 -1, -1, -1, -1, 'a', 'b', 'c', 'd',
119 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
120 /* 0x10 */
121 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
122 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
123 /* 0x20 */
124 '3', '4', '5', '6', '7', '8', '9', '0',
125 '\n', '\e', '\b', '\t', ' ', '-', '=', '[',
126 /* 0x30 */
127 ']', '\\', -1, ';', '\'', '`', ',', '.',
128 '/', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6),
129 /* 0x40 */
130 KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */,
131 KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
132 /* 50 */
133 KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+',
134 KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME,
135 /* 60 */
136 KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1,
137 -1, -1, -1, -1, -1, -1, -1, -1,
138 /* 70 */
139 -1, -1, -1, -1, -1, -1, -1, -1,
140 -1, -1, -1, -1, -1, -1, -1, -1,
141 },
142 { /* Shift modifier */
143 -1, -1, -1, -1, 'A', 'B', 'C', 'D',
144 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
145 /* 0x10 */
146 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
147 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
148 /* 0x20 */
149 '#', '$', '%', '^', '&', '*', '(', ')',
150 '\n', '\e', '\b', '\t', ' ', '-', '=', '[',
151 /* 0x30 */
152 ']', '\\', -1, ':', '\'', '`', ',', '.',
153 '/', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6),
154 /* 0x40 */
155 KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */,
156 KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
157 /* 50 */
158 KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+',
159 KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME,
160 /* 60 */
161 KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1,
162 -1, -1, -1, -1, -1, -1, -1, -1,
163 /* 70 */
164 -1, -1, -1, -1, -1, -1, -1, -1,
165 -1, -1, -1, -1, -1, -1, -1, -1,
166 },
167 { /* Alt */
168 -1, -1, -1, -1, 'a', 'b', 'c', 'd',
169 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
170 /* 0x10 */
171 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
172 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
173 /* 0x20 */
174 '3', '4', '5', '6', '7', '8', '9', '0',
175 '\n', '\e', '\b', '\t', ' ', '-', '=', '[',
176 /* 0x30 */
177 ']', '\\', -1, ';', '\'', '`', ',', '.',
178 '/', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6),
179 /* 0x40 */
180 KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */,
181 KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
182 /* 50 */
183 KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+',
184 KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME,
185 /* 60 */
186 KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1,
187 -1, -1, -1, -1, -1, -1, -1, -1,
188 /* 70 */
189 -1, -1, -1, -1, -1, -1, -1, -1,
190 -1, -1, -1, -1, -1, -1, -1, -1,
191 },
192 { /* Shift+Alt modifier */
193 -1, -1, -1, -1, 'A', 'B', 'C', 'D',
194 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
195 /* 0x10 */
196 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
197 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
198 /* 0x20 */
199 '#', '$', '%', '^', '&', '*', '(', ')',
200 '\n', '\e', '\b', '\t', ' ', '-', '=', '[',
201 /* 0x30 */
202 ']', '\\', -1, ':', '\'', '`', ',', '.',
203 '/', -1 /* CapsLk */, KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KEY_F(5), KEY_F(6),
204 /* 0x40 */
205 KEY_F(7), KEY_F(8), KEY_F(9), KEY_F(10), KEY_F(11), KEY_F(12), KEY_PRINT, -1 /* ScrLk */,
206 KEY_BREAK, KEY_IC, KEY_HOME, KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
207 /* 50 */
208 KEY_LEFT, KEY_DOWN, KEY_UP, -1 /*NumLck*/, '/', '*', '-' /* = ? */, '+',
209 KEY_ENTER, KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, -1, KEY_RIGHT, KEY_HOME,
210 /* 60 */
211 KEY_UP, KEY_PPAGE, -1, KEY_DC, -1 /* < > | */, -1 /* Win Key Right */, -1, -1,
212 -1, -1, -1, -1, -1, -1, -1, -1,
213 /* 70 */
214 -1, -1, -1, -1, -1, -1, -1, -1,
215 -1, -1, -1, -1, -1, -1, -1, -1,
216 }
217}},
218//#endif
219};
220
221#define MOD_SHIFT (1 << 0)
222#define MOD_ALT (1 << 1)
223#define MOD_CTRL (1 << 2)
224
225static void usb_hid_keyboard_queue(int ch) {
226 /* ignore key presses if buffer full */
227 if (keycount < KEYBOARD_BUFFER_SIZE)
228 keybuffer[keycount++] = ch;
229}
230
231typedef union {
232 struct {
233 u8 modifiers;
234 u8 repeats;
235 u8 keys[6];
236 };
237 u8 buffer[8];
238} usb_hid_keyboard_event_t;
239
240#define KEYBOARD_REPEAT_MS 30
241#define INITIAL_REPEAT_DELAY 10
242#define REPEAT_DELAY 2
243
244static void
245usb_hid_process_keyboard_event(usb_hid_keyboard_event_t *current,
246 usb_hid_keyboard_event_t *previous)
247{
248 int i, keypress = 0, modifiers = 0;
249 static int lastkeypress = 0, repeat_delay = INITIAL_REPEAT_DELAY;
250
251 if (current->modifiers & 0x01) /* Left-Ctrl */ modifiers |= MOD_CTRL;
252 if (current->modifiers & 0x02) /* Left-Shift */ modifiers |= MOD_SHIFT;
253 if (current->modifiers & 0x04) /* Left-Alt */ modifiers |= MOD_ALT;
254 if (current->modifiers & 0x08) /* Left-GUI */ ;
255 if (current->modifiers & 0x10) /* Right-Ctrl */ modifiers |= MOD_CTRL;
256 if (current->modifiers & 0x20) /* Right-Shift */ modifiers |= MOD_SHIFT;
257 if (current->modifiers & 0x40) /* Right-AltGr */ modifiers |= MOD_ALT;
258 if (current->modifiers & 0x80) /* Right-GUI */ ;
259
260 if ((current->modifiers & 0x05) && ((current->keys[0] == 0x4c) ||
261 (current->keys[0]==0x63))) {
262 /* vulcan nerve pinch */
263 if (reset_handler)
264 reset_handler();
265 }
266
267 /* Did the event change at all? */
268 if (lastkeypress && !memcmp(current, previous, sizeof(usb_hid_keyboard_event_t))) {
269 /* No. Then it's a key repeat event. */
270 if (repeat_delay) {
271 repeat_delay--;
272 } else {
273 usb_hid_keyboard_queue(lastkeypress);
274 repeat_delay = REPEAT_DELAY;
275 }
276
277 return;
278 }
279
280 lastkeypress = 0;
281
282 for (i=0; i<6; i++) {
283 int j;
284 int skip = 0;
285 // No more keys? skip
286 if (current->keys[i] == 0)
287 return;
288
289 for (j=0; j<6; j++) {
290 if (current->keys[i] == previous->keys[j]) {
291 skip = 1;
292 break;
293 }
294 }
295 if (skip)
296 continue;
297
298
299 /* Mask off MOD_CTRL */
300 keypress = map->map[modifiers & 0x03][current->keys[i]];
301
302 if (modifiers & MOD_CTRL) {
303 switch (keypress) {
304 case 'a' ... 'z':
305 keypress &= 0x1f;
306 break;
307 default:
308 continue;
309 }
310 }
311
312 if (keypress == -1) {
313 /* Debug: Print unknown keys */
314 debug ("usbhid: <%x> %x [ %x %x %x %x %x %x ] %d\n",
315 current->modifiers, current->repeats,
316 current->keys[0], current->keys[1],
317 current->keys[2], current->keys[3],
318 current->keys[4], current->keys[5], i);
319
320 /* Unknown key? Try next one in the queue */
321 continue;
322 }
323
324 usb_hid_keyboard_queue(keypress);
325
326 /* Remember for authentic key repeat */
327 lastkeypress = keypress;
328 repeat_delay = INITIAL_REPEAT_DELAY;
329 }
330}
331
Patrick Georgid21f68b2008-09-02 16:06:22 +0000332static void
333usb_hid_poll (usbdev_t *dev)
334{
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000335 usb_hid_keyboard_event_t current;
336 static usb_hid_keyboard_event_t previous = {
337 .buffer = { 0, 0, 0, 0, 0, 0, 0, 0}
338 };
Patrick Georgi4727c072008-10-16 19:20:51 +0000339 u8* buf;
340 while ((buf=dev->controller->poll_intr_queue (HID_INST(dev)->queue))) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000341 memcpy(&current.buffer, buf, 8);
342 usb_hid_process_keyboard_event(&current, &previous);
343 previous = current;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000344 }
345}
346
Patrick Georgi4727c072008-10-16 19:20:51 +0000347static void
348usb_hid_set_idle (usbdev_t *dev, interface_descriptor_t *interface, u16 duration)
Patrick Georgid21f68b2008-09-02 16:06:22 +0000349{
Patrick Georgi4727c072008-10-16 19:20:51 +0000350 dev_req_t dr;
351 dr.data_dir = host_to_device;
352 dr.req_type = class_type;
353 dr.req_recp = iface_recp;
354 dr.bRequest = SET_IDLE;
355 dr.wValue = (duration >> 2) << 8;
356 dr.wIndex = interface->bInterfaceNumber;
357 dr.wLength = 0;
358 dev->controller->control (dev, OUT, sizeof (dev_req_t), &dr, 0, 0);
359}
360
361static void
362usb_hid_set_protocol (usbdev_t *dev, interface_descriptor_t *interface, hid_proto proto)
363{
364 dev_req_t dr;
365 dr.data_dir = host_to_device;
366 dr.req_type = class_type;
367 dr.req_recp = iface_recp;
368 dr.bRequest = SET_PROTOCOL;
369 dr.wValue = proto;
370 dr.wIndex = interface->bInterfaceNumber;
371 dr.wLength = 0;
372 dev->controller->control (dev, OUT, sizeof (dev_req_t), &dr, 0, 0);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000373}
374
Patrick Georgi657a6dc2008-10-21 15:08:18 +0000375static struct console_input_driver cons = {
376 .havekey = usbhid_havechar,
377 .getchar = usbhid_getchar
378};
379
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000380
381int usb_hid_set_layout (char *country)
382{
383 /* FIXME should be per keyboard */
384 int i;
385
386 for (i=0; i<ARRAY_SIZE(keyboard_layouts); i++) {
387 if (strncmp(keyboard_layouts[i].country, country,
388 strlen(keyboard_layouts[i].country)))
389 continue;
390
391 /* Found, changing keyboard layout */
392 map = &keyboard_layouts[i];
393 printf(" Keyboard layout '%s'\n", map->country);
394 return 0;
395 }
396
397 printf("Keyboard layout '%s' not found, using '%s'\n",
398 country, map->country);
399
400 /* Nothing found, not changed */
401 return -1;
402}
403
Patrick Georgid21f68b2008-09-02 16:06:22 +0000404void
405usb_hid_init (usbdev_t *dev)
406{
407
Patrick Georgi657a6dc2008-10-21 15:08:18 +0000408 static int installed = 0;
409 if (!installed) {
410 installed = 1;
411 console_add_input_driver (&cons);
412 }
413
Patrick Georgi4727c072008-10-16 19:20:51 +0000414 configuration_descriptor_t *cd = (configuration_descriptor_t*)dev->configuration;
415 interface_descriptor_t *interface = (interface_descriptor_t*)(((char *) cd) + cd->bLength);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000416
417 if (interface->bInterfaceSubClass == hid_subclass_boot) {
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000418 u8 countrycode;
419 debug (" supports boot interface..\n");
420 debug (" it's a %s\n",
Patrick Georgid21f68b2008-09-02 16:06:22 +0000421 boot_protos[interface->bInterfaceProtocol]);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000422 switch (interface->bInterfaceProtocol) {
423 case hid_boot_proto_keyboard:
Patrick Georgi4727c072008-10-16 19:20:51 +0000424 dev->data = malloc (sizeof (usbhid_inst_t));
Stefan Reinauer5fe6e232009-07-31 11:39:55 +0000425 if (!dev->data)
426 usb_fatal("Not enough memory for USB HID device.\n");
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000427 debug (" configuring...\n");
Patrick Georgi4727c072008-10-16 19:20:51 +0000428 usb_hid_set_protocol(dev, interface, hid_proto_boot);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000429 usb_hid_set_idle(dev, interface, KEYBOARD_REPEAT_MS);
430 debug (" activating...\n");
431
432 HID_INST (dev)->descriptor =
433 (hid_descriptor_t *)
434 get_descriptor(dev, gen_bmRequestType
435 (device_to_host, standard_type, iface_recp),
436 0x21, 0, 0);
437 countrycode = HID_INST(dev)->descriptor->bCountryCode;
438 /* 35 countries defined: */
439 if (countrycode > 35)
440 countrycode = 0;
441 printf (" Keyboard has %s layout (country code %02x)\n",
442 countries[countrycode][0], countrycode);
443
444 /* Set keyboard layout accordingly */
445 usb_hid_set_layout(countries[countrycode][1]);
Patrick Georgid21f68b2008-09-02 16:06:22 +0000446
447 // only add here, because we only support boot-keyboard HID devices
Patrick Georgid21f68b2008-09-02 16:06:22 +0000448 dev->destroy = usb_hid_destroy;
449 dev->poll = usb_hid_poll;
Patrick Georgi4727c072008-10-16 19:20:51 +0000450 int i;
Stefan Reinauerd233f362009-04-30 16:46:12 +0000451 for (i = 0; i <= dev->num_endp; i++) {
Patrick Georgi4727c072008-10-16 19:20:51 +0000452 if (dev->endpoints[i].endpoint == 0)
453 continue;
454 if (dev->endpoints[i].type != INTERRUPT)
455 continue;
456 if (dev->endpoints[i].direction != IN)
457 continue;
458 break;
459 }
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000460 debug (" found endpoint %x for interrupt-in\n", i);
Patrick Georgi4727c072008-10-16 19:20:51 +0000461 /* 20 buffers of 8 bytes, for every 10 msecs */
462 HID_INST(dev)->queue = dev->controller->create_intr_queue (&dev->endpoints[i], 8, 20, 10);
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000463 keycount = 0;
464 debug (" configuration done.\n");
465 break;
466 case hid_boot_proto_mouse:
467 printf("NOTICE: USB mice are not supported.\n");
468 break;
Patrick Georgid21f68b2008-09-02 16:06:22 +0000469 }
470 }
471}
Patrick Georgi4727c072008-10-16 19:20:51 +0000472
473int usbhid_havechar (void)
474{
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000475 return (keycount != 0);
Patrick Georgi4727c072008-10-16 19:20:51 +0000476}
477
478int usbhid_getchar (void)
479{
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000480 short ret;
481
482 if (keycount == 0)
483 return 0;
484 ret = keybuffer[0];
485 memmove(keybuffer, keybuffer + 1, --keycount);
486
487 return (int)ret;
Patrick Georgi4727c072008-10-16 19:20:51 +0000488}
Stefan Reinauerb56f2d02010-03-25 22:17:36 +0000489