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/usb/hid.h"
36#include "hw/qdev-properties.h"
37#include "qom/object.h"
38
39struct USBHIDState {
40 USBDevice dev;
41 USBEndpoint *intr;
42 HIDState hid;
43 uint32_t usb_version;
44 char *display;
45 uint32_t head;
46};
47
48#define TYPE_USB_HID "usb-hid"
49OBJECT_DECLARE_SIMPLE_TYPE(USBHIDState, USB_HID)
50
51enum {
52 STR_MANUFACTURER = 1,
53 STR_PRODUCT_MOUSE,
54 STR_PRODUCT_TABLET,
55 STR_PRODUCT_KEYBOARD,
56 STR_SERIAL_COMPAT,
57 STR_CONFIG_MOUSE,
58 STR_CONFIG_TABLET,
59 STR_CONFIG_KEYBOARD,
60 STR_SERIAL_MOUSE,
61 STR_SERIAL_TABLET,
62 STR_SERIAL_KEYBOARD,
63};
64
65static const USBDescStrings desc_strings = {
66 [STR_MANUFACTURER] = "QEMU",
67 [STR_PRODUCT_MOUSE] = "QEMU USB Mouse",
68 [STR_PRODUCT_TABLET] = "QEMU USB Tablet",
69 [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
70 [STR_SERIAL_COMPAT] = "42",
71 [STR_CONFIG_MOUSE] = "HID Mouse",
72 [STR_CONFIG_TABLET] = "HID Tablet",
73 [STR_CONFIG_KEYBOARD] = "HID Keyboard",
74 [STR_SERIAL_MOUSE] = "89126",
75 [STR_SERIAL_TABLET] = "28754",
76 [STR_SERIAL_KEYBOARD] = "68284",
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 = 0x00,
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 = 0x00,
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_SERIAL_MOUSE,
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_SERIAL_MOUSE,
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_SERIAL_TABLET,
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_SERIAL_TABLET,
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_SERIAL_KEYBOARD,
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_SERIAL_KEYBOARD,
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, 0x02,
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 HID_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 HID_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 HID_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 HID_SET_PROTOCOL:
632 if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
633 goto fail;
634 }
635 hs->protocol = value;
636 break;
637 case HID_GET_IDLE:
638 data[0] = hs->idle;
639 p->actual_length = 1;
640 break;
641 case HID_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_unrealize(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 usb_desc_create_serial(dev);
720 usb_desc_init(dev);
721 us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
722 hid_init(&us->hid, kind, usb_hid_changed);
723 if (us->display && us->hid.s) {
724 qemu_input_handler_bind(us->hid.s, us->display, us->head, NULL);
725 }
726}
727
728static void usb_tablet_realize(USBDevice *dev, Error **errp)
729{
730
731 usb_hid_initfn(dev, HID_TABLET, &desc_tablet, &desc_tablet2, errp);
732}
733
734static void usb_mouse_realize(USBDevice *dev, Error **errp)
735{
736 usb_hid_initfn(dev, HID_MOUSE, &desc_mouse, &desc_mouse2, errp);
737}
738
739static void usb_keyboard_realize(USBDevice *dev, Error **errp)
740{
741 usb_hid_initfn(dev, HID_KEYBOARD, &desc_keyboard, &desc_keyboard2, errp);
742}
743
744static int usb_ptr_post_load(void *opaque, int version_id)
745{
746 USBHIDState *s = opaque;
747
748 if (s->dev.remote_wakeup) {
749 hid_pointer_activate(&s->hid);
750 }
751 return 0;
752}
753
754static const VMStateDescription vmstate_usb_ptr = {
755 .name = "usb-ptr",
756 .version_id = 1,
757 .minimum_version_id = 1,
758 .post_load = usb_ptr_post_load,
759 .fields = (VMStateField[]) {
760 VMSTATE_USB_DEVICE(dev, USBHIDState),
761 VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
762 VMSTATE_END_OF_LIST()
763 }
764};
765
766static const VMStateDescription vmstate_usb_kbd = {
767 .name = "usb-kbd",
768 .version_id = 1,
769 .minimum_version_id = 1,
770 .fields = (VMStateField[]) {
771 VMSTATE_USB_DEVICE(dev, USBHIDState),
772 VMSTATE_HID_KEYBOARD_DEVICE(hid, USBHIDState),
773 VMSTATE_END_OF_LIST()
774 }
775};
776
777static void usb_hid_class_initfn(ObjectClass *klass, void *data)
778{
779 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
780
781 uc->handle_reset = usb_hid_handle_reset;
782 uc->handle_control = usb_hid_handle_control;
783 uc->handle_data = usb_hid_handle_data;
784 uc->unrealize = usb_hid_unrealize;
785 uc->handle_attach = usb_desc_attach;
786}
787
788static const TypeInfo usb_hid_type_info = {
789 .name = TYPE_USB_HID,
790 .parent = TYPE_USB_DEVICE,
791 .instance_size = sizeof(USBHIDState),
792 .abstract = true,
793 .class_init = usb_hid_class_initfn,
794};
795
796static Property usb_tablet_properties[] = {
797 DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
798 DEFINE_PROP_STRING("display", USBHIDState, display),
799 DEFINE_PROP_UINT32("head", USBHIDState, head, 0),
800 DEFINE_PROP_END_OF_LIST(),
801};
802
803static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
804{
805 DeviceClass *dc = DEVICE_CLASS(klass);
806 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
807
808 uc->realize = usb_tablet_realize;
809 uc->product_desc = "QEMU USB Tablet";
810 dc->vmsd = &vmstate_usb_ptr;
811 device_class_set_props(dc, usb_tablet_properties);
812 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
813}
814
815static const TypeInfo usb_tablet_info = {
816 .name = "usb-tablet",
817 .parent = TYPE_USB_HID,
818 .class_init = usb_tablet_class_initfn,
819};
820
821static Property usb_mouse_properties[] = {
822 DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
823 DEFINE_PROP_END_OF_LIST(),
824};
825
826static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
827{
828 DeviceClass *dc = DEVICE_CLASS(klass);
829 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
830
831 uc->realize = usb_mouse_realize;
832 uc->product_desc = "QEMU USB Mouse";
833 dc->vmsd = &vmstate_usb_ptr;
834 device_class_set_props(dc, usb_mouse_properties);
835 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
836}
837
838static const TypeInfo usb_mouse_info = {
839 .name = "usb-mouse",
840 .parent = TYPE_USB_HID,
841 .class_init = usb_mouse_class_initfn,
842};
843
844static Property usb_keyboard_properties[] = {
845 DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
846 DEFINE_PROP_STRING("display", USBHIDState, display),
847 DEFINE_PROP_END_OF_LIST(),
848};
849
850static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
851{
852 DeviceClass *dc = DEVICE_CLASS(klass);
853 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
854
855 uc->realize = usb_keyboard_realize;
856 uc->product_desc = "QEMU USB Keyboard";
857 dc->vmsd = &vmstate_usb_kbd;
858 device_class_set_props(dc, usb_keyboard_properties);
859 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
860}
861
862static const TypeInfo usb_keyboard_info = {
863 .name = "usb-kbd",
864 .parent = TYPE_USB_HID,
865 .class_init = usb_keyboard_class_initfn,
866};
867
868static void usb_hid_register_types(void)
869{
870 type_register_static(&usb_hid_type_info);
871 type_register_static(&usb_tablet_info);
872 usb_legacy_register("usb-tablet", "tablet", NULL);
873 type_register_static(&usb_mouse_info);
874 usb_legacy_register("usb-mouse", "mouse", NULL);
875 type_register_static(&usb_keyboard_info);
876 usb_legacy_register("usb-kbd", "keyboard", NULL);
877}
878
879type_init(usb_hid_register_types)
880