iPXE
Functions | Variables
usbkbd.c File Reference

USB keyboard driver. More...

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <ipxe/console.h>
#include <ipxe/keys.h>
#include <ipxe/usb.h>
#include "usbkbd.h"

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static LIST_HEAD (usb_keyboards)
 List of USB keyboards. More...
 
static unsigned int usbkbd_map (unsigned int keycode, unsigned int modifiers, unsigned int leds)
 Map USB keycode to iPXE key. More...
 
static void usbkbd_produce (struct usb_keyboard *kbd, unsigned int keycode, unsigned int modifiers)
 Insert keypress into keyboard buffer. More...
 
static unsigned int usbkbd_consume (struct usb_keyboard *kbd)
 Consume character from keyboard buffer. More...
 
static int usbkbd_has_keycode (struct usb_keyboard_report *report, unsigned int keycode)
 Check for presence of keycode in report. More...
 
static void usbkbd_report (struct usb_keyboard *kbd, struct usb_keyboard_report *new)
 Handle keyboard report. More...
 
static void usbkbd_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete interrupt transfer. More...
 
static int usbkbd_set_leds (struct usb_keyboard *kbd)
 Set keyboard LEDs. More...
 
static int usbkbd_probe (struct usb_function *func, struct usb_configuration_descriptor *config)
 Probe device. More...
 
static void usbkbd_remove (struct usb_function *func)
 Remove device. More...
 
static int usbkbd_getchar (void)
 Read a character from the console. More...
 
static int usbkbd_iskey (void)
 Check for available input. More...
 

Variables

static struct usb_endpoint_driver_operations usbkbd_operations
 Interrupt endpoint operations. More...
 
static struct usb_device_id usbkbd_ids []
 USB keyboard device IDs. More...
 
struct usb_driver usbkbd_driver __usb_driver
 USB keyboard driver. More...
 
struct console_driver usbkbd_console __console_driver
 USB keyboard console. More...
 

Detailed Description

USB keyboard driver.

Definition in file usbkbd.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ LIST_HEAD()

static LIST_HEAD ( usb_keyboards  )
static

List of USB keyboards.

◆ usbkbd_map()

static unsigned int usbkbd_map ( unsigned int  keycode,
unsigned int  modifiers,
unsigned int  leds 
)
static

Map USB keycode to iPXE key.

Parameters
keycodeKeycode
modifiersModifiers
ledsLED state
Return values
keyiPXE key

Key codes are defined in the USB HID Usage Tables Keyboard/Keypad page.

Definition at line 62 of file usbkbd.c.

63  {
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,
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[] = {
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 }
unsigned short uint16_t
Definition: stdint.h:11
#define KEY_F6
F6.
Definition: keys.h:76
#define KEY_F11
F11.
Definition: keys.h:81
#define KEY_F12
F12.
Definition: keys.h:82
#define KEY_F8
F8 (for PXE)
Definition: keys.h:78
#define KEY_NPAGE
Page down.
Definition: keys.h:74
#define KEY_HOME
Home.
Definition: keys.h:70
#define KEY_F9
F9.
Definition: keys.h:79
#define USBKBD_SHIFT
Either Shift key.
Definition: usbkbd.h:53
#define KEY_DOWN
Down arrow.
Definition: keys.h:66
#define KEY_UP
Up arrow.
Definition: keys.h:65
#define TAB
Definition: keys.h:46
#define ESC
Escape character.
Definition: ansiesc.h:92
int keypad(WINDOW *, bool)
#define USBKBD_CTRL
Either Ctrl key.
Definition: usbkbd.h:50
#define KEY_PPAGE
Page up.
Definition: keys.h:73
#define KEY_END
End.
Definition: keys.h:69
unsigned char uint8_t
Definition: stdint.h:10
#define CTRL_A
Definition: keys.h:18
#define LF
Definition: keys.h:47
#define KEY_DC
Delete.
Definition: keys.h:72
#define KEY_F10
F10.
Definition: keys.h:80
#define KEY_RIGHT
Right arrow.
Definition: keys.h:67
#define BACKSPACE
Definition: keys.h:45
#define KEY_F7
F7.
Definition: keys.h:77
#define KEY_LEFT
Left arrow.
Definition: keys.h:68
#define KEY_IC
Insert.
Definition: keys.h:71
union @376 key
Sense key.
Definition: scsi.h:18
#define KEY_F5
F5.
Definition: keys.h:75

References BACKSPACE, CTRL_A, ESC, key, KEY_DC, KEY_DOWN, KEY_END, KEY_F10, KEY_F11, KEY_F12, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_HOME, KEY_IC, KEY_LEFT, KEY_NPAGE, KEY_PPAGE, KEY_RIGHT, KEY_UP, keypad(), LF, TAB, USBKBD_CTRL, USBKBD_KEY_0, USBKBD_KEY_1, USBKBD_KEY_A, USBKBD_KEY_CAPS_LOCK, USBKBD_KEY_ENTER, USBKBD_KEY_MINUS, USBKBD_KEY_NUM_LOCK, USBKBD_KEY_PAD_1, USBKBD_KEY_PAD_DOT, USBKBD_KEY_PAD_ENTER, USBKBD_KEY_SLASH, USBKBD_KEY_SPACE, USBKBD_KEY_UP, USBKBD_KEY_Z, USBKBD_LED_CAPS_LOCK, USBKBD_LED_NUM_LOCK, and USBKBD_SHIFT.

Referenced by usbkbd_produce().

◆ usbkbd_produce()

static void usbkbd_produce ( struct usb_keyboard kbd,
unsigned int  keycode,
unsigned int  modifiers 
)
static

Insert keypress into keyboard buffer.

Parameters
kbdUSB keyboard
keycodeKeycode
modifiersModifiers

Definition at line 142 of file usbkbd.c.

143  {
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 }
unsigned int prod
Keyboard buffer producer counter.
Definition: usbkbd.h:146
static unsigned int usbkbd_map(unsigned int keycode, unsigned int modifiers, unsigned int leds)
Map USB keycode to iPXE key.
Definition: usbkbd.c:62
#define DBGC(...)
Definition: compiler.h:505
unsigned int key[USBKBD_BUFSIZE]
Keyboard buffer.
Definition: usbkbd.h:144
static unsigned int usbkbd_fill(struct usb_keyboard *kbd)
Calculate keyboard buffer fill level.
Definition: usbkbd.h:164
uint8_t leds
Keyboard LED state.
Definition: usbkbd.h:136
uint8_t leds_changed
Keyboard LEDs changed.
Definition: usbkbd.h:138
#define USBKBD_BUFSIZE
Keyboard buffer size.
Definition: usbkbd.h:114
const char * name
Name.
Definition: usbkbd.h:119
#define DBGC2(...)
Definition: compiler.h:522
union @376 key
Sense key.
Definition: scsi.h:18

References DBGC, DBGC2, key, usb_keyboard::key, usb_keyboard::leds, usb_keyboard::leds_changed, usb_keyboard::name, usb_keyboard::prod, USBKBD_BUFSIZE, usbkbd_fill(), USBKBD_KEY_CAPS_LOCK, USBKBD_KEY_NUM_LOCK, USBKBD_LED_CAPS_LOCK, USBKBD_LED_NUM_LOCK, and usbkbd_map().

Referenced by usbkbd_report().

◆ usbkbd_consume()

static unsigned int usbkbd_consume ( struct usb_keyboard kbd)
static

Consume character from keyboard buffer.

Parameters
kbdUSB keyboard
Return values
characterCharacter

Definition at line 189 of file usbkbd.c.

189  {
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 }
unsigned int subcons
Keyboard buffer sub-consumer counter.
Definition: usbkbd.h:154
#define sprintf(buf, fmt,...)
Write a formatted string to a buffer.
Definition: stdio.h:36
unsigned int key[USBKBD_BUFSIZE]
Keyboard buffer.
Definition: usbkbd.h:144
#define KEY_ANSI_TERMINATOR(key)
Definition: keys.h:62
static unsigned int usbkbd_fill(struct usb_keyboard *kbd)
Calculate keyboard buffer fill level.
Definition: usbkbd.h:164
#define KEY_MIN
Definition: keys.h:64
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
uint8_t * tmp
Definition: entropy.h:156
#define USBKBD_BUFSIZE
Keyboard buffer size.
Definition: usbkbd.h:114
const char * name
Name.
Definition: usbkbd.h:119
unsigned int cons
Keyboard buffer consumer counter.
Definition: usbkbd.h:148
#define KEY_ANSI_N(key)
Definition: keys.h:61
uint32_t len
Length.
Definition: ena.h:14
#define DBGC2(...)
Definition: compiler.h:522
union @376 key
Sense key.
Definition: scsi.h:18

References assert(), usb_keyboard::cons, DBGC2, key, usb_keyboard::key, KEY_ANSI_N, KEY_ANSI_TERMINATOR, KEY_MIN, len, usb_keyboard::name, sprintf, usb_keyboard::subcons, tmp, USBKBD_BUFSIZE, and usbkbd_fill().

Referenced by usbkbd_getchar().

◆ usbkbd_has_keycode()

static int usbkbd_has_keycode ( struct usb_keyboard_report report,
unsigned int  keycode 
)
static

Check for presence of keycode in report.

Parameters
reportKeyboard report
keycodeKeycode (must be non-zero)
Return values
has_keycodeKeycode is present in report

Definition at line 250 of file usbkbd.c.

251  {
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 }
uint8_t keycode[6]
Keycodes.
Definition: usbkbd.h:26

References usb_keyboard_report::keycode.

Referenced by usbkbd_report().

◆ usbkbd_report()

static void usbkbd_report ( struct usb_keyboard kbd,
struct usb_keyboard_report new 
)
static

Handle keyboard report.

Parameters
kbdUSB keyboard
newNew keyboard report

Definition at line 270 of file usbkbd.c.

271  {
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 }
static int usbkbd_has_keycode(struct usb_keyboard_report *report, unsigned int keycode)
Check for presence of keycode in report.
Definition: usbkbd.c:250
uint8_t keycode[6]
Keycodes.
Definition: usbkbd.h:26
static void usbkbd_produce(struct usb_keyboard *kbd, unsigned int keycode, unsigned int modifiers)
Insert keypress into keyboard buffer.
Definition: usbkbd.c:142
int old
Definition: bitops.h:64
A USB keyboard report.
Definition: usbkbd.h:20
void * memcpy(void *dest, const void *src, size_t len) __nonnull
uint8_t modifiers
Modifier keys.
Definition: usbkbd.h:22
unsigned int keycode
Most recently pressed non-modifier key (if any)
Definition: usbkbd.h:131
#define USBKBD_HOLDOFF
Keyboard auto-repeat hold-off (in units of USBKBD_IDLE_DURATION)
Definition: usbkbd.h:99
unsigned int holdoff
Autorepeat hold-off time (in number of completions reported)
Definition: usbkbd.h:133
const char * name
Name.
Definition: usbkbd.h:119
struct usb_keyboard_report report
Most recent keyboard report.
Definition: usbkbd.h:129
#define DBGC2(...)
Definition: compiler.h:522

References DBGC2, usb_keyboard::holdoff, usb_keyboard_report::keycode, usb_keyboard::keycode, memcpy(), usb_keyboard::name, old, usb_keyboard::report, usbkbd_has_keycode(), USBKBD_HOLDOFF, and usbkbd_produce().

Referenced by usbkbd_complete().

◆ usbkbd_complete()

static void usbkbd_complete ( struct usb_endpoint ep,
struct io_buffer iobuf,
int  rc 
)
static

Complete interrupt transfer.

Parameters
epUSB endpoint
iobufI/O buffer
rcCompletion status code

Definition at line 330 of file usbkbd.c.

331  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct usb_endpoint in
Interrupt IN endpoint.
Definition: usbhid.h:55
#define DBGC(...)
Definition: compiler.h:505
int open
Endpoint is open.
Definition: usb.h:404
A USB keyboard report.
Definition: usbkbd.h:20
static void usb_recycle(struct usb_endpoint *ep, struct io_buffer *iobuf)
Recycle I/O buffer.
Definition: usb.h:617
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
#define DBGC_HDA(...)
Definition: compiler.h:506
static void usbkbd_report(struct usb_keyboard *kbd, struct usb_keyboard_report *new)
Handle keyboard report.
Definition: usbkbd.c:270
struct usb_hid hid
USB human interface device.
Definition: usbkbd.h:126
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
const char * name
Name.
Definition: usbkbd.h:119
A USB keyboard device.
Definition: usbkbd.h:117
void * data
Start of data.
Definition: iobuf.h:44

References container_of, io_buffer::data, DBGC, DBGC_HDA, usb_keyboard::hid, usb_hid::in, iob_len(), usb_keyboard::name, usb_endpoint::open, rc, strerror(), usb_recycle(), and usbkbd_report().

◆ usbkbd_set_leds()

static int usbkbd_set_leds ( struct usb_keyboard kbd)
static

Set keyboard LEDs.

Parameters
kbdUSB keyboard
Return values
rcReturn status code

Definition at line 381 of file usbkbd.c.

381  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
uint8_t interface[0]
List of interface numbers.
Definition: usb.h:680
#define DBGC(...)
Definition: compiler.h:505
uint8_t leds
Keyboard LED state.
Definition: usbkbd.h:136
struct usb_hid hid
USB human interface device.
Definition: usbkbd.h:126
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
#define USBHID_REPORT_OUTPUT
Output report type.
Definition: usbhid.h:45
struct usb_device * usb
USB device.
Definition: usb.h:661
const char * name
Name.
Definition: usbkbd.h:119
#define DBGC2(...)
Definition: compiler.h:522
static int usbhid_set_report(struct usb_device *usb, unsigned int interface, unsigned int type, unsigned int report, void *data, size_t len)
Set report.
Definition: usbhid.h:126
struct usb_function * func
USB function.
Definition: usbhid.h:53
A USB function.
Definition: usb.h:657

References DBGC, DBGC2, usb_hid::func, usb_keyboard::hid, usb_function::interface, usb_keyboard::leds, usb_keyboard::name, rc, strerror(), usb_function::usb, USBHID_REPORT_OUTPUT, and usbhid_set_report().

Referenced by usbkbd_iskey(), and usbkbd_probe().

◆ usbkbd_probe()

static int usbkbd_probe ( struct usb_function func,
struct usb_configuration_descriptor config 
)
static

Probe device.

Parameters
funcUSB function
configConfiguration descriptor
Return values
rcReturn status code

Definition at line 413 of file usbkbd.c.

414  {
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 ),
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
uint8_t interface[0]
List of interface numbers.
Definition: usb.h:680
const char * name
Name.
Definition: usb.h:659
struct list_head list
List of all USB keyboards.
Definition: usbkbd.h:121
struct usb_endpoint in
Interrupt IN endpoint.
Definition: usbhid.h:55
static struct usb_endpoint_driver_operations usbkbd_operations
Interrupt endpoint operations.
Definition: usbkbd.c:364
#define DBGC(...)
Definition: compiler.h:505
int usbhid_describe(struct usb_hid *hid, struct usb_configuration_descriptor *config)
Describe USB human interface device.
Definition: usbhid.c:120
#define USBKBD_INTR_MAX_FILL
Interrupt endpoint maximum fill level.
Definition: usbkbd.h:108
void usbhid_close(struct usb_hid *hid)
Close USB human interface device.
Definition: usbhid.c:83
struct usb_bus * bus
USB bus.
Definition: usbkbd.h:124
#define ENOMEM
Not enough space.
Definition: errno.h:534
static int usbhid_set_idle(struct usb_device *usb, unsigned int interface, unsigned int report, unsigned int duration)
Set idle time.
Definition: usbhid.h:106
struct usb_port * port
USB port.
Definition: usb.h:710
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
static void usb_refill_init(struct usb_endpoint *ep, size_t reserve, size_t len, unsigned int max)
Initialise USB endpoint refill.
Definition: usb.h:601
struct usb_hid hid
USB human interface device.
Definition: usbkbd.h:126
static void usb_func_set_drvdata(struct usb_function *func, void *priv)
Set USB function driver private data.
Definition: usb.h:690
A USB device.
Definition: usb.h:706
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
static int usbhid_set_protocol(struct usb_device *usb, unsigned int interface, unsigned int protocol)
Set protocol.
Definition: usbhid.h:89
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
struct usb_device * usb
USB device.
Definition: usb.h:661
const char * name
Name.
Definition: usbkbd.h:119
const char * usb_endpoint_name(struct usb_endpoint *ep)
Get USB endpoint name (for debugging)
Definition: usb.c:220
size_t mtu
Maximum transfer size.
Definition: usb.h:397
A USB keyboard device.
Definition: usbkbd.h:117
struct usb_keyboard_report report
Most recent keyboard report.
Definition: usbkbd.h:129
static int usbkbd_set_leds(struct usb_keyboard *kbd)
Set keyboard LEDs.
Definition: usbkbd.c:381
struct usb_hub * hub
USB hub.
Definition: usb.h:798
static void usbhid_init(struct usb_hid *hid, struct usb_function *func, struct usb_endpoint_driver_operations *in, struct usb_endpoint_driver_operations *out)
Initialise USB human interface device.
Definition: usbhid.h:69
#define USBHID_PROTOCOL_BOOT
Boot protocol.
Definition: usbhid.h:26
struct usb_bus * bus
USB bus.
Definition: usb.h:828
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
int usbhid_open(struct usb_hid *hid)
Open USB human interface device.
Definition: usbhid.c:43
#define USBKBD_IDLE_DURATION
Keyboard idle duration (in 4ms units)
Definition: usbkbd.h:92

References usb_keyboard::bus, usb_hub::bus, DBGC, ENOMEM, free, usb_keyboard::hid, usb_port::hub, usb_hid::in, usb_function::interface, usb_keyboard::list, list_add_tail, usb_endpoint::mtu, usb_keyboard::name, usb_function::name, NULL, usb_device::port, rc, usb_keyboard::report, strerror(), usb_function::usb, usb_endpoint_name(), usb_func_set_drvdata(), usb_refill_init(), usbhid_close(), usbhid_describe(), usbhid_init(), usbhid_open(), USBHID_PROTOCOL_BOOT, usbhid_set_idle(), usbhid_set_protocol(), USBKBD_IDLE_DURATION, USBKBD_INTR_MAX_FILL, usbkbd_operations, usbkbd_set_leds(), and zalloc().

◆ usbkbd_remove()

static void usbkbd_remove ( struct usb_function func)
static

Remove device.

Parameters
funcUSB function

Definition at line 487 of file usbkbd.c.

487  {
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 }
static void * usb_func_get_drvdata(struct usb_function *func)
Get USB function driver private data.
Definition: usb.h:701
struct list_head list
List of all USB keyboards.
Definition: usbkbd.h:121
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
void usbhid_close(struct usb_hid *hid)
Close USB human interface device.
Definition: usbhid.c:83
struct usb_hid hid
USB human interface device.
Definition: usbkbd.h:126
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
A USB keyboard device.
Definition: usbkbd.h:117

References free, usb_keyboard::hid, usb_keyboard::list, list_del, usb_func_get_drvdata(), and usbhid_close().

◆ usbkbd_getchar()

static int usbkbd_getchar ( void  )
static

Read a character from the console.

Return values
characterCharacter read

Definition at line 532 of file usbkbd.c.

532  {
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 }
struct list_head list
List of all USB keyboards.
Definition: usbkbd.h:121
static unsigned int usbkbd_fill(struct usb_keyboard *kbd)
Calculate keyboard buffer fill level.
Definition: usbkbd.h:164
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
A USB keyboard device.
Definition: usbkbd.h:117
static unsigned int usbkbd_consume(struct usb_keyboard *kbd)
Consume character from keyboard buffer.
Definition: usbkbd.c:189

References usb_keyboard::list, list_for_each_entry, usbkbd_consume(), and usbkbd_fill().

◆ usbkbd_iskey()

static int usbkbd_iskey ( void  )
static

Check for available input.

Return values
is_availableInput is available

Definition at line 549 of file usbkbd.c.

549  {
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 }
struct list_head list
List of all USB keyboards.
Definition: usbkbd.h:121
struct usb_endpoint in
Interrupt IN endpoint.
Definition: usbhid.h:55
static unsigned int usbkbd_fill(struct usb_keyboard *kbd)
Calculate keyboard buffer fill level.
Definition: usbkbd.h:164
int usb_refill(struct usb_endpoint *ep)
Refill endpoint.
Definition: usb.c:642
struct usb_bus * bus
USB bus.
Definition: usbkbd.h:124
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:420
struct usb_hid hid
USB human interface device.
Definition: usbkbd.h:126
static void usb_poll(struct usb_bus *bus)
Poll USB bus.
Definition: usb.h:1049
uint8_t leds_changed
Keyboard LEDs changed.
Definition: usbkbd.h:138
A USB keyboard device.
Definition: usbkbd.h:117
static int usbkbd_set_leds(struct usb_keyboard *kbd)
Set keyboard LEDs.
Definition: usbkbd.c:381
uint8_t fill
Length pair.
Definition: deflate.h:12

References usb_keyboard::bus, fill, usb_keyboard::hid, usb_hid::in, usb_keyboard::leds_changed, usb_keyboard::list, list_for_each_entry, usb_poll(), usb_refill(), usbkbd_fill(), and usbkbd_set_leds().

Variable Documentation

◆ usbkbd_operations

struct usb_endpoint_driver_operations usbkbd_operations
static
Initial value:
= {
.complete = usbkbd_complete,
}
static void usbkbd_complete(struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
Complete interrupt transfer.
Definition: usbkbd.c:330

Interrupt endpoint operations.

Definition at line 364 of file usbkbd.c.

Referenced by usbkbd_probe().

◆ usbkbd_ids

struct usb_device_id usbkbd_ids[]
static
Initial value:
= {
{
.name = "kbd",
.vendor = USB_ANY_ID,
.product = USB_ANY_ID,
},
}
#define USB_ANY_ID
Match-anything ID.
Definition: usb.h:1329

USB keyboard device IDs.

Definition at line 501 of file usbkbd.c.

◆ __usb_driver

struct usb_driver usbkbd_driver __usb_driver
Initial value:
= {
.ids = usbkbd_ids,
.id_count = ( sizeof ( usbkbd_ids ) / sizeof ( usbkbd_ids[0] ) ),
.score = USB_SCORE_NORMAL,
.probe = usbkbd_probe,
.remove = usbkbd_remove,
}
#define USB_SUBCLASS_HID_BOOT
Subclass code for boot devices.
Definition: usbhid.h:18
static struct usb_device_id usbkbd_ids[]
USB keyboard device IDs.
Definition: usbkbd.c:501
static int usbkbd_probe(struct usb_function *func, struct usb_configuration_descriptor *config)
Probe device.
Definition: usbkbd.c:413
#define USBKBD_PROTOCOL
Keyboard protocol.
Definition: usbkbd.h:17
#define USB_CLASS_ID(base, subclass, protocol)
Construct USB class ID.
Definition: usb.h:1345
Normal driver.
Definition: usb.h:1406
static void usbkbd_remove(struct usb_function *func)
Remove device.
Definition: usbkbd.c:487
#define USB_CLASS_HID
Class code for human interface devices.
Definition: usbhid.h:15

USB keyboard driver.

Definition at line 510 of file usbkbd.c.

◆ __console_driver

struct console_driver usbkbd_console __console_driver
Initial value:
= {
.getchar = usbkbd_getchar,
.iskey = usbkbd_iskey,
}
static int usbkbd_getchar(void)
Read a character from the console.
Definition: usbkbd.c:532
static int usbkbd_iskey(void)
Check for available input.
Definition: usbkbd.c:549

USB keyboard console.

Definition at line 580 of file usbkbd.c.