2 * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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
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.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL
);
31 #include <ipxe/console.h>
32 #include <ipxe/keys.h>
33 #include <ipxe/keymap.h>
43 /** List of USB keyboards */
44 static LIST_HEAD ( usb_keyboards
);
46 /******************************************************************************
50 ******************************************************************************
54 * Map USB keycode to iPXE key
57 * @v modifiers Modifiers
61 * Key codes are defined in the USB HID Usage Tables Keyboard/Keypad
64 static unsigned int usbkbd_map ( unsigned int keycode
, unsigned int modifiers
,
68 if ( keycode
< USBKBD_KEY_A
) {
71 } else if ( keycode
<= USBKBD_KEY_Z
) {
73 key
= ( keycode
- USBKBD_KEY_A
+ 'a' );
74 if ( modifiers
& USBKBD_SHIFT
) {
77 } else if ( keycode
<= USBKBD_KEY_0
) {
79 if ( modifiers
& USBKBD_SHIFT
) {
80 key
= "!@#$%^&*()" [ keycode
- USBKBD_KEY_1
];
82 key
= ( ( ( keycode
- USBKBD_KEY_1
+ 1 ) % 10 ) + '0' );
84 } else if ( keycode
<= USBKBD_KEY_SPACE
) {
85 /* Unmodifiable keys */
86 static const uint8_t unmodifable
[] =
87 { LF
, ESC
, BACKSPACE
, TAB
, ' ' };
88 key
= unmodifable
[ keycode
- USBKBD_KEY_ENTER
];
89 } else if ( keycode
<= USBKBD_KEY_SLASH
) {
90 /* Punctuation keys */
91 if ( modifiers
& USBKBD_SHIFT
) {
92 key
= "_+{}|~:\"~<>?" [ keycode
- USBKBD_KEY_MINUS
];
94 key
= "-=[]\\#;'`,./" [ keycode
- USBKBD_KEY_MINUS
];
96 } else if ( keycode
<= USBKBD_KEY_UP
) {
98 static const uint16_t special
[] = {
99 0, 0, 0, 0, 0, KEY_F5
, KEY_F6
, KEY_F7
, KEY_F8
, KEY_F9
,
100 KEY_F10
, KEY_F11
, KEY_F12
, 0, 0, 0, KEY_IC
, KEY_HOME
,
101 KEY_PPAGE
, KEY_DC
, KEY_END
, KEY_NPAGE
, KEY_RIGHT
,
102 KEY_LEFT
, KEY_DOWN
, KEY_UP
104 key
= special
[ keycode
- USBKBD_KEY_CAPS_LOCK
];
105 } else if ( keycode
<= USBKBD_KEY_PAD_ENTER
) {
106 /* Keypad (unaffected by Num Lock) */
107 key
= "\0/*-+\n" [ keycode
- USBKBD_KEY_NUM_LOCK
];
108 } else if ( keycode
<= USBKBD_KEY_PAD_DOT
) {
109 /* Keypad (affected by Num Lock) */
110 if ( leds
& USBKBD_LED_NUM_LOCK
) {
111 key
= "1234567890." [ keycode
- USBKBD_KEY_PAD_1
];
113 static const uint16_t keypad
[] = {
114 KEY_END
, KEY_DOWN
, KEY_NPAGE
, KEY_LEFT
, 0,
115 KEY_RIGHT
, KEY_HOME
, KEY_UP
, KEY_PPAGE
,
118 key
= keypad
[ keycode
- USBKBD_KEY_PAD_1
];
120 } else if ( keycode
== USBKBD_KEY_NON_US
) {
122 key
= ( ( modifiers
& USBKBD_SHIFT
) ?
123 ( KEYMAP_PSEUDO
| '|' ) : ( KEYMAP_PSEUDO
| '\\' ) );
128 /* Remap key if applicable */
129 if ( ( keycode
< USBKBD_KEY_CAPS_LOCK
) ||
130 ( keycode
== USBKBD_KEY_NON_US
) ) {
132 /* Apply modifiers */
133 if ( modifiers
& USBKBD_CTRL
)
135 if ( modifiers
& USBKBD_ALT_RIGHT
)
137 if ( leds
& USBKBD_LED_CAPS_LOCK
)
138 key
|= KEYMAP_CAPSLOCK
;
141 key
= key_remap ( key
);
147 /******************************************************************************
151 ******************************************************************************
155 * Insert keypress into keyboard buffer
157 * @v kbd USB keyboard
159 * @v modifiers Modifiers
161 static void usbkbd_produce ( struct usb_keyboard
*kbd
, unsigned int keycode
,
162 unsigned int modifiers
) {
163 unsigned int leds
= 0;
166 /* Check for LED-modifying keys */
167 if ( keycode
== USBKBD_KEY_CAPS_LOCK
) {
168 leds
= USBKBD_LED_CAPS_LOCK
;
169 } else if ( keycode
== USBKBD_KEY_NUM_LOCK
) {
170 leds
= USBKBD_LED_NUM_LOCK
;
173 /* Handle LED-modifying keys */
176 kbd
->leds_changed
= 1;
180 /* Map to iPXE key */
181 key
= usbkbd_map ( keycode
, modifiers
, kbd
->leds
);
183 /* Do nothing if this keycode has no corresponding iPXE key */
185 DBGC ( kbd
, "KBD %s has no key for keycode %#02x:%#02x\n",
186 kbd
->name
, modifiers
, keycode
);
190 /* Check for buffer overrun */
191 if ( usbkbd_fill ( kbd
) >= USBKBD_BUFSIZE
) {
192 DBGC ( kbd
, "KBD %s buffer overrun (key %#02x)\n",
197 /* Insert into buffer */
198 kbd
->key
[ ( kbd
->prod
++ ) % USBKBD_BUFSIZE
] = key
;
199 DBGC2 ( kbd
, "KBD %s key %#02x produced\n", kbd
->name
, key
);
203 * Consume character from keyboard buffer
205 * @v kbd USB keyboard
206 * @ret character Character
208 static unsigned int usbkbd_consume ( struct usb_keyboard
*kbd
) {
209 static char buf
[] = "\x1b[xx~";
212 unsigned int character
;
217 assert ( usbkbd_fill ( kbd
) > 0 );
219 /* Get current keypress */
220 key
= kbd
->key
[ kbd
->cons
% USBKBD_BUFSIZE
];
222 /* If this is a straightforward key, just consume and return it */
223 if ( key
< KEY_MIN
) {
225 DBGC2 ( kbd
, "KBD %s key %#02x consumed\n", kbd
->name
, key
);
229 /* Construct ANSI sequence */
230 ansi_n
= KEY_ANSI_N ( key
);
232 tmp
+= sprintf ( tmp
, "%d", ansi_n
);
233 *(tmp
++) = KEY_ANSI_TERMINATOR ( key
);
236 assert ( len
< sizeof ( buf
) );
237 if ( kbd
->subcons
== 0 ) {
238 DBGC2 ( kbd
, "KBD %s key %#02x consumed as ^[%s\n",
239 kbd
->name
, key
, &buf
[1] );
242 /* Extract character from ANSI sequence */
243 assert ( kbd
->subcons
< len
);
244 character
= buf
[ kbd
->subcons
++ ];
246 /* Consume key if applicable */
247 if ( kbd
->subcons
== len
) {
255 /******************************************************************************
259 ******************************************************************************
263 * Check for presence of keycode in report
265 * @v report Keyboard report
266 * @v keycode Keycode (must be non-zero)
267 * @ret has_keycode Keycode is present in report
269 static int usbkbd_has_keycode ( struct usb_keyboard_report
*report
,
270 unsigned int keycode
) {
273 /* Check for keycode */
274 for ( i
= 0 ; i
< ( sizeof ( report
->keycode
) /
275 sizeof ( report
->keycode
[0] ) ) ; i
++ ) {
276 if ( report
->keycode
[i
] == keycode
)
284 * Handle keyboard report
286 * @v kbd USB keyboard
287 * @v new New keyboard report
289 static void usbkbd_report ( struct usb_keyboard
*kbd
,
290 struct usb_keyboard_report
*new ) {
291 struct usb_keyboard_report
*old
= &kbd
->report
;
292 unsigned int keycode
;
295 /* Check if current key has been released */
296 if ( kbd
->keycode
&& ! usbkbd_has_keycode ( new, kbd
->keycode
) ) {
297 DBGC2 ( kbd
, "KBD %s keycode %#02x released\n",
298 kbd
->name
, kbd
->keycode
);
302 /* Decrement auto-repeat hold-off timer, if applicable */
306 /* Check if a new key has been pressed */
307 for ( i
= 0 ; i
< ( sizeof ( new->keycode
) /
308 sizeof ( new->keycode
[0] ) ) ; i
++ ) {
310 /* Ignore keys present in the previous report */
311 keycode
= new->keycode
[i
];
312 if ( ( keycode
== 0 ) || usbkbd_has_keycode ( old
, keycode
) )
314 DBGC2 ( kbd
, "KBD %s keycode %#02x pressed\n",
315 kbd
->name
, keycode
);
317 /* Insert keypress into keyboard buffer */
318 usbkbd_produce ( kbd
, keycode
, new->modifiers
);
320 /* Record as most recent keycode */
321 kbd
->keycode
= keycode
;
323 /* Start auto-repeat hold-off timer */
324 kbd
->holdoff
= USBKBD_HOLDOFF
;
327 /* Insert auto-repeated keypress into keyboard buffer, if applicable */
328 if ( kbd
->keycode
&& ! kbd
->holdoff
)
329 usbkbd_produce ( kbd
, kbd
->keycode
, new->modifiers
);
332 memcpy ( old
, new, sizeof ( *old
) );
335 /******************************************************************************
339 ******************************************************************************
343 * Complete interrupt transfer
346 * @v iobuf I/O buffer
347 * @v rc Completion status code
349 static void usbkbd_complete ( struct usb_endpoint
*ep
,
350 struct io_buffer
*iobuf
, int rc
) {
351 struct usb_keyboard
*kbd
= container_of ( ep
, struct usb_keyboard
,
353 struct usb_keyboard_report
*report
;
355 /* Ignore packets cancelled when the endpoint closes */
359 /* Ignore packets with errors */
361 DBGC ( kbd
, "KBD %s interrupt IN failed: %s\n",
362 kbd
->name
, strerror ( rc
) );
366 /* Ignore underlength packets */
367 if ( iob_len ( iobuf
) < sizeof ( *report
) ) {
368 DBGC ( kbd
, "KBD %s underlength report:\n", kbd
->name
);
369 DBGC_HDA ( kbd
, 0, iobuf
->data
, iob_len ( iobuf
) );
372 report
= iobuf
->data
;
374 /* Handle keyboard report */
375 usbkbd_report ( kbd
, report
);
378 /* Recycle I/O buffer */
379 usb_recycle ( &kbd
->hid
.in
, iobuf
);
382 /** Interrupt endpoint operations */
383 static struct usb_endpoint_driver_operations usbkbd_operations
= {
384 .complete
= usbkbd_complete
,
387 /******************************************************************************
391 ******************************************************************************
397 * @v kbd USB keyboard
398 * @ret rc Return status code
400 static int usbkbd_set_leds ( struct usb_keyboard
*kbd
) {
401 struct usb_function
*func
= kbd
->hid
.func
;
404 DBGC2 ( kbd
, "KBD %s setting LEDs to %#02x\n", kbd
->name
, kbd
->leds
);
406 /* Set keyboard LEDs */
407 if ( ( rc
= usbhid_set_report ( func
->usb
, func
->interface
[0],
408 USBHID_REPORT_OUTPUT
, 0, &kbd
->leds
,
409 sizeof ( kbd
->leds
) ) ) != 0 ) {
410 DBGC ( kbd
, "KBD %s could not set LEDs to %#02x: %s\n",
411 kbd
->name
, kbd
->leds
, strerror ( rc
) );
418 /******************************************************************************
422 ******************************************************************************
428 * @v func USB function
429 * @v config Configuration descriptor
430 * @ret rc Return status code
432 static int usbkbd_probe ( struct usb_function
*func
,
433 struct usb_configuration_descriptor
*config
) {
434 struct usb_device
*usb
= func
->usb
;
435 struct usb_keyboard
*kbd
;
438 /* Allocate and initialise structure */
439 kbd
= zalloc ( sizeof ( *kbd
) );
444 kbd
->name
= func
->name
;
445 kbd
->bus
= usb
->port
->hub
->bus
;
446 usbhid_init ( &kbd
->hid
, func
, &usbkbd_operations
, NULL
);
447 usb_refill_init ( &kbd
->hid
.in
, 0, sizeof ( kbd
->report
),
448 USBKBD_INTR_MAX_FILL
);
450 /* Describe USB human interface device */
451 if ( ( rc
= usbhid_describe ( &kbd
->hid
, config
) ) != 0 ) {
452 DBGC ( kbd
, "KBD %s could not describe: %s\n",
453 kbd
->name
, strerror ( rc
) );
456 DBGC ( kbd
, "KBD %s using %s (len %zd)\n",
457 kbd
->name
, usb_endpoint_name ( &kbd
->hid
.in
), kbd
->hid
.in
.mtu
);
459 /* Set boot protocol */
460 if ( ( rc
= usbhid_set_protocol ( usb
, func
->interface
[0],
461 USBHID_PROTOCOL_BOOT
) ) != 0 ) {
462 DBGC ( kbd
, "KBD %s could not set boot protocol: %s\n",
463 kbd
->name
, strerror ( rc
) );
464 goto err_set_protocol
;
468 if ( ( rc
= usbhid_set_idle ( usb
, func
->interface
[0], 0,
469 USBKBD_IDLE_DURATION
) ) != 0 ) {
470 DBGC ( kbd
, "KBD %s could not set idle time: %s\n",
471 kbd
->name
, strerror ( rc
) );
475 /* Open USB human interface device */
476 if ( ( rc
= usbhid_open ( &kbd
->hid
) ) != 0 ) {
477 DBGC ( kbd
, "KBD %s could not open: %s\n",
478 kbd
->name
, strerror ( rc
) );
482 /* Add to list of USB keyboards */
483 list_add_tail ( &kbd
->list
, &usb_keyboards
);
485 /* Set initial LED state */
486 usbkbd_set_leds ( kbd
);
488 usb_func_set_drvdata ( func
, kbd
);
491 usbhid_close ( &kbd
->hid
);
504 * @v func USB function
506 static void usbkbd_remove ( struct usb_function
*func
) {
507 struct usb_keyboard
*kbd
= usb_func_get_drvdata ( func
);
509 /* Remove from list of USB keyboards */
510 list_del ( &kbd
->list
);
512 /* Close USB human interface device */
513 usbhid_close ( &kbd
->hid
);
519 /** USB keyboard device IDs */
520 static struct usb_device_id usbkbd_ids
[] = {
523 .vendor
= USB_ANY_ID
,
524 .product
= USB_ANY_ID
,
528 /** USB keyboard driver */
529 struct usb_driver usbkbd_driver __usb_driver
= {
531 .id_count
= ( sizeof ( usbkbd_ids
) / sizeof ( usbkbd_ids
[0] ) ),
532 .class = USB_CLASS_ID ( USB_CLASS_HID
, USB_SUBCLASS_HID_BOOT
,
534 .score
= USB_SCORE_NORMAL
,
535 .probe
= usbkbd_probe
,
536 .remove
= usbkbd_remove
,
539 /******************************************************************************
543 ******************************************************************************
547 * Read a character from the console
549 * @ret character Character read
551 static int usbkbd_getchar ( void ) {
552 struct usb_keyboard
*kbd
;
554 /* Consume first available key */
555 list_for_each_entry ( kbd
, &usb_keyboards
, list
) {
556 if ( usbkbd_fill ( kbd
) )
557 return usbkbd_consume ( kbd
);
564 * Check for available input
566 * @ret is_available Input is available
568 static int usbkbd_iskey ( void ) {
569 struct usb_keyboard
*kbd
;
572 /* Poll USB keyboards, refill endpoints, and set LEDs if applicable */
573 list_for_each_entry ( kbd
, &usb_keyboards
, list
) {
576 usb_poll ( kbd
->bus
);
578 /* Refill endpoints */
579 usb_refill ( &kbd
->hid
.in
);
581 /* Update keyboard LEDs, if applicable */
582 if ( kbd
->leds_changed
) {
583 usbkbd_set_leds ( kbd
);
584 kbd
->leds_changed
= 0;
588 /* Check for a non-empty keyboard buffer */
589 list_for_each_entry ( kbd
, &usb_keyboards
, list
) {
590 fill
= usbkbd_fill ( kbd
);
598 /** USB keyboard console */
599 struct console_driver usbkbd_console __console_driver
= {
600 .getchar
= usbkbd_getchar
,
601 .iskey
= usbkbd_iskey
,