|
@@ -53,13 +53,14 @@ static LIST_HEAD ( usb_keyboards );
|
53
|
53
|
*
|
54
|
54
|
* @v keycode Keycode
|
55
|
55
|
* @v modifiers Modifiers
|
|
56
|
+ * @v leds LED state
|
56
|
57
|
* @ret key iPXE key
|
57
|
58
|
*
|
58
|
59
|
* Key codes are defined in the USB HID Usage Tables Keyboard/Keypad
|
59
|
60
|
* page.
|
60
|
61
|
*/
|
61
|
|
-static unsigned int usbkbd_map ( unsigned int keycode,
|
62
|
|
- unsigned int modifiers ) {
|
|
62
|
+static unsigned int usbkbd_map ( unsigned int keycode, unsigned int modifiers,
|
|
63
|
+ unsigned int leds ) {
|
63
|
64
|
unsigned int key;
|
64
|
65
|
|
65
|
66
|
if ( keycode < USBKBD_KEY_A ) {
|
|
@@ -70,7 +71,8 @@ static unsigned int usbkbd_map ( unsigned int keycode,
|
70
|
71
|
key = ( keycode - USBKBD_KEY_A + 'a' );
|
71
|
72
|
if ( modifiers & USBKBD_CTRL ) {
|
72
|
73
|
key -= ( 'a' - CTRL_A );
|
73
|
|
- } else if ( modifiers & USBKBD_SHIFT ) {
|
|
74
|
+ } else if ( ( modifiers & USBKBD_SHIFT ) ||
|
|
75
|
+ ( leds & USBKBD_LED_CAPS_LOCK ) ) {
|
74
|
76
|
key -= ( 'a' - 'A' );
|
75
|
77
|
}
|
76
|
78
|
} else if ( keycode <= USBKBD_KEY_0 ) {
|
|
@@ -100,7 +102,22 @@ static unsigned int usbkbd_map ( unsigned int keycode,
|
100
|
102
|
KEY_PPAGE, KEY_DC, KEY_END, KEY_NPAGE, KEY_RIGHT,
|
101
|
103
|
KEY_LEFT, KEY_DOWN, KEY_UP
|
102
|
104
|
};
|
103
|
|
- key = special[ keycode - USBKBD_KEY_CAPSLOCK ];
|
|
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
|
+ };
|
104
|
121
|
} else {
|
105
|
122
|
key = 0;
|
106
|
123
|
}
|
|
@@ -124,10 +141,25 @@ static unsigned int usbkbd_map ( unsigned int keycode,
|
124
|
141
|
*/
|
125
|
142
|
static void usbkbd_produce ( struct usb_keyboard *kbd, unsigned int keycode,
|
126
|
143
|
unsigned int modifiers ) {
|
|
144
|
+ unsigned int leds = 0;
|
127
|
145
|
unsigned int key;
|
128
|
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
|
+
|
129
|
161
|
/* Map to iPXE key */
|
130
|
|
- key = usbkbd_map ( keycode, modifiers );
|
|
162
|
+ key = usbkbd_map ( keycode, modifiers, kbd->leds );
|
131
|
163
|
|
132
|
164
|
/* Do nothing if this keycode has no corresponding iPXE key */
|
133
|
165
|
if ( ! key ) {
|
|
@@ -333,6 +365,37 @@ static struct usb_endpoint_driver_operations usbkbd_operations = {
|
333
|
365
|
.complete = usbkbd_complete,
|
334
|
366
|
};
|
335
|
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
|
+ */
|
|
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
|
+
|
336
|
399
|
/******************************************************************************
|
337
|
400
|
*
|
338
|
401
|
* USB interface
|
|
@@ -400,6 +463,9 @@ static int usbkbd_probe ( struct usb_function *func,
|
400
|
463
|
/* Add to list of USB keyboards */
|
401
|
464
|
list_add_tail ( &kbd->list, &usb_keyboards );
|
402
|
465
|
|
|
466
|
+ /* Set initial LED state */
|
|
467
|
+ usbkbd_set_leds ( kbd );
|
|
468
|
+
|
403
|
469
|
usb_func_set_drvdata ( func, kbd );
|
404
|
470
|
return 0;
|
405
|
471
|
|
|
@@ -484,10 +550,20 @@ static int usbkbd_iskey ( void ) {
|
484
|
550
|
struct usb_keyboard *kbd;
|
485
|
551
|
unsigned int fill;
|
486
|
552
|
|
487
|
|
- /* Poll all USB keyboards and refill endpoints */
|
|
553
|
+ /* Poll USB keyboards, refill endpoints, and set LEDs if applicable */
|
488
|
554
|
list_for_each_entry ( kbd, &usb_keyboards, list ) {
|
|
555
|
+
|
|
556
|
+ /* Poll keyboard */
|
489
|
557
|
usb_poll ( kbd->bus );
|
|
558
|
+
|
|
559
|
+ /* Refill endpoints */
|
490
|
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
|
+ }
|
491
|
567
|
}
|
492
|
568
|
|
493
|
569
|
/* Check for a non-empty keyboard buffer */
|