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