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#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
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
41#define USB_DT_HID 0x21
42#define USB_DT_REPORT 0x22
43#define USB_DT_PHY 0x23
44
45typedef 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#define TYPE_USB_HID "usb-hid"
55#define USB_HID(obj) OBJECT_CHECK(USBHIDState, (obj), TYPE_USB_HID)
56
57enum {
58 STR_MANUFACTURER = 1,
59 STR_PRODUCT_MOUSE,
60 STR_PRODUCT_TABLET,
61 STR_PRODUCT_KEYBOARD,
62 STR_SERIALNUMBER,
63 STR_CONFIG_MOUSE,
64 STR_CONFIG_TABLET,
65 STR_CONFIG_KEYBOARD,
66};
67
68static const USBDescStrings desc_strings = {
69 [STR_MANUFACTURER] = "QEMU",
70 [STR_PRODUCT_MOUSE] = "QEMU USB Mouse",
71 [STR_PRODUCT_TABLET] = "QEMU USB Tablet",
72 [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
73 [STR_SERIALNUMBER] = "42",
74 [STR_CONFIG_MOUSE] = "HID Mouse",
75 [STR_CONFIG_TABLET] = "HID Tablet",
76 [STR_CONFIG_KEYBOARD] = "HID Keyboard",
77};
78
79static const USBDescIface desc_iface_mouse = {
80 .bInterfaceNumber = 0,
81 .bNumEndpoints = 1,
82 .bInterfaceClass = USB_CLASS_HID,
83 .bInterfaceSubClass = 0x01,
84 .bInterfaceProtocol = 0x02,
85 .ndesc = 1,
86 .descs = (USBDescOther[]) {
87 {
88
89 .data = (uint8_t[]) {
90 0x09,
91 USB_DT_HID,
92 0x01, 0x00,
93 0x00,
94 0x01,
95 USB_DT_REPORT,
96 52, 0,
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,
115 .bInterfaceProtocol = 0x02,
116 .ndesc = 1,
117 .descs = (USBDescOther[]) {
118 {
119
120 .data = (uint8_t[]) {
121 0x09,
122 USB_DT_HID,
123 0x01, 0x00,
124 0x00,
125 0x01,
126 USB_DT_REPORT,
127 52, 0,
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,
137 },
138 },
139};
140
141static const USBDescIface desc_iface_tablet = {
142 .bInterfaceNumber = 0,
143 .bNumEndpoints = 1,
144 .bInterfaceClass = USB_CLASS_HID,
145 .bInterfaceProtocol = 0x02,
146 .ndesc = 1,
147 .descs = (USBDescOther[]) {
148 {
149
150 .data = (uint8_t[]) {
151 0x09,
152 USB_DT_HID,
153 0x01, 0x00,
154 0x00,
155 0x01,
156 USB_DT_REPORT,
157 74, 0,
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 = 0x02,
176 .ndesc = 1,
177 .descs = (USBDescOther[]) {
178 {
179
180 .data = (uint8_t[]) {
181 0x09,
182 USB_DT_HID,
183 0x01, 0x00,
184 0x00,
185 0x01,
186 USB_DT_REPORT,
187 74, 0,
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,
197 },
198 },
199};
200
201static const USBDescIface desc_iface_keyboard = {
202 .bInterfaceNumber = 0,
203 .bNumEndpoints = 1,
204 .bInterfaceClass = USB_CLASS_HID,
205 .bInterfaceSubClass = 0x01,
206 .bInterfaceProtocol = 0x01,
207 .ndesc = 1,
208 .descs = (USBDescOther[]) {
209 {
210
211 .data = (uint8_t[]) {
212 0x09,
213 USB_DT_HID,
214 0x11, 0x01,
215 0x00,
216 0x01,
217 USB_DT_REPORT,
218 0x3f, 0,
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,
237 .bInterfaceProtocol = 0x01,
238 .ndesc = 1,
239 .descs = (USBDescOther[]) {
240 {
241
242 .data = (uint8_t[]) {
243 0x09,
244 USB_DT_HID,
245 0x11, 0x01,
246 0x00,
247 0x01,
248 USB_DT_REPORT,
249 0x3f, 0,
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,
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_SERIALNUMBER,
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_SERIALNUMBER,
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_SERIALNUMBER,
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_SERIALNUMBER,
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_SERIALNUMBER,
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_SERIALNUMBER,
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,
458 0x09, 0x02,
459 0xa1, 0x01,
460 0x09, 0x01,
461 0xa1, 0x00,
462 0x05, 0x09,
463 0x19, 0x01,
464 0x29, 0x03,
465 0x15, 0x00,
466 0x25, 0x01,
467 0x95, 0x03,
468 0x75, 0x01,
469 0x81, 0x02,
470 0x95, 0x01,
471 0x75, 0x05,
472 0x81, 0x01,
473 0x05, 0x01,
474 0x09, 0x30,
475 0x09, 0x31,
476 0x09, 0x38,
477 0x15, 0x81,
478 0x25, 0x7f,
479 0x75, 0x08,
480 0x95, 0x03,
481 0x81, 0x06,
482 0xc0,
483 0xc0,
484};
485
486static const uint8_t qemu_tablet_hid_report_descriptor[] = {
487 0x05, 0x01,
488 0x09, 0x01,
489 0xa1, 0x01,
490 0x09, 0x01,
491 0xa1, 0x00,
492 0x05, 0x09,
493 0x19, 0x01,
494 0x29, 0x03,
495 0x15, 0x00,
496 0x25, 0x01,
497 0x95, 0x03,
498 0x75, 0x01,
499 0x81, 0x02,
500 0x95, 0x01,
501 0x75, 0x05,
502 0x81, 0x01,
503 0x05, 0x01,
504 0x09, 0x30,
505 0x09, 0x31,
506 0x15, 0x00,
507 0x26, 0xff, 0x7f,
508 0x35, 0x00,
509 0x46, 0xff, 0x7f,
510 0x75, 0x10,
511 0x95, 0x02,
512 0x81, 0x02,
513 0x05, 0x01,
514 0x09, 0x38,
515 0x15, 0x81,
516 0x25, 0x7f,
517 0x35, 0x00,
518 0x45, 0x00,
519 0x75, 0x08,
520 0x95, 0x01,
521 0x81, 0x06,
522 0xc0,
523 0xc0,
524};
525
526static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
527 0x05, 0x01,
528 0x09, 0x06,
529 0xa1, 0x01,
530 0x75, 0x01,
531 0x95, 0x08,
532 0x05, 0x07,
533 0x19, 0xe0,
534 0x29, 0xe7,
535 0x15, 0x00,
536 0x25, 0x01,
537 0x81, 0x02,
538 0x95, 0x01,
539 0x75, 0x08,
540 0x81, 0x01,
541 0x95, 0x05,
542 0x75, 0x01,
543 0x05, 0x08,
544 0x19, 0x01,
545 0x29, 0x05,
546 0x91, 0x02,
547 0x95, 0x01,
548 0x75, 0x03,
549 0x91, 0x01,
550 0x95, 0x06,
551 0x75, 0x08,
552 0x15, 0x00,
553 0x25, 0xff,
554 0x05, 0x07,
555 0x19, 0x00,
556 0x29, 0xff,
557 0x81, 0x00,
558 0xc0,
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
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 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 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 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 SET_PROTOCOL:
632 if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
633 goto fail;
634 }
635 hs->protocol = value;
636 break;
637 case GET_IDLE:
638 data[0] = hs->idle;
639 p->actual_length = 1;
640 break;
641 case 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 uint8_t buf[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_handle_destroy(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 if (dev->serial) {
720 usb_desc_set_string(dev, STR_SERIALNUMBER, dev->serial);
721 }
722 usb_desc_init(dev);
723 us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
724 hid_init(&us->hid, kind, usb_hid_changed);
725 if (us->display && us->hid.s) {
726 qemu_input_handler_bind(us->hid.s, us->display, us->head, NULL);
727 }
728}
729
730static void usb_tablet_realize(USBDevice *dev, Error **errp)
731{
732
733 usb_hid_initfn(dev, HID_TABLET, &desc_tablet, &desc_tablet2, errp);
734}
735
736static void usb_mouse_realize(USBDevice *dev, Error **errp)
737{
738 usb_hid_initfn(dev, HID_MOUSE, &desc_mouse, &desc_mouse2, errp);
739}
740
741static void usb_keyboard_realize(USBDevice *dev, Error **errp)
742{
743 usb_hid_initfn(dev, HID_KEYBOARD, &desc_keyboard, &desc_keyboard2, errp);
744}
745
746static int usb_ptr_post_load(void *opaque, int version_id)
747{
748 USBHIDState *s = opaque;
749
750 if (s->dev.remote_wakeup) {
751 hid_pointer_activate(&s->hid);
752 }
753 return 0;
754}
755
756static const VMStateDescription vmstate_usb_ptr = {
757 .name = "usb-ptr",
758 .version_id = 1,
759 .minimum_version_id = 1,
760 .post_load = usb_ptr_post_load,
761 .fields = (VMStateField[]) {
762 VMSTATE_USB_DEVICE(dev, USBHIDState),
763 VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
764 VMSTATE_END_OF_LIST()
765 }
766};
767
768static const VMStateDescription vmstate_usb_kbd = {
769 .name = "usb-kbd",
770 .version_id = 1,
771 .minimum_version_id = 1,
772 .fields = (VMStateField[]) {
773 VMSTATE_USB_DEVICE(dev, USBHIDState),
774 VMSTATE_HID_KEYBOARD_DEVICE(hid, USBHIDState),
775 VMSTATE_END_OF_LIST()
776 }
777};
778
779static void usb_hid_class_initfn(ObjectClass *klass, void *data)
780{
781 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
782
783 uc->handle_reset = usb_hid_handle_reset;
784 uc->handle_control = usb_hid_handle_control;
785 uc->handle_data = usb_hid_handle_data;
786 uc->handle_destroy = usb_hid_handle_destroy;
787 uc->handle_attach = usb_desc_attach;
788}
789
790static const TypeInfo usb_hid_type_info = {
791 .name = TYPE_USB_HID,
792 .parent = TYPE_USB_DEVICE,
793 .instance_size = sizeof(USBHIDState),
794 .abstract = true,
795 .class_init = usb_hid_class_initfn,
796};
797
798static Property usb_tablet_properties[] = {
799 DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
800 DEFINE_PROP_STRING("display", USBHIDState, display),
801 DEFINE_PROP_UINT32("head", USBHIDState, head, 0),
802 DEFINE_PROP_END_OF_LIST(),
803};
804
805static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
806{
807 DeviceClass *dc = DEVICE_CLASS(klass);
808 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
809
810 uc->realize = usb_tablet_realize;
811 uc->product_desc = "QEMU USB Tablet";
812 dc->vmsd = &vmstate_usb_ptr;
813 dc->props = usb_tablet_properties;
814 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
815}
816
817static const TypeInfo usb_tablet_info = {
818 .name = "usb-tablet",
819 .parent = TYPE_USB_HID,
820 .class_init = usb_tablet_class_initfn,
821};
822
823static Property usb_mouse_properties[] = {
824 DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
825 DEFINE_PROP_END_OF_LIST(),
826};
827
828static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
829{
830 DeviceClass *dc = DEVICE_CLASS(klass);
831 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
832
833 uc->realize = usb_mouse_realize;
834 uc->product_desc = "QEMU USB Mouse";
835 dc->vmsd = &vmstate_usb_ptr;
836 dc->props = usb_mouse_properties;
837 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
838}
839
840static const TypeInfo usb_mouse_info = {
841 .name = "usb-mouse",
842 .parent = TYPE_USB_HID,
843 .class_init = usb_mouse_class_initfn,
844};
845
846static Property usb_keyboard_properties[] = {
847 DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
848 DEFINE_PROP_STRING("display", USBHIDState, display),
849 DEFINE_PROP_END_OF_LIST(),
850};
851
852static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
853{
854 DeviceClass *dc = DEVICE_CLASS(klass);
855 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
856
857 uc->realize = usb_keyboard_realize;
858 uc->product_desc = "QEMU USB Keyboard";
859 dc->vmsd = &vmstate_usb_kbd;
860 dc->props = usb_keyboard_properties;
861 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
862}
863
864static const TypeInfo usb_keyboard_info = {
865 .name = "usb-kbd",
866 .parent = TYPE_USB_HID,
867 .class_init = usb_keyboard_class_initfn,
868};
869
870static void usb_hid_register_types(void)
871{
872 type_register_static(&usb_hid_type_info);
873 type_register_static(&usb_tablet_info);
874 usb_legacy_register("usb-tablet", "tablet", NULL);
875 type_register_static(&usb_mouse_info);
876 usb_legacy_register("usb-mouse", "mouse", NULL);
877 type_register_static(&usb_keyboard_info);
878 usb_legacy_register("usb-kbd", "keyboard", NULL);
879}
880
881type_init(usb_hid_register_types)
882