4 * Copyright (c) 2005 Fabrice Bellard
5 * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com)
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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
25 #include "qemu/osdep.h"
27 #include "ui/console.h"
30 #include "qapi/error.h"
31 #include "qemu/timer.h"
32 #include "hw/input/hid.h"
34 /* HID interface requests */
35 #define GET_REPORT 0xa101
36 #define GET_IDLE 0xa102
37 #define GET_PROTOCOL 0xa103
38 #define SET_REPORT 0x2109
39 #define SET_IDLE 0x210a
40 #define SET_PROTOCOL 0x210b
42 /* HID descriptor types */
43 #define USB_DT_HID 0x21
44 #define USB_DT_REPORT 0x22
45 #define USB_DT_PHY 0x23
47 typedef struct USBHIDState
{
56 #define TYPE_USB_HID "usb-hid"
57 #define USB_HID(obj) OBJECT_CHECK(USBHIDState, (obj), TYPE_USB_HID)
73 static const USBDescStrings desc_strings
= {
74 [STR_MANUFACTURER
] = "QEMU",
75 [STR_PRODUCT_MOUSE
] = "QEMU USB Mouse",
76 [STR_PRODUCT_TABLET
] = "QEMU USB Tablet",
77 [STR_PRODUCT_KEYBOARD
] = "QEMU USB Keyboard",
78 [STR_SERIAL_COMPAT
] = "42",
79 [STR_CONFIG_MOUSE
] = "HID Mouse",
80 [STR_CONFIG_TABLET
] = "HID Tablet",
81 [STR_CONFIG_KEYBOARD
] = "HID Keyboard",
82 [STR_SERIAL_MOUSE
] = "89126",
83 [STR_SERIAL_TABLET
] = "28754",
84 [STR_SERIAL_KEYBOARD
] = "68284",
87 static const USBDescIface desc_iface_mouse
= {
88 .bInterfaceNumber
= 0,
90 .bInterfaceClass
= USB_CLASS_HID
,
91 .bInterfaceSubClass
= 0x01, /* boot */
92 .bInterfaceProtocol
= 0x02,
94 .descs
= (USBDescOther
[]) {
98 0x09, /* u8 bLength */
99 USB_DT_HID
, /* u8 bDescriptorType */
100 0x01, 0x00, /* u16 HID_class */
101 0x00, /* u8 country_code */
102 0x01, /* u8 num_descriptors */
103 USB_DT_REPORT
, /* u8 type: Report */
108 .eps
= (USBDescEndpoint
[]) {
110 .bEndpointAddress
= USB_DIR_IN
| 0x01,
111 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
118 static const USBDescIface desc_iface_mouse2
= {
119 .bInterfaceNumber
= 0,
121 .bInterfaceClass
= USB_CLASS_HID
,
122 .bInterfaceSubClass
= 0x01, /* boot */
123 .bInterfaceProtocol
= 0x02,
125 .descs
= (USBDescOther
[]) {
128 .data
= (uint8_t[]) {
129 0x09, /* u8 bLength */
130 USB_DT_HID
, /* u8 bDescriptorType */
131 0x01, 0x00, /* u16 HID_class */
132 0x00, /* u8 country_code */
133 0x01, /* u8 num_descriptors */
134 USB_DT_REPORT
, /* u8 type: Report */
139 .eps
= (USBDescEndpoint
[]) {
141 .bEndpointAddress
= USB_DIR_IN
| 0x01,
142 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
144 .bInterval
= 7, /* 2 ^ (8-1) * 125 usecs = 8 ms */
149 static const USBDescIface desc_iface_tablet
= {
150 .bInterfaceNumber
= 0,
152 .bInterfaceClass
= USB_CLASS_HID
,
153 .bInterfaceProtocol
= 0x00,
155 .descs
= (USBDescOther
[]) {
158 .data
= (uint8_t[]) {
159 0x09, /* u8 bLength */
160 USB_DT_HID
, /* u8 bDescriptorType */
161 0x01, 0x00, /* u16 HID_class */
162 0x00, /* u8 country_code */
163 0x01, /* u8 num_descriptors */
164 USB_DT_REPORT
, /* u8 type: Report */
169 .eps
= (USBDescEndpoint
[]) {
171 .bEndpointAddress
= USB_DIR_IN
| 0x01,
172 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
179 static const USBDescIface desc_iface_tablet2
= {
180 .bInterfaceNumber
= 0,
182 .bInterfaceClass
= USB_CLASS_HID
,
183 .bInterfaceProtocol
= 0x00,
185 .descs
= (USBDescOther
[]) {
188 .data
= (uint8_t[]) {
189 0x09, /* u8 bLength */
190 USB_DT_HID
, /* u8 bDescriptorType */
191 0x01, 0x00, /* u16 HID_class */
192 0x00, /* u8 country_code */
193 0x01, /* u8 num_descriptors */
194 USB_DT_REPORT
, /* u8 type: Report */
199 .eps
= (USBDescEndpoint
[]) {
201 .bEndpointAddress
= USB_DIR_IN
| 0x01,
202 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
204 .bInterval
= 4, /* 2 ^ (4-1) * 125 usecs = 1 ms */
209 static const USBDescIface desc_iface_keyboard
= {
210 .bInterfaceNumber
= 0,
212 .bInterfaceClass
= USB_CLASS_HID
,
213 .bInterfaceSubClass
= 0x01, /* boot */
214 .bInterfaceProtocol
= 0x01, /* keyboard */
216 .descs
= (USBDescOther
[]) {
219 .data
= (uint8_t[]) {
220 0x09, /* u8 bLength */
221 USB_DT_HID
, /* u8 bDescriptorType */
222 0x11, 0x01, /* u16 HID_class */
223 0x00, /* u8 country_code */
224 0x01, /* u8 num_descriptors */
225 USB_DT_REPORT
, /* u8 type: Report */
226 0x3f, 0, /* u16 len */
230 .eps
= (USBDescEndpoint
[]) {
232 .bEndpointAddress
= USB_DIR_IN
| 0x01,
233 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
240 static const USBDescIface desc_iface_keyboard2
= {
241 .bInterfaceNumber
= 0,
243 .bInterfaceClass
= USB_CLASS_HID
,
244 .bInterfaceSubClass
= 0x01, /* boot */
245 .bInterfaceProtocol
= 0x01, /* keyboard */
247 .descs
= (USBDescOther
[]) {
250 .data
= (uint8_t[]) {
251 0x09, /* u8 bLength */
252 USB_DT_HID
, /* u8 bDescriptorType */
253 0x11, 0x01, /* u16 HID_class */
254 0x00, /* u8 country_code */
255 0x01, /* u8 num_descriptors */
256 USB_DT_REPORT
, /* u8 type: Report */
257 0x3f, 0, /* u16 len */
261 .eps
= (USBDescEndpoint
[]) {
263 .bEndpointAddress
= USB_DIR_IN
| 0x01,
264 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
266 .bInterval
= 7, /* 2 ^ (8-1) * 125 usecs = 8 ms */
271 static const USBDescDevice desc_device_mouse
= {
273 .bMaxPacketSize0
= 8,
274 .bNumConfigurations
= 1,
275 .confs
= (USBDescConfig
[]) {
278 .bConfigurationValue
= 1,
279 .iConfiguration
= STR_CONFIG_MOUSE
,
280 .bmAttributes
= USB_CFG_ATT_ONE
| USB_CFG_ATT_WAKEUP
,
283 .ifs
= &desc_iface_mouse
,
288 static const USBDescDevice desc_device_mouse2
= {
290 .bMaxPacketSize0
= 64,
291 .bNumConfigurations
= 1,
292 .confs
= (USBDescConfig
[]) {
295 .bConfigurationValue
= 1,
296 .iConfiguration
= STR_CONFIG_MOUSE
,
297 .bmAttributes
= USB_CFG_ATT_ONE
| USB_CFG_ATT_WAKEUP
,
300 .ifs
= &desc_iface_mouse2
,
305 static const USBDescDevice desc_device_tablet
= {
307 .bMaxPacketSize0
= 8,
308 .bNumConfigurations
= 1,
309 .confs
= (USBDescConfig
[]) {
312 .bConfigurationValue
= 1,
313 .iConfiguration
= STR_CONFIG_TABLET
,
314 .bmAttributes
= USB_CFG_ATT_ONE
| USB_CFG_ATT_WAKEUP
,
317 .ifs
= &desc_iface_tablet
,
322 static const USBDescDevice desc_device_tablet2
= {
324 .bMaxPacketSize0
= 64,
325 .bNumConfigurations
= 1,
326 .confs
= (USBDescConfig
[]) {
329 .bConfigurationValue
= 1,
330 .iConfiguration
= STR_CONFIG_TABLET
,
331 .bmAttributes
= USB_CFG_ATT_ONE
| USB_CFG_ATT_WAKEUP
,
334 .ifs
= &desc_iface_tablet2
,
339 static const USBDescDevice desc_device_keyboard
= {
341 .bMaxPacketSize0
= 8,
342 .bNumConfigurations
= 1,
343 .confs
= (USBDescConfig
[]) {
346 .bConfigurationValue
= 1,
347 .iConfiguration
= STR_CONFIG_KEYBOARD
,
348 .bmAttributes
= USB_CFG_ATT_ONE
| USB_CFG_ATT_WAKEUP
,
351 .ifs
= &desc_iface_keyboard
,
356 static const USBDescDevice desc_device_keyboard2
= {
358 .bMaxPacketSize0
= 64,
359 .bNumConfigurations
= 1,
360 .confs
= (USBDescConfig
[]) {
363 .bConfigurationValue
= 1,
364 .iConfiguration
= STR_CONFIG_KEYBOARD
,
365 .bmAttributes
= USB_CFG_ATT_ONE
| USB_CFG_ATT_WAKEUP
,
368 .ifs
= &desc_iface_keyboard2
,
373 static const USBDescMSOS desc_msos_suspend
= {
374 .SelectiveSuspendEnabled
= true,
377 static const USBDesc desc_mouse
= {
382 .iManufacturer
= STR_MANUFACTURER
,
383 .iProduct
= STR_PRODUCT_MOUSE
,
384 .iSerialNumber
= STR_SERIAL_MOUSE
,
386 .full
= &desc_device_mouse
,
388 .msos
= &desc_msos_suspend
,
391 static const USBDesc desc_mouse2
= {
396 .iManufacturer
= STR_MANUFACTURER
,
397 .iProduct
= STR_PRODUCT_MOUSE
,
398 .iSerialNumber
= STR_SERIAL_MOUSE
,
400 .full
= &desc_device_mouse
,
401 .high
= &desc_device_mouse2
,
403 .msos
= &desc_msos_suspend
,
406 static const USBDesc desc_tablet
= {
411 .iManufacturer
= STR_MANUFACTURER
,
412 .iProduct
= STR_PRODUCT_TABLET
,
413 .iSerialNumber
= STR_SERIAL_TABLET
,
415 .full
= &desc_device_tablet
,
417 .msos
= &desc_msos_suspend
,
420 static const USBDesc desc_tablet2
= {
425 .iManufacturer
= STR_MANUFACTURER
,
426 .iProduct
= STR_PRODUCT_TABLET
,
427 .iSerialNumber
= STR_SERIAL_TABLET
,
429 .full
= &desc_device_tablet
,
430 .high
= &desc_device_tablet2
,
432 .msos
= &desc_msos_suspend
,
435 static const USBDesc desc_keyboard
= {
440 .iManufacturer
= STR_MANUFACTURER
,
441 .iProduct
= STR_PRODUCT_KEYBOARD
,
442 .iSerialNumber
= STR_SERIAL_KEYBOARD
,
444 .full
= &desc_device_keyboard
,
446 .msos
= &desc_msos_suspend
,
449 static const USBDesc desc_keyboard2
= {
454 .iManufacturer
= STR_MANUFACTURER
,
455 .iProduct
= STR_PRODUCT_KEYBOARD
,
456 .iSerialNumber
= STR_SERIAL_KEYBOARD
,
458 .full
= &desc_device_keyboard
,
459 .high
= &desc_device_keyboard2
,
461 .msos
= &desc_msos_suspend
,
464 static const uint8_t qemu_mouse_hid_report_descriptor
[] = {
465 0x05, 0x01, /* Usage Page (Generic Desktop) */
466 0x09, 0x02, /* Usage (Mouse) */
467 0xa1, 0x01, /* Collection (Application) */
468 0x09, 0x01, /* Usage (Pointer) */
469 0xa1, 0x00, /* Collection (Physical) */
470 0x05, 0x09, /* Usage Page (Button) */
471 0x19, 0x01, /* Usage Minimum (1) */
472 0x29, 0x03, /* Usage Maximum (3) */
473 0x15, 0x00, /* Logical Minimum (0) */
474 0x25, 0x01, /* Logical Maximum (1) */
475 0x95, 0x03, /* Report Count (3) */
476 0x75, 0x01, /* Report Size (1) */
477 0x81, 0x02, /* Input (Data, Variable, Absolute) */
478 0x95, 0x01, /* Report Count (1) */
479 0x75, 0x05, /* Report Size (5) */
480 0x81, 0x01, /* Input (Constant) */
481 0x05, 0x01, /* Usage Page (Generic Desktop) */
482 0x09, 0x30, /* Usage (X) */
483 0x09, 0x31, /* Usage (Y) */
484 0x09, 0x38, /* Usage (Wheel) */
485 0x15, 0x81, /* Logical Minimum (-0x7f) */
486 0x25, 0x7f, /* Logical Maximum (0x7f) */
487 0x75, 0x08, /* Report Size (8) */
488 0x95, 0x03, /* Report Count (3) */
489 0x81, 0x06, /* Input (Data, Variable, Relative) */
490 0xc0, /* End Collection */
491 0xc0, /* End Collection */
494 static const uint8_t qemu_tablet_hid_report_descriptor
[] = {
495 0x05, 0x01, /* Usage Page (Generic Desktop) */
496 0x09, 0x02, /* Usage (Mouse) */
497 0xa1, 0x01, /* Collection (Application) */
498 0x09, 0x01, /* Usage (Pointer) */
499 0xa1, 0x00, /* Collection (Physical) */
500 0x05, 0x09, /* Usage Page (Button) */
501 0x19, 0x01, /* Usage Minimum (1) */
502 0x29, 0x03, /* Usage Maximum (3) */
503 0x15, 0x00, /* Logical Minimum (0) */
504 0x25, 0x01, /* Logical Maximum (1) */
505 0x95, 0x03, /* Report Count (3) */
506 0x75, 0x01, /* Report Size (1) */
507 0x81, 0x02, /* Input (Data, Variable, Absolute) */
508 0x95, 0x01, /* Report Count (1) */
509 0x75, 0x05, /* Report Size (5) */
510 0x81, 0x01, /* Input (Constant) */
511 0x05, 0x01, /* Usage Page (Generic Desktop) */
512 0x09, 0x30, /* Usage (X) */
513 0x09, 0x31, /* Usage (Y) */
514 0x15, 0x00, /* Logical Minimum (0) */
515 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
516 0x35, 0x00, /* Physical Minimum (0) */
517 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
518 0x75, 0x10, /* Report Size (16) */
519 0x95, 0x02, /* Report Count (2) */
520 0x81, 0x02, /* Input (Data, Variable, Absolute) */
521 0x05, 0x01, /* Usage Page (Generic Desktop) */
522 0x09, 0x38, /* Usage (Wheel) */
523 0x15, 0x81, /* Logical Minimum (-0x7f) */
524 0x25, 0x7f, /* Logical Maximum (0x7f) */
525 0x35, 0x00, /* Physical Minimum (same as logical) */
526 0x45, 0x00, /* Physical Maximum (same as logical) */
527 0x75, 0x08, /* Report Size (8) */
528 0x95, 0x01, /* Report Count (1) */
529 0x81, 0x06, /* Input (Data, Variable, Relative) */
530 0xc0, /* End Collection */
531 0xc0, /* End Collection */
534 static const uint8_t qemu_keyboard_hid_report_descriptor
[] = {
535 0x05, 0x01, /* Usage Page (Generic Desktop) */
536 0x09, 0x06, /* Usage (Keyboard) */
537 0xa1, 0x01, /* Collection (Application) */
538 0x75, 0x01, /* Report Size (1) */
539 0x95, 0x08, /* Report Count (8) */
540 0x05, 0x07, /* Usage Page (Key Codes) */
541 0x19, 0xe0, /* Usage Minimum (224) */
542 0x29, 0xe7, /* Usage Maximum (231) */
543 0x15, 0x00, /* Logical Minimum (0) */
544 0x25, 0x01, /* Logical Maximum (1) */
545 0x81, 0x02, /* Input (Data, Variable, Absolute) */
546 0x95, 0x01, /* Report Count (1) */
547 0x75, 0x08, /* Report Size (8) */
548 0x81, 0x01, /* Input (Constant) */
549 0x95, 0x05, /* Report Count (5) */
550 0x75, 0x01, /* Report Size (1) */
551 0x05, 0x08, /* Usage Page (LEDs) */
552 0x19, 0x01, /* Usage Minimum (1) */
553 0x29, 0x05, /* Usage Maximum (5) */
554 0x91, 0x02, /* Output (Data, Variable, Absolute) */
555 0x95, 0x01, /* Report Count (1) */
556 0x75, 0x03, /* Report Size (3) */
557 0x91, 0x01, /* Output (Constant) */
558 0x95, 0x06, /* Report Count (6) */
559 0x75, 0x08, /* Report Size (8) */
560 0x15, 0x00, /* Logical Minimum (0) */
561 0x25, 0xff, /* Logical Maximum (255) */
562 0x05, 0x07, /* Usage Page (Key Codes) */
563 0x19, 0x00, /* Usage Minimum (0) */
564 0x29, 0xff, /* Usage Maximum (255) */
565 0x81, 0x00, /* Input (Data, Array) */
566 0xc0, /* End Collection */
569 static void usb_hid_changed(HIDState
*hs
)
571 USBHIDState
*us
= container_of(hs
, USBHIDState
, hid
);
573 usb_wakeup(us
->intr
, 0);
576 static void usb_hid_handle_reset(USBDevice
*dev
)
578 USBHIDState
*us
= USB_HID(dev
);
583 static void usb_hid_handle_control(USBDevice
*dev
, USBPacket
*p
,
584 int request
, int value
, int index
, int length
, uint8_t *data
)
586 USBHIDState
*us
= USB_HID(dev
);
587 HIDState
*hs
= &us
->hid
;
590 ret
= usb_desc_handle_control(dev
, p
, request
, value
, index
, length
, data
);
596 /* hid specific requests */
597 case InterfaceRequest
| USB_REQ_GET_DESCRIPTOR
:
598 switch (value
>> 8) {
600 if (hs
->kind
== HID_MOUSE
) {
601 memcpy(data
, qemu_mouse_hid_report_descriptor
,
602 sizeof(qemu_mouse_hid_report_descriptor
));
603 p
->actual_length
= sizeof(qemu_mouse_hid_report_descriptor
);
604 } else if (hs
->kind
== HID_TABLET
) {
605 memcpy(data
, qemu_tablet_hid_report_descriptor
,
606 sizeof(qemu_tablet_hid_report_descriptor
));
607 p
->actual_length
= sizeof(qemu_tablet_hid_report_descriptor
);
608 } else if (hs
->kind
== HID_KEYBOARD
) {
609 memcpy(data
, qemu_keyboard_hid_report_descriptor
,
610 sizeof(qemu_keyboard_hid_report_descriptor
));
611 p
->actual_length
= sizeof(qemu_keyboard_hid_report_descriptor
);
619 if (hs
->kind
== HID_MOUSE
|| hs
->kind
== HID_TABLET
) {
620 p
->actual_length
= hid_pointer_poll(hs
, data
, length
);
621 } else if (hs
->kind
== HID_KEYBOARD
) {
622 p
->actual_length
= hid_keyboard_poll(hs
, data
, length
);
626 if (hs
->kind
== HID_KEYBOARD
) {
627 p
->actual_length
= hid_keyboard_write(hs
, data
, length
);
633 if (hs
->kind
!= HID_KEYBOARD
&& hs
->kind
!= HID_MOUSE
) {
636 data
[0] = hs
->protocol
;
637 p
->actual_length
= 1;
640 if (hs
->kind
!= HID_KEYBOARD
&& hs
->kind
!= HID_MOUSE
) {
643 hs
->protocol
= value
;
647 p
->actual_length
= 1;
650 hs
->idle
= (uint8_t) (value
>> 8);
651 hid_set_next_idle(hs
);
652 if (hs
->kind
== HID_MOUSE
|| hs
->kind
== HID_TABLET
) {
653 hid_pointer_activate(hs
);
658 p
->status
= USB_RET_STALL
;
663 static void usb_hid_handle_data(USBDevice
*dev
, USBPacket
*p
)
665 USBHIDState
*us
= USB_HID(dev
);
666 HIDState
*hs
= &us
->hid
;
667 uint8_t buf
[p
->iov
.size
];
672 if (p
->ep
->nr
== 1) {
673 if (hs
->kind
== HID_MOUSE
|| hs
->kind
== HID_TABLET
) {
674 hid_pointer_activate(hs
);
676 if (!hid_has_events(hs
)) {
677 p
->status
= USB_RET_NAK
;
680 hid_set_next_idle(hs
);
681 if (hs
->kind
== HID_MOUSE
|| hs
->kind
== HID_TABLET
) {
682 len
= hid_pointer_poll(hs
, buf
, p
->iov
.size
);
683 } else if (hs
->kind
== HID_KEYBOARD
) {
684 len
= hid_keyboard_poll(hs
, buf
, p
->iov
.size
);
686 usb_packet_copy(p
, buf
, len
);
694 p
->status
= USB_RET_STALL
;
699 static void usb_hid_unrealize(USBDevice
*dev
, Error
**errp
)
701 USBHIDState
*us
= USB_HID(dev
);
706 static void usb_hid_initfn(USBDevice
*dev
, int kind
,
707 const USBDesc
*usb1
, const USBDesc
*usb2
,
710 USBHIDState
*us
= USB_HID(dev
);
711 switch (us
->usb_version
) {
713 dev
->usb_desc
= usb1
;
716 dev
->usb_desc
= usb2
;
719 dev
->usb_desc
= NULL
;
721 if (!dev
->usb_desc
) {
722 error_setg(errp
, "Invalid usb version %d for usb hid device",
727 usb_desc_create_serial(dev
);
729 us
->intr
= usb_ep_get(dev
, USB_TOKEN_IN
, 1);
730 hid_init(&us
->hid
, kind
, usb_hid_changed
);
731 if (us
->display
&& us
->hid
.s
) {
732 qemu_input_handler_bind(us
->hid
.s
, us
->display
, us
->head
, NULL
);
736 static void usb_tablet_realize(USBDevice
*dev
, Error
**errp
)
739 usb_hid_initfn(dev
, HID_TABLET
, &desc_tablet
, &desc_tablet2
, errp
);
742 static void usb_mouse_realize(USBDevice
*dev
, Error
**errp
)
744 usb_hid_initfn(dev
, HID_MOUSE
, &desc_mouse
, &desc_mouse2
, errp
);
747 static void usb_keyboard_realize(USBDevice
*dev
, Error
**errp
)
749 usb_hid_initfn(dev
, HID_KEYBOARD
, &desc_keyboard
, &desc_keyboard2
, errp
);
752 static int usb_ptr_post_load(void *opaque
, int version_id
)
754 USBHIDState
*s
= opaque
;
756 if (s
->dev
.remote_wakeup
) {
757 hid_pointer_activate(&s
->hid
);
762 static const VMStateDescription vmstate_usb_ptr
= {
765 .minimum_version_id
= 1,
766 .post_load
= usb_ptr_post_load
,
767 .fields
= (VMStateField
[]) {
768 VMSTATE_USB_DEVICE(dev
, USBHIDState
),
769 VMSTATE_HID_POINTER_DEVICE(hid
, USBHIDState
),
770 VMSTATE_END_OF_LIST()
774 static const VMStateDescription vmstate_usb_kbd
= {
777 .minimum_version_id
= 1,
778 .fields
= (VMStateField
[]) {
779 VMSTATE_USB_DEVICE(dev
, USBHIDState
),
780 VMSTATE_HID_KEYBOARD_DEVICE(hid
, USBHIDState
),
781 VMSTATE_END_OF_LIST()
785 static void usb_hid_class_initfn(ObjectClass
*klass
, void *data
)
787 USBDeviceClass
*uc
= USB_DEVICE_CLASS(klass
);
789 uc
->handle_reset
= usb_hid_handle_reset
;
790 uc
->handle_control
= usb_hid_handle_control
;
791 uc
->handle_data
= usb_hid_handle_data
;
792 uc
->unrealize
= usb_hid_unrealize
;
793 uc
->handle_attach
= usb_desc_attach
;
796 static const TypeInfo usb_hid_type_info
= {
797 .name
= TYPE_USB_HID
,
798 .parent
= TYPE_USB_DEVICE
,
799 .instance_size
= sizeof(USBHIDState
),
801 .class_init
= usb_hid_class_initfn
,
804 static Property usb_tablet_properties
[] = {
805 DEFINE_PROP_UINT32("usb_version", USBHIDState
, usb_version
, 2),
806 DEFINE_PROP_STRING("display", USBHIDState
, display
),
807 DEFINE_PROP_UINT32("head", USBHIDState
, head
, 0),
808 DEFINE_PROP_END_OF_LIST(),
811 static void usb_tablet_class_initfn(ObjectClass
*klass
, void *data
)
813 DeviceClass
*dc
= DEVICE_CLASS(klass
);
814 USBDeviceClass
*uc
= USB_DEVICE_CLASS(klass
);
816 uc
->realize
= usb_tablet_realize
;
817 uc
->product_desc
= "QEMU USB Tablet";
818 dc
->vmsd
= &vmstate_usb_ptr
;
819 dc
->props
= usb_tablet_properties
;
820 set_bit(DEVICE_CATEGORY_INPUT
, dc
->categories
);
823 static const TypeInfo usb_tablet_info
= {
824 .name
= "usb-tablet",
825 .parent
= TYPE_USB_HID
,
826 .class_init
= usb_tablet_class_initfn
,
829 static Property usb_mouse_properties
[] = {
830 DEFINE_PROP_UINT32("usb_version", USBHIDState
, usb_version
, 2),
831 DEFINE_PROP_END_OF_LIST(),
834 static void usb_mouse_class_initfn(ObjectClass
*klass
, void *data
)
836 DeviceClass
*dc
= DEVICE_CLASS(klass
);
837 USBDeviceClass
*uc
= USB_DEVICE_CLASS(klass
);
839 uc
->realize
= usb_mouse_realize
;
840 uc
->product_desc
= "QEMU USB Mouse";
841 dc
->vmsd
= &vmstate_usb_ptr
;
842 dc
->props
= usb_mouse_properties
;
843 set_bit(DEVICE_CATEGORY_INPUT
, dc
->categories
);
846 static const TypeInfo usb_mouse_info
= {
848 .parent
= TYPE_USB_HID
,
849 .class_init
= usb_mouse_class_initfn
,
852 static Property usb_keyboard_properties
[] = {
853 DEFINE_PROP_UINT32("usb_version", USBHIDState
, usb_version
, 2),
854 DEFINE_PROP_STRING("display", USBHIDState
, display
),
855 DEFINE_PROP_END_OF_LIST(),
858 static void usb_keyboard_class_initfn(ObjectClass
*klass
, void *data
)
860 DeviceClass
*dc
= DEVICE_CLASS(klass
);
861 USBDeviceClass
*uc
= USB_DEVICE_CLASS(klass
);
863 uc
->realize
= usb_keyboard_realize
;
864 uc
->product_desc
= "QEMU USB Keyboard";
865 dc
->vmsd
= &vmstate_usb_kbd
;
866 dc
->props
= usb_keyboard_properties
;
867 set_bit(DEVICE_CATEGORY_INPUT
, dc
->categories
);
870 static const TypeInfo usb_keyboard_info
= {
872 .parent
= TYPE_USB_HID
,
873 .class_init
= usb_keyboard_class_initfn
,
876 static void usb_hid_register_types(void)
878 type_register_static(&usb_hid_type_info
);
879 type_register_static(&usb_tablet_info
);
880 usb_legacy_register("usb-tablet", "tablet", NULL
);
881 type_register_static(&usb_mouse_info
);
882 usb_legacy_register("usb-mouse", "mouse", NULL
);
883 type_register_static(&usb_keyboard_info
);
884 usb_legacy_register("usb-kbd", "keyboard", NULL
);
887 type_init(usb_hid_register_types
)