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