1 /*
2 * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <ipxe/console.h>
31 #include <ipxe/keys.h>
32 #include <ipxe/usb.h>
33 #include "usbkbd.h"
34
35 /** @file
36 *
37 * USB keyboard driver
38 *
39 */
40
41 /** List of USB keyboards */
42 static LIST_HEAD ( usb_keyboards );
43
44 /******************************************************************************
45 *
46 * Keyboard map
47 *
48 ******************************************************************************
49 */
50
51 /**
52 * Map USB keycode to iPXE key
53 *
54 * @v keycode Keycode
55 * @v modifiers Modifiers
56 * @v leds LED state
57 * @ret key iPXE key
58 *
59 * Key codes are defined in the USB HID Usage Tables Keyboard/Keypad
60 * page.
61 */
usbkbd_map(unsigned int keycode,unsigned int modifiers,unsigned int leds)62 static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers,
63 unsigned int leds ) {
64 unsigned int key;
65
66 if ( keycode < USBKBD_KEY_A ) {
67 /* Not keys */
68 key = 0;
69 } else if ( keycode <= USBKBD_KEY_Z ) {
70 /* Alphabetic keys */
71 key = ( keycode - USBKBD_KEY_A + 'a' );
72 if ( modifiers & USBKBD_CTRL ) {
73 key -= ( 'a' - CTRL_A );
74 } else if ( ( modifiers & USBKBD_SHIFT ) ||
75 ( leds & USBKBD_LED_CAPS_LOCK ) ) {
76 key -= ( 'a' - 'A' );
77 }
78 } else if ( keycode <= USBKBD_KEY_0 ) {
79 /* Numeric key row */
80 if ( modifiers & USBKBD_SHIFT ) {
81 key = "!@#$%^&*()" [ keycode - USBKBD_KEY_1 ];
82 } else {
83 key = ( ( ( keycode - USBKBD_KEY_1 + 1 ) % 10 ) + '0' );
84 }
85 } else if ( keycode <= USBKBD_KEY_SPACE ) {
86 /* Unmodifiable keys */
87 static const uint8_t unmodifable[] =
88 { LF, ESC, BACKSPACE, TAB, ' ' };
89 key = unmodifable[ keycode - USBKBD_KEY_ENTER ];
90 } else if ( keycode <= USBKBD_KEY_SLASH ) {
91 /* Punctuation keys */
92 if ( modifiers & USBKBD_SHIFT ) {
93 key = "_+{}|~:\"~<>?" [ keycode - USBKBD_KEY_MINUS ];
94 } else {
95 key = "-=[]\\#;'`,./" [ keycode - USBKBD_KEY_MINUS ];
96 }
97 } else if ( keycode <= USBKBD_KEY_UP ) {
98 /* Special keys */
99 static const uint16_t special[] = {
100 0, 0, 0, 0, 0, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9,
101 KEY_F10, KEY_F11, KEY_F12, 0, 0, 0, KEY_IC, KEY_HOME,
102 KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
103 KEY_LEFT, KEY_DOWN, KEY_UP
104 };
105 key = special[ keycode - USBKBD_KEY_CAPS_LOCK ];
106 } else if ( keycode <= USBKBD_KEY_PAD_ENTER ) {
107 /* Keypad (unaffected by Num Lock) */
108 key = "\0/*-+\n" [ keycode - USBKBD_KEY_NUM_LOCK ];
109 } else if ( keycode <= USBKBD_KEY_PAD_DOT ) {
110 /* Keypad (affected by Num Lock) */
111 if ( leds & USBKBD_LED_NUM_LOCK ) {
112 key = "1234567890." [ keycode - USBKBD_KEY_PAD_1 ];
113 } else {
114 static const uint16_t keypad[] = {
115 KEY_END, KEY_DOWN, KEY_NPAGE, KEY_LEFT, 0,
116 KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PPAGE,
117 KEY_IC, KEY_DC
118 };
119 key = keypad[ keycode - USBKBD_KEY_PAD_1 ];
120 };
121 } else {
122 key = 0;
123 }
124
125 return key;
126 }
127
128 /******************************************************************************
129 *
130 * Keyboard buffer
131 *
132 ******************************************************************************
133 */
134
135 /**
136 * Insert keypress into keyboard buffer
137 *
138 * @v kbd USB keyboard
139 * @v keycode Keycode
140 * @v modifiers Modifiers
141 */
usbkbd_produce(struct usb_keyboard * kbd,unsigned int keycode,unsigned int modifiers)142 static void usbkbd_produce ( struct usb_keyboard *kbd, unsigned int keycode,
143 unsigned int modifiers ) {
144 unsigned int leds = 0;
145 unsigned int key;
146
147 /* Check for LED-modifying keys */
148 if ( keycode == USBKBD_KEY_CAPS_LOCK ) {
149 leds = USBKBD_LED_CAPS_LOCK;
150 } else if ( keycode == USBKBD_KEY_NUM_LOCK ) {
151 leds = USBKBD_LED_NUM_LOCK;
152 }
153
154 /* Handle LED-modifying keys */
155 if ( leds ) {
156 kbd->leds ^= leds;
157 kbd->leds_changed = 1;
158 return;
159 }
160
161 /* Map to iPXE key */
162 key = usbkbd_map ( keycode, modifiers, kbd->leds );
163
164 /* Do nothing if this keycode has no corresponding iPXE key */
165 if ( ! key ) {
166 DBGC ( kbd, "KBD %s has no key for keycode %#02x:%#02x\n",
167 kbd->name, modifiers, keycode );
168 return;
169 }
170
171 /* Check for buffer overrun */
172 if ( usbkbd_fill ( kbd ) >= USBKBD_BUFSIZE ) {
173 DBGC ( kbd, "KBD %s buffer overrun (key %#02x)\n",
174 kbd->name, key );
175 return;
176 }
177
178 /* Insert into buffer */
179 kbd->key[ ( kbd->prod++ ) % USBKBD_BUFSIZE ] = key;
180 DBGC2 ( kbd, "KBD %s key %#02x produced\n", kbd->name, key );
181 }
182
183 /**
184 * Consume character from keyboard buffer
185 *
186 * @v kbd USB keyboard
187 * @ret character Character
188 */
usbkbd_consume(struct usb_keyboard * kbd)189 static unsigned int usbkbd_consume ( struct usb_keyboard *kbd ) {
190 static char buf[] = "\x1b[xx~";
191 char *tmp = &buf[2];
192 unsigned int key;
193 unsigned int character;
194 unsigned int ansi_n;
195 unsigned int len;
196
197 /* Sanity check */
198 assert ( usbkbd_fill ( kbd ) > 0 );
199
200 /* Get current keypress */
201 key = kbd->key[ kbd->cons % USBKBD_BUFSIZE ];
202
203 /* If this is a straightforward key, just consume and return it */
204 if ( key < KEY_MIN ) {
205 kbd->cons++;
206 DBGC2 ( kbd, "KBD %s key %#02x consumed\n", kbd->name, key );
207 return key;
208 }
209
210 /* Construct ANSI sequence */
211 ansi_n = KEY_ANSI_N ( key );
212 if ( ansi_n )
213 tmp += sprintf ( tmp, "%d", ansi_n );
214 *(tmp++) = KEY_ANSI_TERMINATOR ( key );
215 *tmp = '\0';
216 len = ( tmp - buf );
217 assert ( len < sizeof ( buf ) );
218 if ( kbd->subcons == 0 ) {
219 DBGC2 ( kbd, "KBD %s key %#02x consumed as ^[%s\n",
220 kbd->name, key, &buf[1] );
221 }
222
223 /* Extract character from ANSI sequence */
224 assert ( kbd->subcons < len );
225 character = buf[ kbd->subcons++ ];
226
227 /* Consume key if applicable */
228 if ( kbd->subcons == len ) {
229 kbd->cons++;
230 kbd->subcons = 0;
231 }
232
233 return character;
234 }
235
236 /******************************************************************************
237 *
238 * Keyboard report
239 *
240 ******************************************************************************
241 */
242
243 /**
244 * Check for presence of keycode in report
245 *
246 * @v report Keyboard report
247 * @v keycode Keycode (must be non-zero)
248 * @ret has_keycode Keycode is present in report
249 */
usbkbd_has_keycode(struct usb_keyboard_report * report,unsigned int keycode)250 static int usbkbd_has_keycode ( struct usb_keyboard_report *report,
251 unsigned int keycode ) {
252 unsigned int i;
253
254 /* Check for keycode */
255 for ( i = 0 ; i < ( sizeof ( report->keycode ) /
256 sizeof ( report->keycode[0] ) ) ; i++ ) {
257 if ( report->keycode[i] == keycode )
258 return keycode;
259 }
260
261 return 0;
262 }
263
264 /**
265 * Handle keyboard report
266 *
267 * @v kbd USB keyboard
268 * @v new New keyboard report
269 */
usbkbd_report(struct usb_keyboard * kbd,struct usb_keyboard_report * new)270 static void usbkbd_report ( struct usb_keyboard *kbd,
271 struct usb_keyboard_report *new ) {
272 struct usb_keyboard_report *old = &kbd->report;
273 unsigned int keycode;
274 unsigned int i;
275
276 /* Check if current key has been released */
277 if ( kbd->keycode && ! usbkbd_has_keycode ( new, kbd->keycode ) ) {
278 DBGC2 ( kbd, "KBD %s keycode %#02x released\n",
279 kbd->name, kbd->keycode );
280 kbd->keycode = 0;
281 }
282
283 /* Decrement auto-repeat hold-off timer, if applicable */
284 if ( kbd->holdoff )
285 kbd->holdoff--;
286
287 /* Check if a new key has been pressed */
288 for ( i = 0 ; i < ( sizeof ( new->keycode ) /
289 sizeof ( new->keycode[0] ) ) ; i++ ) {
290
291 /* Ignore keys present in the previous report */
292 keycode = new->keycode[i];
293 if ( ( keycode == 0 ) || usbkbd_has_keycode ( old, keycode ) )
294 continue;
295 DBGC2 ( kbd, "KBD %s keycode %#02x pressed\n",
296 kbd->name, keycode );
297
298 /* Insert keypress into keyboard buffer */
299 usbkbd_produce ( kbd, keycode, new->modifiers );
300
301 /* Record as most recent keycode */
302 kbd->keycode = keycode;
303
304 /* Start auto-repeat hold-off timer */
305 kbd->holdoff = USBKBD_HOLDOFF;
306 }
307
308 /* Insert auto-repeated keypress into keyboard buffer, if applicable */
309 if ( kbd->keycode && ! kbd->holdoff )
310 usbkbd_produce ( kbd, kbd->keycode, new->modifiers );
311
312 /* Record report */
313 memcpy ( old, new, sizeof ( *old ) );
314 }
315
316 /******************************************************************************
317 *
318 * Interrupt endpoint
319 *
320 ******************************************************************************
321 */
322
323 /**
324 * Complete interrupt transfer
325 *
326 * @v ep USB endpoint
327 * @v iobuf I/O buffer
328 * @v rc Completion status code
329 */
usbkbd_complete(struct usb_endpoint * ep,struct io_buffer * iobuf,int rc)330 static void usbkbd_complete ( struct usb_endpoint *ep,
331 struct io_buffer *iobuf, int rc ) {
332 struct usb_keyboard *kbd = container_of ( ep, struct usb_keyboard,
333 hid.in );
334 struct usb_keyboard_report *report;
335
336 /* Ignore packets cancelled when the endpoint closes */
337 if ( ! ep->open )
338 goto drop;
339
340 /* Ignore packets with errors */
341 if ( rc != 0 ) {
342 DBGC ( kbd, "KBD %s interrupt IN failed: %s\n",
343 kbd->name, strerror ( rc ) );
344 goto drop;
345 }
346
347 /* Ignore underlength packets */
348 if ( iob_len ( iobuf ) < sizeof ( *report ) ) {
349 DBGC ( kbd, "KBD %s underlength report:\n", kbd->name );
350 DBGC_HDA ( kbd, 0, iobuf->data, iob_len ( iobuf ) );
351 goto drop;
352 }
353 report = iobuf->data;
354
355 /* Handle keyboard report */
356 usbkbd_report ( kbd, report );
357
358 drop:
359 /* Recycle I/O buffer */
360 usb_recycle ( &kbd->hid.in, iobuf );
361 }
362
363 /** Interrupt endpoint operations */
364 static struct usb_endpoint_driver_operations usbkbd_operations = {
365 .complete = usbkbd_complete,
366 };
367
368 /******************************************************************************
369 *
370 * Keyboard LEDs
371 *
372 ******************************************************************************
373 */
374
375 /**
376 * Set keyboard LEDs
377 *
378 * @v kbd USB keyboard
379 * @ret rc Return status code
380 */
usbkbd_set_leds(struct usb_keyboard * kbd)381 static int usbkbd_set_leds ( struct usb_keyboard *kbd ) {
382 struct usb_function *func = kbd->hid.func;
383 int rc;
384
385 DBGC2 ( kbd, "KBD %s setting LEDs to %#02x\n", kbd->name, kbd->leds );
386
387 /* Set keyboard LEDs */
388 if ( ( rc = usbhid_set_report ( func->usb, func->interface[0],
389 USBHID_REPORT_OUTPUT, 0, &kbd->leds,
390 sizeof ( kbd->leds ) ) ) != 0 ) {
391 DBGC ( kbd, "KBD %s could not set LEDs to %#02x: %s\n",
392 kbd->name, kbd->leds, strerror ( rc ) );
393 return rc;
394 }
395
396 return 0;
397 }
398
399 /******************************************************************************
400 *
401 * USB interface
402 *
403 ******************************************************************************
404 */
405
406 /**
407 * Probe device
408 *
409 * @v func USB function
410 * @v config Configuration descriptor
411 * @ret rc Return status code
412 */
usbkbd_probe(struct usb_function * func,struct usb_configuration_descriptor * config)413 static int usbkbd_probe ( struct usb_function *func,
414 struct usb_configuration_descriptor *config ) {
415 struct usb_device *usb = func->usb;
416 struct usb_keyboard *kbd;
417 int rc;
418
419 /* Allocate and initialise structure */
420 kbd = zalloc ( sizeof ( *kbd ) );
421 if ( ! kbd ) {
422 rc = -ENOMEM;
423 goto err_alloc;
424 }
425 kbd->name = func->name;
426 kbd->bus = usb->port->hub->bus;
427 usbhid_init ( &kbd->hid, func, &usbkbd_operations, NULL );
428 usb_refill_init ( &kbd->hid.in, 0, sizeof ( kbd->report ),
429 USBKBD_INTR_MAX_FILL );
430
431 /* Describe USB human interface device */
432 if ( ( rc = usbhid_describe ( &kbd->hid, config ) ) != 0 ) {
433 DBGC ( kbd, "KBD %s could not describe: %s\n",
434 kbd->name, strerror ( rc ) );
435 goto err_describe;
436 }
437 DBGC ( kbd, "KBD %s using %s (len %zd)\n",
438 kbd->name, usb_endpoint_name ( &kbd->hid.in ), kbd->hid.in.mtu );
439
440 /* Set boot protocol */
441 if ( ( rc = usbhid_set_protocol ( usb, func->interface[0],
442 USBHID_PROTOCOL_BOOT ) ) != 0 ) {
443 DBGC ( kbd, "KBD %s could not set boot protocol: %s\n",
444 kbd->name, strerror ( rc ) );
445 goto err_set_protocol;
446 }
447
448 /* Set idle time */
449 if ( ( rc = usbhid_set_idle ( usb, func->interface[0], 0,
450 USBKBD_IDLE_DURATION ) ) != 0 ) {
451 DBGC ( kbd, "KBD %s could not set idle time: %s\n",
452 kbd->name, strerror ( rc ) );
453 goto err_set_idle;
454 }
455
456 /* Open USB human interface device */
457 if ( ( rc = usbhid_open ( &kbd->hid ) ) != 0 ) {
458 DBGC ( kbd, "KBD %s could not open: %s\n",
459 kbd->name, strerror ( rc ) );
460 goto err_open;
461 }
462
463 /* Add to list of USB keyboards */
464 list_add_tail ( &kbd->list, &usb_keyboards );
465
466 /* Set initial LED state */
467 usbkbd_set_leds ( kbd );
468
469 usb_func_set_drvdata ( func, kbd );
470 return 0;
471
472 usbhid_close ( &kbd->hid );
473 err_open:
474 err_set_idle:
475 err_set_protocol:
476 err_describe:
477 free ( kbd );
478 err_alloc:
479 return rc;
480 }
481
482 /**
483 * Remove device
484 *
485 * @v func USB function
486 */
usbkbd_remove(struct usb_function * func)487 static void usbkbd_remove ( struct usb_function *func ) {
488 struct usb_keyboard *kbd = usb_func_get_drvdata ( func );
489
490 /* Remove from list of USB keyboards */
491 list_del ( &kbd->list );
492
493 /* Close USB human interface device */
494 usbhid_close ( &kbd->hid );
495
496 /* Free device */
497 free ( kbd );
498 }
499
500 /** USB keyboard device IDs */
501 static struct usb_device_id usbkbd_ids[] = {
502 {
503 .name = "kbd",
504 .vendor = USB_ANY_ID,
505 .product = USB_ANY_ID,
506 },
507 };
508
509 /** USB keyboard driver */
510 struct usb_driver usbkbd_driver __usb_driver = {
511 .ids = usbkbd_ids,
512 .id_count = ( sizeof ( usbkbd_ids ) / sizeof ( usbkbd_ids[0] ) ),
513 .class = USB_CLASS_ID ( USB_CLASS_HID, USB_SUBCLASS_HID_BOOT,
514 USBKBD_PROTOCOL ),
515 .score = USB_SCORE_NORMAL,
516 .probe = usbkbd_probe,
517 .remove = usbkbd_remove,
518 };
519
520 /******************************************************************************
521 *
522 * Console interface
523 *
524 ******************************************************************************
525 */
526
527 /**
528 * Read a character from the console
529 *
530 * @ret character Character read
531 */
usbkbd_getchar(void)532 static int usbkbd_getchar ( void ) {
533 struct usb_keyboard *kbd;
534
535 /* Consume first available key */
536 list_for_each_entry ( kbd, &usb_keyboards, list ) {
537 if ( usbkbd_fill ( kbd ) )
538 return usbkbd_consume ( kbd );
539 }
540
541 return 0;
542 }
543
544 /**
545 * Check for available input
546 *
547 * @ret is_available Input is available
548 */
usbkbd_iskey(void)549 static int usbkbd_iskey ( void ) {
550 struct usb_keyboard *kbd;
551 unsigned int fill;
552
553 /* Poll USB keyboards, refill endpoints, and set LEDs if applicable */
554 list_for_each_entry ( kbd, &usb_keyboards, list ) {
555
556 /* Poll keyboard */
557 usb_poll ( kbd->bus );
558
559 /* Refill endpoints */
560 usb_refill ( &kbd->hid.in );
561
562 /* Update keyboard LEDs, if applicable */
563 if ( kbd->leds_changed ) {
564 usbkbd_set_leds ( kbd );
565 kbd->leds_changed = 0;
566 }
567 }
568
569 /* Check for a non-empty keyboard buffer */
570 list_for_each_entry ( kbd, &usb_keyboards, list ) {
571 fill = usbkbd_fill ( kbd );
572 if ( fill )
573 return fill;
574 }
575
576 return 0;
577 }
578
579 /** USB keyboard console */
580 struct console_driver usbkbd_console __console_driver = {
581 .getchar = usbkbd_getchar,
582 .iskey = usbkbd_iskey,
583 };
584