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