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