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