qemu/hw/usb/dev-hid.c
<<
>>
Prefs
   1/*
   2 * QEMU USB HID devices
   3 *
   4 * Copyright (c) 2005 Fabrice Bellard
   5 * Copyright (c) 2007 OpenMoko, Inc.  (andrew@openedhand.com)
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25
  26#include "qemu/osdep.h"
  27#include "ui/console.h"
  28#include "hw/usb.h"
  29#include "migration/vmstate.h"
  30#include "desc.h"
  31#include "qapi/error.h"
  32#include "qemu/module.h"
  33#include "qemu/timer.h"
  34#include "hw/input/hid.h"
  35#include "hw/qdev-properties.h"
  36
  37/* HID interface requests */
  38#define GET_REPORT   0xa101
  39#define GET_IDLE     0xa102
  40#define GET_PROTOCOL 0xa103
  41#define SET_REPORT   0x2109
  42#define SET_IDLE     0x210a
  43#define SET_PROTOCOL 0x210b
  44
  45/* HID descriptor types */
  46#define USB_DT_HID    0x21
  47#define USB_DT_REPORT 0x22
  48#define USB_DT_PHY    0x23
  49
  50typedef struct USBHIDState {
  51    USBDevice dev;
  52    USBEndpoint *intr;
  53    HIDState hid;
  54    uint32_t usb_version;
  55    char *display;
  56    uint32_t head;
  57} USBHIDState;
  58
  59#define TYPE_USB_HID "usb-hid"
  60#define USB_HID(obj) OBJECT_CHECK(USBHIDState, (obj), TYPE_USB_HID)
  61
  62enum {
  63    STR_MANUFACTURER = 1,
  64    STR_PRODUCT_MOUSE,
  65    STR_PRODUCT_TABLET,
  66    STR_PRODUCT_KEYBOARD,
  67    STR_SERIAL_COMPAT,
  68    STR_CONFIG_MOUSE,
  69    STR_CONFIG_TABLET,
  70    STR_CONFIG_KEYBOARD,
  71    STR_SERIAL_MOUSE,
  72    STR_SERIAL_TABLET,
  73    STR_SERIAL_KEYBOARD,
  74};
  75
  76static const USBDescStrings desc_strings = {
  77    [STR_MANUFACTURER]     = "QEMU",
  78    [STR_PRODUCT_MOUSE]    = "QEMU USB Mouse",
  79    [STR_PRODUCT_TABLET]   = "QEMU USB Tablet",
  80    [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
  81    [STR_SERIAL_COMPAT]    = "42",
  82    [STR_CONFIG_MOUSE]     = "HID Mouse",
  83    [STR_CONFIG_TABLET]    = "HID Tablet",
  84    [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
  85    [STR_SERIAL_MOUSE]     = "89126",
  86    [STR_SERIAL_TABLET]    = "28754",
  87    [STR_SERIAL_KEYBOARD]  = "68284",
  88};
  89
  90static const USBDescIface desc_iface_mouse = {
  91    .bInterfaceNumber              = 0,
  92    .bNumEndpoints                 = 1,
  93    .bInterfaceClass               = USB_CLASS_HID,
  94    .bInterfaceSubClass            = 0x01, /* boot */
  95    .bInterfaceProtocol            = 0x02,
  96    .ndesc                         = 1,
  97    .descs = (USBDescOther[]) {
  98        {
  99            /* HID descriptor */
 100            .data = (uint8_t[]) {
 101                0x09,          /*  u8  bLength */
 102                USB_DT_HID,    /*  u8  bDescriptorType */
 103                0x01, 0x00,    /*  u16 HID_class */
 104                0x00,          /*  u8  country_code */
 105                0x01,          /*  u8  num_descriptors */
 106                USB_DT_REPORT, /*  u8  type: Report */
 107                52, 0,         /*  u16 len */
 108            },
 109        },
 110    },
 111    .eps = (USBDescEndpoint[]) {
 112        {
 113            .bEndpointAddress      = USB_DIR_IN | 0x01,
 114            .bmAttributes          = USB_ENDPOINT_XFER_INT,
 115            .wMaxPacketSize        = 4,
 116            .bInterval             = 0x0a,
 117        },
 118    },
 119};
 120
 121static const USBDescIface desc_iface_mouse2 = {
 122    .bInterfaceNumber              = 0,
 123    .bNumEndpoints                 = 1,
 124    .bInterfaceClass               = USB_CLASS_HID,
 125    .bInterfaceSubClass            = 0x01, /* boot */
 126    .bInterfaceProtocol            = 0x02,
 127    .ndesc                         = 1,
 128    .descs = (USBDescOther[]) {
 129        {
 130            /* HID descriptor */
 131            .data = (uint8_t[]) {
 132                0x09,          /*  u8  bLength */
 133                USB_DT_HID,    /*  u8  bDescriptorType */
 134                0x01, 0x00,    /*  u16 HID_class */
 135                0x00,          /*  u8  country_code */
 136                0x01,          /*  u8  num_descriptors */
 137                USB_DT_REPORT, /*  u8  type: Report */
 138                52, 0,         /*  u16 len */
 139            },
 140        },
 141    },
 142    .eps = (USBDescEndpoint[]) {
 143        {
 144            .bEndpointAddress      = USB_DIR_IN | 0x01,
 145            .bmAttributes          = USB_ENDPOINT_XFER_INT,
 146            .wMaxPacketSize        = 4,
 147            .bInterval             = 7, /* 2 ^ (8-1) * 125 usecs = 8 ms */
 148        },
 149    },
 150};
 151
 152static const USBDescIface desc_iface_tablet = {
 153    .bInterfaceNumber              = 0,
 154    .bNumEndpoints                 = 1,
 155    .bInterfaceClass               = USB_CLASS_HID,
 156    .bInterfaceProtocol            = 0x00,
 157    .ndesc                         = 1,
 158    .descs = (USBDescOther[]) {
 159        {
 160            /* HID descriptor */
 161            .data = (uint8_t[]) {
 162                0x09,          /*  u8  bLength */
 163                USB_DT_HID,    /*  u8  bDescriptorType */
 164                0x01, 0x00,    /*  u16 HID_class */
 165                0x00,          /*  u8  country_code */
 166                0x01,          /*  u8  num_descriptors */
 167                USB_DT_REPORT, /*  u8  type: Report */
 168                74, 0,         /*  u16 len */
 169            },
 170        },
 171    },
 172    .eps = (USBDescEndpoint[]) {
 173        {
 174            .bEndpointAddress      = USB_DIR_IN | 0x01,
 175            .bmAttributes          = USB_ENDPOINT_XFER_INT,
 176            .wMaxPacketSize        = 8,
 177            .bInterval             = 0x0a,
 178        },
 179    },
 180};
 181
 182static const USBDescIface desc_iface_tablet2 = {
 183    .bInterfaceNumber              = 0,
 184    .bNumEndpoints                 = 1,
 185    .bInterfaceClass               = USB_CLASS_HID,
 186    .bInterfaceProtocol            = 0x00,
 187    .ndesc                         = 1,
 188    .descs = (USBDescOther[]) {
 189        {
 190            /* HID descriptor */
 191            .data = (uint8_t[]) {
 192                0x09,          /*  u8  bLength */
 193                USB_DT_HID,    /*  u8  bDescriptorType */
 194                0x01, 0x00,    /*  u16 HID_class */
 195                0x00,          /*  u8  country_code */
 196                0x01,          /*  u8  num_descriptors */
 197                USB_DT_REPORT, /*  u8  type: Report */
 198                74, 0,         /*  u16 len */
 199            },
 200        },
 201    },
 202    .eps = (USBDescEndpoint[]) {
 203        {
 204            .bEndpointAddress      = USB_DIR_IN | 0x01,
 205            .bmAttributes          = USB_ENDPOINT_XFER_INT,
 206            .wMaxPacketSize        = 8,
 207            .bInterval             = 4, /* 2 ^ (4-1) * 125 usecs = 1 ms */
 208        },
 209    },
 210};
 211
 212static const USBDescIface desc_iface_keyboard = {
 213    .bInterfaceNumber              = 0,
 214    .bNumEndpoints                 = 1,
 215    .bInterfaceClass               = USB_CLASS_HID,
 216    .bInterfaceSubClass            = 0x01, /* boot */
 217    .bInterfaceProtocol            = 0x01, /* keyboard */
 218    .ndesc                         = 1,
 219    .descs = (USBDescOther[]) {
 220        {
 221            /* HID descriptor */
 222            .data = (uint8_t[]) {
 223                0x09,          /*  u8  bLength */
 224                USB_DT_HID,    /*  u8  bDescriptorType */
 225                0x11, 0x01,    /*  u16 HID_class */
 226                0x00,          /*  u8  country_code */
 227                0x01,          /*  u8  num_descriptors */
 228                USB_DT_REPORT, /*  u8  type: Report */
 229                0x3f, 0,       /*  u16 len */
 230            },
 231        },
 232    },
 233    .eps = (USBDescEndpoint[]) {
 234        {
 235            .bEndpointAddress      = USB_DIR_IN | 0x01,
 236            .bmAttributes          = USB_ENDPOINT_XFER_INT,
 237            .wMaxPacketSize        = 8,
 238            .bInterval             = 0x0a,
 239        },
 240    },
 241};
 242
 243static const USBDescIface desc_iface_keyboard2 = {
 244    .bInterfaceNumber              = 0,
 245    .bNumEndpoints                 = 1,
 246    .bInterfaceClass               = USB_CLASS_HID,
 247    .bInterfaceSubClass            = 0x01, /* boot */
 248    .bInterfaceProtocol            = 0x01, /* keyboard */
 249    .ndesc                         = 1,
 250    .descs = (USBDescOther[]) {
 251        {
 252            /* HID descriptor */
 253            .data = (uint8_t[]) {
 254                0x09,          /*  u8  bLength */
 255                USB_DT_HID,    /*  u8  bDescriptorType */
 256                0x11, 0x01,    /*  u16 HID_class */
 257                0x00,          /*  u8  country_code */
 258                0x01,          /*  u8  num_descriptors */
 259                USB_DT_REPORT, /*  u8  type: Report */
 260                0x3f, 0,       /*  u16 len */
 261            },
 262        },
 263    },
 264    .eps = (USBDescEndpoint[]) {
 265        {
 266            .bEndpointAddress      = USB_DIR_IN | 0x01,
 267            .bmAttributes          = USB_ENDPOINT_XFER_INT,
 268            .wMaxPacketSize        = 8,
 269            .bInterval             = 7, /* 2 ^ (8-1) * 125 usecs = 8 ms */
 270        },
 271    },
 272};
 273
 274static const USBDescDevice desc_device_mouse = {
 275    .bcdUSB                        = 0x0100,
 276    .bMaxPacketSize0               = 8,
 277    .bNumConfigurations            = 1,
 278    .confs = (USBDescConfig[]) {
 279        {
 280            .bNumInterfaces        = 1,
 281            .bConfigurationValue   = 1,
 282            .iConfiguration        = STR_CONFIG_MOUSE,
 283            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
 284            .bMaxPower             = 50,
 285            .nif = 1,
 286            .ifs = &desc_iface_mouse,
 287        },
 288    },
 289};
 290
 291static const USBDescDevice desc_device_mouse2 = {
 292    .bcdUSB                        = 0x0200,
 293    .bMaxPacketSize0               = 64,
 294    .bNumConfigurations            = 1,
 295    .confs = (USBDescConfig[]) {
 296        {
 297            .bNumInterfaces        = 1,
 298            .bConfigurationValue   = 1,
 299            .iConfiguration        = STR_CONFIG_MOUSE,
 300            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
 301            .bMaxPower             = 50,
 302            .nif = 1,
 303            .ifs = &desc_iface_mouse2,
 304        },
 305    },
 306};
 307
 308static const USBDescDevice desc_device_tablet = {
 309    .bcdUSB                        = 0x0100,
 310    .bMaxPacketSize0               = 8,
 311    .bNumConfigurations            = 1,
 312    .confs = (USBDescConfig[]) {
 313        {
 314            .bNumInterfaces        = 1,
 315            .bConfigurationValue   = 1,
 316            .iConfiguration        = STR_CONFIG_TABLET,
 317            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
 318            .bMaxPower             = 50,
 319            .nif = 1,
 320            .ifs = &desc_iface_tablet,
 321        },
 322    },
 323};
 324
 325static const USBDescDevice desc_device_tablet2 = {
 326    .bcdUSB                        = 0x0200,
 327    .bMaxPacketSize0               = 64,
 328    .bNumConfigurations            = 1,
 329    .confs = (USBDescConfig[]) {
 330        {
 331            .bNumInterfaces        = 1,
 332            .bConfigurationValue   = 1,
 333            .iConfiguration        = STR_CONFIG_TABLET,
 334            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
 335            .bMaxPower             = 50,
 336            .nif = 1,
 337            .ifs = &desc_iface_tablet2,
 338        },
 339    },
 340};
 341
 342static const USBDescDevice desc_device_keyboard = {
 343    .bcdUSB                        = 0x0100,
 344    .bMaxPacketSize0               = 8,
 345    .bNumConfigurations            = 1,
 346    .confs = (USBDescConfig[]) {
 347        {
 348            .bNumInterfaces        = 1,
 349            .bConfigurationValue   = 1,
 350            .iConfiguration        = STR_CONFIG_KEYBOARD,
 351            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
 352            .bMaxPower             = 50,
 353            .nif = 1,
 354            .ifs = &desc_iface_keyboard,
 355        },
 356    },
 357};
 358
 359static const USBDescDevice desc_device_keyboard2 = {
 360    .bcdUSB                        = 0x0200,
 361    .bMaxPacketSize0               = 64,
 362    .bNumConfigurations            = 1,
 363    .confs = (USBDescConfig[]) {
 364        {
 365            .bNumInterfaces        = 1,
 366            .bConfigurationValue   = 1,
 367            .iConfiguration        = STR_CONFIG_KEYBOARD,
 368            .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
 369            .bMaxPower             = 50,
 370            .nif = 1,
 371            .ifs = &desc_iface_keyboard2,
 372        },
 373    },
 374};
 375
 376static const USBDescMSOS desc_msos_suspend = {
 377    .SelectiveSuspendEnabled = true,
 378};
 379
 380static const USBDesc desc_mouse = {
 381    .id = {
 382        .idVendor          = 0x0627,
 383        .idProduct         = 0x0001,
 384        .bcdDevice         = 0,
 385        .iManufacturer     = STR_MANUFACTURER,
 386        .iProduct          = STR_PRODUCT_MOUSE,
 387        .iSerialNumber     = STR_SERIAL_MOUSE,
 388    },
 389    .full = &desc_device_mouse,
 390    .str  = desc_strings,
 391    .msos = &desc_msos_suspend,
 392};
 393
 394static const USBDesc desc_mouse2 = {
 395    .id = {
 396        .idVendor          = 0x0627,
 397        .idProduct         = 0x0001,
 398        .bcdDevice         = 0,
 399        .iManufacturer     = STR_MANUFACTURER,
 400        .iProduct          = STR_PRODUCT_MOUSE,
 401        .iSerialNumber     = STR_SERIAL_MOUSE,
 402    },
 403    .full = &desc_device_mouse,
 404    .high = &desc_device_mouse2,
 405    .str  = desc_strings,
 406    .msos = &desc_msos_suspend,
 407};
 408
 409static const USBDesc desc_tablet = {
 410    .id = {
 411        .idVendor          = 0x0627,
 412        .idProduct         = 0x0001,
 413        .bcdDevice         = 0,
 414        .iManufacturer     = STR_MANUFACTURER,
 415        .iProduct          = STR_PRODUCT_TABLET,
 416        .iSerialNumber     = STR_SERIAL_TABLET,
 417    },
 418    .full = &desc_device_tablet,
 419    .str  = desc_strings,
 420    .msos = &desc_msos_suspend,
 421};
 422
 423static const USBDesc desc_tablet2 = {
 424    .id = {
 425        .idVendor          = 0x0627,
 426        .idProduct         = 0x0001,
 427        .bcdDevice         = 0,
 428        .iManufacturer     = STR_MANUFACTURER,
 429        .iProduct          = STR_PRODUCT_TABLET,
 430        .iSerialNumber     = STR_SERIAL_TABLET,
 431    },
 432    .full = &desc_device_tablet,
 433    .high = &desc_device_tablet2,
 434    .str  = desc_strings,
 435    .msos = &desc_msos_suspend,
 436};
 437
 438static const USBDesc desc_keyboard = {
 439    .id = {
 440        .idVendor          = 0x0627,
 441        .idProduct         = 0x0001,
 442        .bcdDevice         = 0,
 443        .iManufacturer     = STR_MANUFACTURER,
 444        .iProduct          = STR_PRODUCT_KEYBOARD,
 445        .iSerialNumber     = STR_SERIAL_KEYBOARD,
 446    },
 447    .full = &desc_device_keyboard,
 448    .str  = desc_strings,
 449    .msos = &desc_msos_suspend,
 450};
 451
 452static const USBDesc desc_keyboard2 = {
 453    .id = {
 454        .idVendor          = 0x0627,
 455        .idProduct         = 0x0001,
 456        .bcdDevice         = 0,
 457        .iManufacturer     = STR_MANUFACTURER,
 458        .iProduct          = STR_PRODUCT_KEYBOARD,
 459        .iSerialNumber     = STR_SERIAL_KEYBOARD,
 460    },
 461    .full = &desc_device_keyboard,
 462    .high = &desc_device_keyboard2,
 463    .str  = desc_strings,
 464    .msos = &desc_msos_suspend,
 465};
 466
 467static const uint8_t qemu_mouse_hid_report_descriptor[] = {
 468    0x05, 0x01,         /* Usage Page (Generic Desktop) */
 469    0x09, 0x02,         /* Usage (Mouse) */
 470    0xa1, 0x01,         /* Collection (Application) */
 471    0x09, 0x01,         /*   Usage (Pointer) */
 472    0xa1, 0x00,         /*   Collection (Physical) */
 473    0x05, 0x09,         /*     Usage Page (Button) */
 474    0x19, 0x01,         /*     Usage Minimum (1) */
 475    0x29, 0x03,         /*     Usage Maximum (3) */
 476    0x15, 0x00,         /*     Logical Minimum (0) */
 477    0x25, 0x01,         /*     Logical Maximum (1) */
 478    0x95, 0x03,         /*     Report Count (3) */
 479    0x75, 0x01,         /*     Report Size (1) */
 480    0x81, 0x02,         /*     Input (Data, Variable, Absolute) */
 481    0x95, 0x01,         /*     Report Count (1) */
 482    0x75, 0x05,         /*     Report Size (5) */
 483    0x81, 0x01,         /*     Input (Constant) */
 484    0x05, 0x01,         /*     Usage Page (Generic Desktop) */
 485    0x09, 0x30,         /*     Usage (X) */
 486    0x09, 0x31,         /*     Usage (Y) */
 487    0x09, 0x38,         /*     Usage (Wheel) */
 488    0x15, 0x81,         /*     Logical Minimum (-0x7f) */
 489    0x25, 0x7f,         /*     Logical Maximum (0x7f) */
 490    0x75, 0x08,         /*     Report Size (8) */
 491    0x95, 0x03,         /*     Report Count (3) */
 492    0x81, 0x06,         /*     Input (Data, Variable, Relative) */
 493    0xc0,               /*   End Collection */
 494    0xc0,               /* End Collection */
 495};
 496
 497static const uint8_t qemu_tablet_hid_report_descriptor[] = {
 498    0x05, 0x01,         /* Usage Page (Generic Desktop) */
 499    0x09, 0x02,         /* Usage (Mouse) */
 500    0xa1, 0x01,         /* Collection (Application) */
 501    0x09, 0x01,         /*   Usage (Pointer) */
 502    0xa1, 0x00,         /*   Collection (Physical) */
 503    0x05, 0x09,         /*     Usage Page (Button) */
 504    0x19, 0x01,         /*     Usage Minimum (1) */
 505    0x29, 0x03,         /*     Usage Maximum (3) */
 506    0x15, 0x00,         /*     Logical Minimum (0) */
 507    0x25, 0x01,         /*     Logical Maximum (1) */
 508    0x95, 0x03,         /*     Report Count (3) */
 509    0x75, 0x01,         /*     Report Size (1) */
 510    0x81, 0x02,         /*     Input (Data, Variable, Absolute) */
 511    0x95, 0x01,         /*     Report Count (1) */
 512    0x75, 0x05,         /*     Report Size (5) */
 513    0x81, 0x01,         /*     Input (Constant) */
 514    0x05, 0x01,         /*     Usage Page (Generic Desktop) */
 515    0x09, 0x30,         /*     Usage (X) */
 516    0x09, 0x31,         /*     Usage (Y) */
 517    0x15, 0x00,         /*     Logical Minimum (0) */
 518    0x26, 0xff, 0x7f,   /*     Logical Maximum (0x7fff) */
 519    0x35, 0x00,         /*     Physical Minimum (0) */
 520    0x46, 0xff, 0x7f,   /*     Physical Maximum (0x7fff) */
 521    0x75, 0x10,         /*     Report Size (16) */
 522    0x95, 0x02,         /*     Report Count (2) */
 523    0x81, 0x02,         /*     Input (Data, Variable, Absolute) */
 524    0x05, 0x01,         /*     Usage Page (Generic Desktop) */
 525    0x09, 0x38,         /*     Usage (Wheel) */
 526    0x15, 0x81,         /*     Logical Minimum (-0x7f) */
 527    0x25, 0x7f,         /*     Logical Maximum (0x7f) */
 528    0x35, 0x00,         /*     Physical Minimum (same as logical) */
 529    0x45, 0x00,         /*     Physical Maximum (same as logical) */
 530    0x75, 0x08,         /*     Report Size (8) */
 531    0x95, 0x01,         /*     Report Count (1) */
 532    0x81, 0x06,         /*     Input (Data, Variable, Relative) */
 533    0xc0,               /*   End Collection */
 534    0xc0,               /* End Collection */
 535};
 536
 537static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
 538    0x05, 0x01,         /* Usage Page (Generic Desktop) */
 539    0x09, 0x06,         /* Usage (Keyboard) */
 540    0xa1, 0x01,         /* Collection (Application) */
 541    0x75, 0x01,         /*   Report Size (1) */
 542    0x95, 0x08,         /*   Report Count (8) */
 543    0x05, 0x07,         /*   Usage Page (Key Codes) */
 544    0x19, 0xe0,         /*   Usage Minimum (224) */
 545    0x29, 0xe7,         /*   Usage Maximum (231) */
 546    0x15, 0x00,         /*   Logical Minimum (0) */
 547    0x25, 0x01,         /*   Logical Maximum (1) */
 548    0x81, 0x02,         /*   Input (Data, Variable, Absolute) */
 549    0x95, 0x01,         /*   Report Count (1) */
 550    0x75, 0x08,         /*   Report Size (8) */
 551    0x81, 0x01,         /*   Input (Constant) */
 552    0x95, 0x05,         /*   Report Count (5) */
 553    0x75, 0x01,         /*   Report Size (1) */
 554    0x05, 0x08,         /*   Usage Page (LEDs) */
 555    0x19, 0x01,         /*   Usage Minimum (1) */
 556    0x29, 0x05,         /*   Usage Maximum (5) */
 557    0x91, 0x02,         /*   Output (Data, Variable, Absolute) */
 558    0x95, 0x01,         /*   Report Count (1) */
 559    0x75, 0x03,         /*   Report Size (3) */
 560    0x91, 0x01,         /*   Output (Constant) */
 561    0x95, 0x06,         /*   Report Count (6) */
 562    0x75, 0x08,         /*   Report Size (8) */
 563    0x15, 0x00,         /*   Logical Minimum (0) */
 564    0x25, 0xff,         /*   Logical Maximum (255) */
 565    0x05, 0x07,         /*   Usage Page (Key Codes) */
 566    0x19, 0x00,         /*   Usage Minimum (0) */
 567    0x29, 0xff,         /*   Usage Maximum (255) */
 568    0x81, 0x00,         /*   Input (Data, Array) */
 569    0xc0,               /* End Collection */
 570};
 571
 572static void usb_hid_changed(HIDState *hs)
 573{
 574    USBHIDState *us = container_of(hs, USBHIDState, hid);
 575
 576    usb_wakeup(us->intr, 0);
 577}
 578
 579static void usb_hid_handle_reset(USBDevice *dev)
 580{
 581    USBHIDState *us = USB_HID(dev);
 582
 583    hid_reset(&us->hid);
 584}
 585
 586static void usb_hid_handle_control(USBDevice *dev, USBPacket *p,
 587               int request, int value, int index, int length, uint8_t *data)
 588{
 589    USBHIDState *us = USB_HID(dev);
 590    HIDState *hs = &us->hid;
 591    int ret;
 592
 593    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
 594    if (ret >= 0) {
 595        return;
 596    }
 597
 598    switch (request) {
 599        /* hid specific requests */
 600    case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
 601        switch (value >> 8) {
 602        case 0x22:
 603            if (hs->kind == HID_MOUSE) {
 604                memcpy(data, qemu_mouse_hid_report_descriptor,
 605                       sizeof(qemu_mouse_hid_report_descriptor));
 606                p->actual_length = sizeof(qemu_mouse_hid_report_descriptor);
 607            } else if (hs->kind == HID_TABLET) {
 608                memcpy(data, qemu_tablet_hid_report_descriptor,
 609                       sizeof(qemu_tablet_hid_report_descriptor));
 610                p->actual_length = sizeof(qemu_tablet_hid_report_descriptor);
 611            } else if (hs->kind == HID_KEYBOARD) {
 612                memcpy(data, qemu_keyboard_hid_report_descriptor,
 613                       sizeof(qemu_keyboard_hid_report_descriptor));
 614                p->actual_length = sizeof(qemu_keyboard_hid_report_descriptor);
 615            }
 616            break;
 617        default:
 618            goto fail;
 619        }
 620        break;
 621    case GET_REPORT:
 622        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
 623            p->actual_length = hid_pointer_poll(hs, data, length);
 624        } else if (hs->kind == HID_KEYBOARD) {
 625            p->actual_length = hid_keyboard_poll(hs, data, length);
 626        }
 627        break;
 628    case SET_REPORT:
 629        if (hs->kind == HID_KEYBOARD) {
 630            p->actual_length = hid_keyboard_write(hs, data, length);
 631        } else {
 632            goto fail;
 633        }
 634        break;
 635    case GET_PROTOCOL:
 636        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
 637            goto fail;
 638        }
 639        data[0] = hs->protocol;
 640        p->actual_length = 1;
 641        break;
 642    case SET_PROTOCOL:
 643        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
 644            goto fail;
 645        }
 646        hs->protocol = value;
 647        break;
 648    case GET_IDLE:
 649        data[0] = hs->idle;
 650        p->actual_length = 1;
 651        break;
 652    case SET_IDLE:
 653        hs->idle = (uint8_t) (value >> 8);
 654        hid_set_next_idle(hs);
 655        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
 656            hid_pointer_activate(hs);
 657        }
 658        break;
 659    default:
 660    fail:
 661        p->status = USB_RET_STALL;
 662        break;
 663    }
 664}
 665
 666static void usb_hid_handle_data(USBDevice *dev, USBPacket *p)
 667{
 668    USBHIDState *us = USB_HID(dev);
 669    HIDState *hs = &us->hid;
 670    uint8_t buf[p->iov.size];
 671    int len = 0;
 672
 673    switch (p->pid) {
 674    case USB_TOKEN_IN:
 675        if (p->ep->nr == 1) {
 676            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
 677                hid_pointer_activate(hs);
 678            }
 679            if (!hid_has_events(hs)) {
 680                p->status = USB_RET_NAK;
 681                return;
 682            }
 683            hid_set_next_idle(hs);
 684            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
 685                len = hid_pointer_poll(hs, buf, p->iov.size);
 686            } else if (hs->kind == HID_KEYBOARD) {
 687                len = hid_keyboard_poll(hs, buf, p->iov.size);
 688            }
 689            usb_packet_copy(p, buf, len);
 690        } else {
 691            goto fail;
 692        }
 693        break;
 694    case USB_TOKEN_OUT:
 695    default:
 696    fail:
 697        p->status = USB_RET_STALL;
 698        break;
 699    }
 700}
 701
 702static void usb_hid_unrealize(USBDevice *dev)
 703{
 704    USBHIDState *us = USB_HID(dev);
 705
 706    hid_free(&us->hid);
 707}
 708
 709static void usb_hid_initfn(USBDevice *dev, int kind,
 710                           const USBDesc *usb1, const USBDesc *usb2,
 711                           Error **errp)
 712{
 713    USBHIDState *us = USB_HID(dev);
 714    switch (us->usb_version) {
 715    case 1:
 716        dev->usb_desc = usb1;
 717        break;
 718    case 2:
 719        dev->usb_desc = usb2;
 720        break;
 721    default:
 722        dev->usb_desc = NULL;
 723    }
 724    if (!dev->usb_desc) {
 725        error_setg(errp, "Invalid usb version %d for usb hid device",
 726                   us->usb_version);
 727        return;
 728    }
 729
 730    usb_desc_create_serial(dev);
 731    usb_desc_init(dev);
 732    us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
 733    hid_init(&us->hid, kind, usb_hid_changed);
 734    if (us->display && us->hid.s) {
 735        qemu_input_handler_bind(us->hid.s, us->display, us->head, NULL);
 736    }
 737}
 738
 739static void usb_tablet_realize(USBDevice *dev, Error **errp)
 740{
 741
 742    usb_hid_initfn(dev, HID_TABLET, &desc_tablet, &desc_tablet2, errp);
 743}
 744
 745static void usb_mouse_realize(USBDevice *dev, Error **errp)
 746{
 747    usb_hid_initfn(dev, HID_MOUSE, &desc_mouse, &desc_mouse2, errp);
 748}
 749
 750static void usb_keyboard_realize(USBDevice *dev, Error **errp)
 751{
 752    usb_hid_initfn(dev, HID_KEYBOARD, &desc_keyboard, &desc_keyboard2, errp);
 753}
 754
 755static int usb_ptr_post_load(void *opaque, int version_id)
 756{
 757    USBHIDState *s = opaque;
 758
 759    if (s->dev.remote_wakeup) {
 760        hid_pointer_activate(&s->hid);
 761    }
 762    return 0;
 763}
 764
 765static const VMStateDescription vmstate_usb_ptr = {
 766    .name = "usb-ptr",
 767    .version_id = 1,
 768    .minimum_version_id = 1,
 769    .post_load = usb_ptr_post_load,
 770    .fields = (VMStateField[]) {
 771        VMSTATE_USB_DEVICE(dev, USBHIDState),
 772        VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
 773        VMSTATE_END_OF_LIST()
 774    }
 775};
 776
 777static const VMStateDescription vmstate_usb_kbd = {
 778    .name = "usb-kbd",
 779    .version_id = 1,
 780    .minimum_version_id = 1,
 781    .fields = (VMStateField[]) {
 782        VMSTATE_USB_DEVICE(dev, USBHIDState),
 783        VMSTATE_HID_KEYBOARD_DEVICE(hid, USBHIDState),
 784        VMSTATE_END_OF_LIST()
 785    }
 786};
 787
 788static void usb_hid_class_initfn(ObjectClass *klass, void *data)
 789{
 790    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 791
 792    uc->handle_reset   = usb_hid_handle_reset;
 793    uc->handle_control = usb_hid_handle_control;
 794    uc->handle_data    = usb_hid_handle_data;
 795    uc->unrealize      = usb_hid_unrealize;
 796    uc->handle_attach  = usb_desc_attach;
 797}
 798
 799static const TypeInfo usb_hid_type_info = {
 800    .name = TYPE_USB_HID,
 801    .parent = TYPE_USB_DEVICE,
 802    .instance_size = sizeof(USBHIDState),
 803    .abstract = true,
 804    .class_init = usb_hid_class_initfn,
 805};
 806
 807static Property usb_tablet_properties[] = {
 808        DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
 809        DEFINE_PROP_STRING("display", USBHIDState, display),
 810        DEFINE_PROP_UINT32("head", USBHIDState, head, 0),
 811        DEFINE_PROP_END_OF_LIST(),
 812};
 813
 814static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
 815{
 816    DeviceClass *dc = DEVICE_CLASS(klass);
 817    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 818
 819    uc->realize        = usb_tablet_realize;
 820    uc->product_desc   = "QEMU USB Tablet";
 821    dc->vmsd = &vmstate_usb_ptr;
 822    device_class_set_props(dc, usb_tablet_properties);
 823    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 824}
 825
 826static const TypeInfo usb_tablet_info = {
 827    .name          = "usb-tablet",
 828    .parent        = TYPE_USB_HID,
 829    .class_init    = usb_tablet_class_initfn,
 830};
 831
 832static Property usb_mouse_properties[] = {
 833        DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
 834        DEFINE_PROP_END_OF_LIST(),
 835};
 836
 837static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
 838{
 839    DeviceClass *dc = DEVICE_CLASS(klass);
 840    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 841
 842    uc->realize        = usb_mouse_realize;
 843    uc->product_desc   = "QEMU USB Mouse";
 844    dc->vmsd = &vmstate_usb_ptr;
 845    device_class_set_props(dc, usb_mouse_properties);
 846    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 847}
 848
 849static const TypeInfo usb_mouse_info = {
 850    .name          = "usb-mouse",
 851    .parent        = TYPE_USB_HID,
 852    .class_init    = usb_mouse_class_initfn,
 853};
 854
 855static Property usb_keyboard_properties[] = {
 856        DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
 857        DEFINE_PROP_STRING("display", USBHIDState, display),
 858        DEFINE_PROP_END_OF_LIST(),
 859};
 860
 861static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
 862{
 863    DeviceClass *dc = DEVICE_CLASS(klass);
 864    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
 865
 866    uc->realize        = usb_keyboard_realize;
 867    uc->product_desc   = "QEMU USB Keyboard";
 868    dc->vmsd = &vmstate_usb_kbd;
 869    device_class_set_props(dc, usb_keyboard_properties);
 870    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
 871}
 872
 873static const TypeInfo usb_keyboard_info = {
 874    .name          = "usb-kbd",
 875    .parent        = TYPE_USB_HID,
 876    .class_init    = usb_keyboard_class_initfn,
 877};
 878
 879static void usb_hid_register_types(void)
 880{
 881    type_register_static(&usb_hid_type_info);
 882    type_register_static(&usb_tablet_info);
 883    usb_legacy_register("usb-tablet", "tablet", NULL);
 884    type_register_static(&usb_mouse_info);
 885    usb_legacy_register("usb-mouse", "mouse", NULL);
 886    type_register_static(&usb_keyboard_info);
 887    usb_legacy_register("usb-kbd", "keyboard", NULL);
 888}
 889
 890type_init(usb_hid_register_types)
 891