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