Commit 47b2d338d982c9e26b2af6b51c1cc0da7cbd2b60

Authored by balrog
1 parent 07cf0ba0

Add USB HID keyboard.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2996 c046a42c-6fe2-441c-8c8c-71466251a162
hw/usb-hid.c
... ... @@ -2,6 +2,7 @@
2 2 * QEMU USB HID devices
3 3 *
4 4 * Copyright (c) 2005 Fabrice Bellard
  5 + * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com)
5 6 *
6 7 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 8 * of this software and associated documentation files (the "Software"), to deal
... ... @@ -27,21 +28,44 @@
27 28 #define GET_REPORT 0xa101
28 29 #define GET_IDLE 0xa102
29 30 #define GET_PROTOCOL 0xa103
  31 +#define SET_REPORT 0x2109
30 32 #define SET_IDLE 0x210a
31 33 #define SET_PROTOCOL 0x210b
32 34  
33   -#define USB_MOUSE 1
34   -#define USB_TABLET 2
  35 +/* HID descriptor types */
  36 +#define USB_DT_HID 0x21
  37 +#define USB_DT_REPORT 0x22
  38 +#define USB_DT_PHY 0x23
  39 +
  40 +#define USB_MOUSE 1
  41 +#define USB_TABLET 2
  42 +#define USB_KEYBOARD 3
35 43  
36 44 typedef struct USBMouseState {
37   - USBDevice dev;
38 45 int dx, dy, dz, buttons_state;
39 46 int x, y;
40   - int kind;
41 47 int mouse_grabbed;
42 48 QEMUPutMouseEntry *eh_entry;
43 49 } USBMouseState;
44 50  
  51 +typedef struct USBKeyboardState {
  52 + uint16_t modifiers;
  53 + uint8_t leds;
  54 + uint8_t key[16];
  55 + int keys;
  56 +} USBKeyboardState;
  57 +
  58 +typedef struct USBHIDState {
  59 + USBDevice dev;
  60 + union {
  61 + USBMouseState ptr;
  62 + USBKeyboardState kbd;
  63 + };
  64 + int kind;
  65 + int protocol;
  66 + int idle;
  67 +} USBHIDState;
  68 +
45 69 /* mostly the same values as the Bochs USB Mouse device */
46 70 static const uint8_t qemu_mouse_dev_descriptor[] = {
47 71 0x12, /* u8 bLength; */
... ... @@ -98,7 +122,7 @@ static const uint8_t qemu_mouse_config_descriptor[] = {
98 122 0x03, /* u8 if_bInterfaceClass; */
99 123 0x01, /* u8 if_bInterfaceSubClass; */
100 124 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
101   - 0x05, /* u8 if_iInterface; */
  125 + 0x07, /* u8 if_iInterface; */
102 126  
103 127 /* HID descriptor */
104 128 0x09, /* u8 bLength; */
... ... @@ -125,7 +149,7 @@ static const uint8_t qemu_tablet_config_descriptor[] = {
125 149 0x22, 0x00, /* u16 wTotalLength; */
126 150 0x01, /* u8 bNumInterfaces; (1) */
127 151 0x01, /* u8 bConfigurationValue; */
128   - 0x04, /* u8 iConfiguration; */
  152 + 0x05, /* u8 iConfiguration; */
129 153 0xa0, /* u8 bmAttributes;
130 154 Bit 7: must be set,
131 155 6: Self-powered,
... ... @@ -153,7 +177,7 @@ static const uint8_t qemu_tablet_config_descriptor[] = {
153 177 0x03, /* u8 if_bInterfaceClass; */
154 178 0x01, /* u8 if_bInterfaceSubClass; */
155 179 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
156   - 0x05, /* u8 if_iInterface; */
  180 + 0x07, /* u8 if_iInterface; */
157 181  
158 182 /* HID descriptor */
159 183 0x09, /* u8 bLength; */
... ... @@ -173,6 +197,61 @@ static const uint8_t qemu_tablet_config_descriptor[] = {
173 197 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
174 198 };
175 199  
  200 +static const uint8_t qemu_keyboard_config_descriptor[] = {
  201 + /* one configuration */
  202 + 0x09, /* u8 bLength; */
  203 + USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */
  204 + 0x22, 0x00, /* u16 wTotalLength; */
  205 + 0x01, /* u8 bNumInterfaces; (1) */
  206 + 0x01, /* u8 bConfigurationValue; */
  207 + 0x06, /* u8 iConfiguration; */
  208 + 0xa0, /* u8 bmAttributes;
  209 + Bit 7: must be set,
  210 + 6: Self-powered,
  211 + 5: Remote wakeup,
  212 + 4..0: resvd */
  213 + 0x32, /* u8 MaxPower; */
  214 +
  215 + /* USB 1.1:
  216 + * USB 2.0, single TT organization (mandatory):
  217 + * one interface, protocol 0
  218 + *
  219 + * USB 2.0, multiple TT organization (optional):
  220 + * two interfaces, protocols 1 (like single TT)
  221 + * and 2 (multiple TT mode) ... config is
  222 + * sometimes settable
  223 + * NOT IMPLEMENTED
  224 + */
  225 +
  226 + /* one interface */
  227 + 0x09, /* u8 if_bLength; */
  228 + USB_DT_INTERFACE, /* u8 if_bDescriptorType; Interface */
  229 + 0x00, /* u8 if_bInterfaceNumber; */
  230 + 0x00, /* u8 if_bAlternateSetting; */
  231 + 0x01, /* u8 if_bNumEndpoints; */
  232 + 0x03, /* u8 if_bInterfaceClass; HID */
  233 + 0x01, /* u8 if_bInterfaceSubClass; Boot */
  234 + 0x01, /* u8 if_bInterfaceProtocol; Keyboard */
  235 + 0x07, /* u8 if_iInterface; */
  236 +
  237 + /* HID descriptor */
  238 + 0x09, /* u8 bLength; */
  239 + USB_DT_HID, /* u8 bDescriptorType; */
  240 + 0x11, 0x01, /* u16 HID_class */
  241 + 0x00, /* u8 country_code */
  242 + 0x01, /* u8 num_descriptors */
  243 + USB_DT_REPORT, /* u8 type; Report */
  244 + 0x3f, 0x00, /* u16 len */
  245 +
  246 + /* one endpoint (status change endpoint) */
  247 + 0x07, /* u8 ep_bLength; */
  248 + USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; Endpoint */
  249 + USB_DIR_IN | 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
  250 + 0x03, /* u8 ep_bmAttributes; Interrupt */
  251 + 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
  252 + 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
  253 +};
  254 +
176 255 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
177 256 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01,
178 257 0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
... ... @@ -223,6 +302,83 @@ static const uint8_t qemu_tablet_hid_report_descriptor[] = {
223 302 0xC0, /* End Collection */
224 303 };
225 304  
  305 +static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
  306 + 0x05, 0x01, /* Usage Page (Generic Desktop) */
  307 + 0x09, 0x06, /* Usage (Keyboard) */
  308 + 0xa1, 0x01, /* Collection (Application) */
  309 + 0x75, 0x01, /* Report Size (1) */
  310 + 0x95, 0x08, /* Report Count (8) */
  311 + 0x05, 0x07, /* Usage Page (Key Codes) */
  312 + 0x19, 0xe0, /* Usage Minimum (224) */
  313 + 0x29, 0xe7, /* Usage Maximum (231) */
  314 + 0x15, 0x00, /* Logical Minimum (0) */
  315 + 0x25, 0x01, /* Logical Maximum (1) */
  316 + 0x81, 0x02, /* Input (Data, Variable, Absolute) */
  317 + 0x95, 0x01, /* Report Count (1) */
  318 + 0x75, 0x08, /* Report Size (8) */
  319 + 0x81, 0x01, /* Input (Constant) */
  320 + 0x95, 0x05, /* Report Count (5) */
  321 + 0x75, 0x01, /* Report Size (1) */
  322 + 0x05, 0x08, /* Usage Page (LEDs) */
  323 + 0x19, 0x01, /* Usage Minimum (1) */
  324 + 0x29, 0x05, /* Usage Maximum (5) */
  325 + 0x91, 0x02, /* Output (Data, Variable, Absolute) */
  326 + 0x95, 0x01, /* Report Count (1) */
  327 + 0x75, 0x03, /* Report Size (3) */
  328 + 0x91, 0x01, /* Output (Constant) */
  329 + 0x95, 0x06, /* Report Count (6) */
  330 + 0x75, 0x08, /* Report Size (8) */
  331 + 0x15, 0x00, /* Logical Minimum (0) */
  332 + 0x25, 0xff, /* Logical Maximum (255) */
  333 + 0x05, 0x07, /* Usage Page (Key Codes) */
  334 + 0x19, 0x00, /* Usage Minimum (0) */
  335 + 0x29, 0xff, /* Usage Maximum (255) */
  336 + 0x81, 0x00, /* Input (Data, Array) */
  337 + 0xc0, /* End Collection */
  338 +};
  339 +
  340 +#define USB_HID_USAGE_ERROR_ROLLOVER 0x01
  341 +#define USB_HID_USAGE_POSTFAIL 0x02
  342 +#define USB_HID_USAGE_ERROR_UNDEFINED 0x03
  343 +
  344 +/* Indices are QEMU keycodes, values are from HID Usage Table. Indices
  345 + * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
  346 +static const uint8_t usb_hid_usage_keys[0x100] = {
  347 + 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
  348 + 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
  349 + 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
  350 + 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
  351 + 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
  352 + 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
  353 + 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
  354 + 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
  355 + 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
  356 + 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
  357 + 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
  358 + 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
  359 + 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
  360 + 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
  361 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  362 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
  363 +
  364 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  365 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  366 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  367 + 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
  368 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  369 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  370 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
  371 + 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  372 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
  373 + 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
  374 + 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
  375 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  376 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  377 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  378 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  379 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  380 +};
  381 +
226 382 static void usb_mouse_event(void *opaque,
227 383 int dx1, int dy1, int dz1, int buttons_state)
228 384 {
... ... @@ -245,6 +401,51 @@ static void usb_tablet_event(void *opaque,
245 401 s->buttons_state = buttons_state;
246 402 }
247 403  
  404 +static void usb_keyboard_event(void *opaque, int keycode)
  405 +{
  406 + USBKeyboardState *s = opaque;
  407 + uint8_t hid_code, key;
  408 + int i;
  409 +
  410 + key = keycode & 0x7f;
  411 + hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
  412 + s->modifiers &= ~(1 << 8);
  413 +
  414 + switch (hid_code) {
  415 + case 0x00:
  416 + return;
  417 +
  418 + case 0xe0:
  419 + if (s->modifiers & (1 << 9)) {
  420 + s->modifiers ^= 3 << 8;
  421 + return;
  422 + }
  423 + case 0xe1 ... 0xe7:
  424 + if (keycode & (1 << 7)) {
  425 + s->modifiers &= ~(1 << (hid_code & 0x0f));
  426 + return;
  427 + }
  428 + case 0xe8 ... 0xef:
  429 + s->modifiers |= 1 << (hid_code & 0x0f);
  430 + return;
  431 + }
  432 +
  433 + if (keycode & (1 << 7)) {
  434 + for (i = s->keys - 1; i >= 0; i --)
  435 + if (s->key[i] == hid_code) {
  436 + s->key[i] = s->key[-- s->keys];
  437 + s->key[s->keys] = 0x00;
  438 + return;
  439 + }
  440 + } else {
  441 + for (i = s->keys - 1; i >= 0; i --)
  442 + if (s->key[i] == hid_code)
  443 + return;
  444 + if (s->keys < sizeof(s->key))
  445 + s->key[s->keys ++] = hid_code;
  446 + }
  447 +}
  448 +
248 449 static inline int int_clamp(int val, int vmin, int vmax)
249 450 {
250 451 if (val < vmin)
... ... @@ -326,22 +527,59 @@ static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
326 527 return l;
327 528 }
328 529  
  530 +static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
  531 +{
  532 + if (len < 2)
  533 + return 0;
  534 +
  535 + buf[0] = s->modifiers & 0xff;
  536 + buf[1] = 0;
  537 + if (s->keys > 6)
  538 + memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
  539 + else
  540 + memcpy(buf + 2, s->key, MIN(8, len) - 2);
  541 +
  542 + return MIN(8, len);
  543 +}
  544 +
  545 +static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
  546 +{
  547 + if (len > 0) {
  548 + /* 0x01: Num Lock LED
  549 + * 0x02: Caps Lock LED
  550 + * 0x04: Scroll Lock LED
  551 + * 0x08: Compose LED
  552 + * 0x10: Kana LED */
  553 + s->leds = buf[0];
  554 + }
  555 + return 0;
  556 +}
  557 +
329 558 static void usb_mouse_handle_reset(USBDevice *dev)
330 559 {
331   - USBMouseState *s = (USBMouseState *)dev;
332   -
333   - s->dx = 0;
334   - s->dy = 0;
335   - s->dz = 0;
336   - s->x = 0;
337   - s->y = 0;
338   - s->buttons_state = 0;
  560 + USBHIDState *s = (USBHIDState *)dev;
  561 +
  562 + s->ptr.dx = 0;
  563 + s->ptr.dy = 0;
  564 + s->ptr.dz = 0;
  565 + s->ptr.x = 0;
  566 + s->ptr.y = 0;
  567 + s->ptr.buttons_state = 0;
  568 + s->protocol = 1;
  569 +}
  570 +
  571 +static void usb_keyboard_handle_reset(USBDevice *dev)
  572 +{
  573 + USBHIDState *s = (USBHIDState *)dev;
  574 +
  575 + qemu_add_kbd_event_handler(usb_keyboard_event, &s->kbd);
  576 + s->protocol = 1;
339 577 }
340 578  
341   -static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
  579 +static int usb_hid_handle_control(USBDevice *dev, int request, int value,
342 580 int index, int length, uint8_t *data)
343 581 {
344   - USBMouseState *s = (USBMouseState *)dev;
  582 + USBHIDState *s = (USBHIDState *)dev;
345 583 int ret = 0;
346 584  
347 585 switch(request) {
... ... @@ -387,7 +625,11 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
387 625 memcpy(data, qemu_tablet_config_descriptor,
388 626 sizeof(qemu_tablet_config_descriptor));
389 627 ret = sizeof(qemu_tablet_config_descriptor);
390   - }
  628 + } else if (s->kind == USB_KEYBOARD) {
  629 + memcpy(data, qemu_keyboard_config_descriptor,
  630 + sizeof(qemu_keyboard_config_descriptor));
  631 + ret = sizeof(qemu_keyboard_config_descriptor);
  632 + }
391 633 break;
392 634 case USB_DT_STRING:
393 635 switch(value & 0xff) {
... ... @@ -405,10 +647,7 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
405 647 break;
406 648 case 2:
407 649 /* product description */
408   - if (s->kind == USB_MOUSE)
409   - ret = set_usb_string(data, "QEMU USB Mouse");
410   - else if (s->kind == USB_TABLET)
411   - ret = set_usb_string(data, "QEMU USB Tablet");
  650 + ret = set_usb_string(data, s->dev.devname);
412 651 break;
413 652 case 3:
414 653 /* vendor description */
... ... @@ -418,6 +657,12 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
418 657 ret = set_usb_string(data, "HID Mouse");
419 658 break;
420 659 case 5:
  660 + ret = set_usb_string(data, "HID Tablet");
  661 + break;
  662 + case 6:
  663 + ret = set_usb_string(data, "HID Keyboard");
  664 + break;
  665 + case 7:
421 666 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
422 667 break;
423 668 default:
... ... @@ -454,19 +699,48 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
454 699 memcpy(data, qemu_tablet_hid_report_descriptor,
455 700 sizeof(qemu_tablet_hid_report_descriptor));
456 701 ret = sizeof(qemu_tablet_hid_report_descriptor);
457   - }
458   - break;
  702 + } else if (s->kind == USB_KEYBOARD) {
  703 + memcpy(data, qemu_keyboard_hid_report_descriptor,
  704 + sizeof(qemu_keyboard_hid_report_descriptor));
  705 + ret = sizeof(qemu_keyboard_hid_report_descriptor);
  706 + }
  707 + break;
459 708 default:
460 709 goto fail;
461 710 }
462 711 break;
463 712 case GET_REPORT:
464 713 if (s->kind == USB_MOUSE)
465   - ret = usb_mouse_poll(s, data, length);
  714 + ret = usb_mouse_poll(&s->ptr, data, length);
466 715 else if (s->kind == USB_TABLET)
467   - ret = usb_tablet_poll(s, data, length);
  716 + ret = usb_tablet_poll(&s->ptr, data, length);
  717 + else if (s->kind == USB_KEYBOARD)
  718 + ret = usb_keyboard_poll(&s->kbd, data, length);
  719 + break;
  720 + case SET_REPORT:
  721 + if (s->kind == USB_KEYBOARD)
  722 + ret = usb_keyboard_write(&s->kbd, data, length);
  723 + else
  724 + goto fail;
  725 + break;
  726 + case GET_PROTOCOL:
  727 + if (s->kind != USB_KEYBOARD)
  728 + goto fail;
  729 + ret = 1;
  730 + data[0] = s->protocol;
  731 + break;
  732 + case SET_PROTOCOL:
  733 + if (s->kind != USB_KEYBOARD)
  734 + goto fail;
  735 + ret = 0;
  736 + s->protocol = value;
  737 + break;
  738 + case GET_IDLE:
  739 + ret = 1;
  740 + data[0] = s->idle;
468 741 break;
469 742 case SET_IDLE:
  743 + s->idle = value;
470 744 ret = 0;
471 745 break;
472 746 default:
... ... @@ -477,18 +751,20 @@ static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
477 751 return ret;
478 752 }
479 753  
480   -static int usb_mouse_handle_data(USBDevice *dev, USBPacket *p)
  754 +static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
481 755 {
482   - USBMouseState *s = (USBMouseState *)dev;
  756 + USBHIDState *s = (USBHIDState *)dev;
483 757 int ret = 0;
484 758  
485 759 switch(p->pid) {
486 760 case USB_TOKEN_IN:
487 761 if (p->devep == 1) {
488   - if (s->kind == USB_MOUSE)
489   - ret = usb_mouse_poll(s, p->data, p->len);
490   - else if (s->kind == USB_TABLET)
491   - ret = usb_tablet_poll(s, p->data, p->len);
  762 + if (s->kind == USB_MOUSE)
  763 + ret = usb_mouse_poll(&s->ptr, p->data, p->len);
  764 + else if (s->kind == USB_TABLET)
  765 + ret = usb_tablet_poll(&s->ptr, p->data, p->len);
  766 + else if (s->kind == USB_KEYBOARD)
  767 + ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
492 768 } else {
493 769 goto fail;
494 770 }
... ... @@ -502,28 +778,30 @@ static int usb_mouse_handle_data(USBDevice *dev, USBPacket *p)
502 778 return ret;
503 779 }
504 780  
505   -static void usb_mouse_handle_destroy(USBDevice *dev)
  781 +static void usb_hid_handle_destroy(USBDevice *dev)
506 782 {
507   - USBMouseState *s = (USBMouseState *)dev;
  783 + USBHIDState *s = (USBHIDState *)dev;
508 784  
509   - qemu_remove_mouse_event_handler(s->eh_entry);
  785 + if (s->kind != USB_KEYBOARD)
  786 + qemu_remove_mouse_event_handler(s->ptr.eh_entry);
  787 + /* TODO: else */
510 788 qemu_free(s);
511 789 }
512 790  
513 791 USBDevice *usb_tablet_init(void)
514 792 {
515   - USBMouseState *s;
  793 + USBHIDState *s;
516 794  
517   - s = qemu_mallocz(sizeof(USBMouseState));
  795 + s = qemu_mallocz(sizeof(USBHIDState));
518 796 if (!s)
519 797 return NULL;
520 798 s->dev.speed = USB_SPEED_FULL;
521 799 s->dev.handle_packet = usb_generic_handle_packet;
522 800  
523 801 s->dev.handle_reset = usb_mouse_handle_reset;
524   - s->dev.handle_control = usb_mouse_handle_control;
525   - s->dev.handle_data = usb_mouse_handle_data;
526   - s->dev.handle_destroy = usb_mouse_handle_destroy;
  802 + s->dev.handle_control = usb_hid_handle_control;
  803 + s->dev.handle_data = usb_hid_handle_data;
  804 + s->dev.handle_destroy = usb_hid_handle_destroy;
527 805 s->kind = USB_TABLET;
528 806  
529 807 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
... ... @@ -533,21 +811,42 @@ USBDevice *usb_tablet_init(void)
533 811  
534 812 USBDevice *usb_mouse_init(void)
535 813 {
536   - USBMouseState *s;
  814 + USBHIDState *s;
537 815  
538   - s = qemu_mallocz(sizeof(USBMouseState));
  816 + s = qemu_mallocz(sizeof(USBHIDState));
539 817 if (!s)
540 818 return NULL;
541 819 s->dev.speed = USB_SPEED_FULL;
542 820 s->dev.handle_packet = usb_generic_handle_packet;
543 821  
544 822 s->dev.handle_reset = usb_mouse_handle_reset;
545   - s->dev.handle_control = usb_mouse_handle_control;
546   - s->dev.handle_data = usb_mouse_handle_data;
547   - s->dev.handle_destroy = usb_mouse_handle_destroy;
  823 + s->dev.handle_control = usb_hid_handle_control;
  824 + s->dev.handle_data = usb_hid_handle_data;
  825 + s->dev.handle_destroy = usb_hid_handle_destroy;
548 826 s->kind = USB_MOUSE;
549 827  
550 828 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
551 829  
552 830 return (USBDevice *)s;
553 831 }
  832 +
  833 +USBDevice *usb_keyboard_init(void)
  834 +{
  835 + USBHIDState *s;
  836 +
  837 + s = qemu_mallocz(sizeof(USBHIDState));
  838 + if (!s)
  839 + return NULL;
  840 + s->dev.speed = USB_SPEED_FULL;
  841 + s->dev.handle_packet = usb_generic_handle_packet;
  842 +
  843 + s->dev.handle_reset = usb_keyboard_handle_reset;
  844 + s->dev.handle_control = usb_hid_handle_control;
  845 + s->dev.handle_data = usb_hid_handle_data;
  846 + s->dev.handle_destroy = usb_hid_handle_destroy;
  847 + s->kind = USB_KEYBOARD;
  848 +
  849 + pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");
  850 +
  851 + return (USBDevice *) s;
  852 +}
... ...
hw/usb.h
... ... @@ -218,6 +218,7 @@ void usb_host_info(void);
218 218 /* usb-hid.c */
219 219 USBDevice *usb_mouse_init(void);
220 220 USBDevice *usb_tablet_init(void);
  221 +USBDevice *usb_keyboard_init(void);
221 222  
222 223 /* usb-msd.c */
223 224 USBDevice *usb_msd_init(const char *filename);
... ...
qemu-doc.texi
... ... @@ -1362,6 +1362,8 @@ Pass through the host device identified by @var{vendor_id:product_id}
1362 1362 Virtual Wacom PenPartner tablet. This device is similar to the @code{tablet}
1363 1363 above but it can be used with the tslib library because in addition to touch
1364 1364 coordinates it reports touch pressure.
  1365 +@item @code{keyboard}
  1366 +Standard USB keyboard. Will override the PS/2 keyboard (if present).
1365 1367 @end table
1366 1368  
1367 1369 @node host_usb_devices
... ...
... ... @@ -4319,7 +4319,9 @@ static int usb_device_add(const char *devname)
4319 4319 } else if (!strcmp(devname, "mouse")) {
4320 4320 dev = usb_mouse_init();
4321 4321 } else if (!strcmp(devname, "tablet")) {
4322   - dev = usb_tablet_init();
  4322 + dev = usb_tablet_init();
  4323 + } else if (!strcmp(devname, "keyboard")) {
  4324 + dev = usb_keyboard_init();
4323 4325 } else if (strstart(devname, "disk:", &p)) {
4324 4326 dev = usb_msd_init(p);
4325 4327 } else if (!strcmp(devname, "wacom-tablet")) {
... ...