cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

dev-hid.c (29043B)


      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    g_autofree uint8_t *buf = g_malloc(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)