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} USBHIDState;
51
52enum {
53 STR_MANUFACTURER = 1,
54 STR_PRODUCT_MOUSE,
55 STR_PRODUCT_TABLET,
56 STR_PRODUCT_KEYBOARD,
57 STR_SERIALNUMBER,
58 STR_CONFIG_MOUSE,
59 STR_CONFIG_TABLET,
60 STR_CONFIG_KEYBOARD,
61};
62
63static const USBDescStrings desc_strings = {
64 [STR_MANUFACTURER] = "QEMU",
65 [STR_PRODUCT_MOUSE] = "QEMU USB Mouse",
66 [STR_PRODUCT_TABLET] = "QEMU USB Tablet",
67 [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
68 [STR_SERIALNUMBER] = "42",
69 [STR_CONFIG_MOUSE] = "HID Mouse",
70 [STR_CONFIG_TABLET] = "HID Tablet",
71 [STR_CONFIG_KEYBOARD] = "HID Keyboard",
72};
73
74static const USBDescIface desc_iface_mouse = {
75 .bInterfaceNumber = 0,
76 .bNumEndpoints = 1,
77 .bInterfaceClass = USB_CLASS_HID,
78 .bInterfaceSubClass = 0x01,
79 .bInterfaceProtocol = 0x02,
80 .ndesc = 1,
81 .descs = (USBDescOther[]) {
82 {
83
84 .data = (uint8_t[]) {
85 0x09,
86 USB_DT_HID,
87 0x01, 0x00,
88 0x00,
89 0x01,
90 USB_DT_REPORT,
91 52, 0,
92 },
93 },
94 },
95 .eps = (USBDescEndpoint[]) {
96 {
97 .bEndpointAddress = USB_DIR_IN | 0x01,
98 .bmAttributes = USB_ENDPOINT_XFER_INT,
99 .wMaxPacketSize = 4,
100 .bInterval = 0x0a,
101 },
102 },
103};
104
105static const USBDescIface desc_iface_tablet = {
106 .bInterfaceNumber = 0,
107 .bNumEndpoints = 1,
108 .bInterfaceClass = USB_CLASS_HID,
109 .bInterfaceProtocol = 0x02,
110 .ndesc = 1,
111 .descs = (USBDescOther[]) {
112 {
113
114 .data = (uint8_t[]) {
115 0x09,
116 USB_DT_HID,
117 0x01, 0x00,
118 0x00,
119 0x01,
120 USB_DT_REPORT,
121 74, 0,
122 },
123 },
124 },
125 .eps = (USBDescEndpoint[]) {
126 {
127 .bEndpointAddress = USB_DIR_IN | 0x01,
128 .bmAttributes = USB_ENDPOINT_XFER_INT,
129 .wMaxPacketSize = 8,
130 .bInterval = 0x0a,
131 },
132 },
133};
134
135static const USBDescIface desc_iface_tablet2 = {
136 .bInterfaceNumber = 0,
137 .bNumEndpoints = 1,
138 .bInterfaceClass = USB_CLASS_HID,
139 .bInterfaceProtocol = 0x02,
140 .ndesc = 1,
141 .descs = (USBDescOther[]) {
142 {
143
144 .data = (uint8_t[]) {
145 0x09,
146 USB_DT_HID,
147 0x01, 0x00,
148 0x00,
149 0x01,
150 USB_DT_REPORT,
151 74, 0,
152 },
153 },
154 },
155 .eps = (USBDescEndpoint[]) {
156 {
157 .bEndpointAddress = USB_DIR_IN | 0x01,
158 .bmAttributes = USB_ENDPOINT_XFER_INT,
159 .wMaxPacketSize = 8,
160 .bInterval = 4,
161 },
162 },
163};
164
165static const USBDescIface desc_iface_keyboard = {
166 .bInterfaceNumber = 0,
167 .bNumEndpoints = 1,
168 .bInterfaceClass = USB_CLASS_HID,
169 .bInterfaceSubClass = 0x01,
170 .bInterfaceProtocol = 0x01,
171 .ndesc = 1,
172 .descs = (USBDescOther[]) {
173 {
174
175 .data = (uint8_t[]) {
176 0x09,
177 USB_DT_HID,
178 0x11, 0x01,
179 0x00,
180 0x01,
181 USB_DT_REPORT,
182 0x3f, 0,
183 },
184 },
185 },
186 .eps = (USBDescEndpoint[]) {
187 {
188 .bEndpointAddress = USB_DIR_IN | 0x01,
189 .bmAttributes = USB_ENDPOINT_XFER_INT,
190 .wMaxPacketSize = 8,
191 .bInterval = 0x0a,
192 },
193 },
194};
195
196static const USBDescDevice desc_device_mouse = {
197 .bcdUSB = 0x0100,
198 .bMaxPacketSize0 = 8,
199 .bNumConfigurations = 1,
200 .confs = (USBDescConfig[]) {
201 {
202 .bNumInterfaces = 1,
203 .bConfigurationValue = 1,
204 .iConfiguration = STR_CONFIG_MOUSE,
205 .bmAttributes = 0xa0,
206 .bMaxPower = 50,
207 .nif = 1,
208 .ifs = &desc_iface_mouse,
209 },
210 },
211};
212
213static const USBDescDevice desc_device_tablet = {
214 .bcdUSB = 0x0100,
215 .bMaxPacketSize0 = 8,
216 .bNumConfigurations = 1,
217 .confs = (USBDescConfig[]) {
218 {
219 .bNumInterfaces = 1,
220 .bConfigurationValue = 1,
221 .iConfiguration = STR_CONFIG_TABLET,
222 .bmAttributes = 0xa0,
223 .bMaxPower = 50,
224 .nif = 1,
225 .ifs = &desc_iface_tablet,
226 },
227 },
228};
229
230static const USBDescDevice desc_device_tablet2 = {
231 .bcdUSB = 0x0200,
232 .bMaxPacketSize0 = 64,
233 .bNumConfigurations = 1,
234 .confs = (USBDescConfig[]) {
235 {
236 .bNumInterfaces = 1,
237 .bConfigurationValue = 1,
238 .iConfiguration = STR_CONFIG_TABLET,
239 .bmAttributes = 0x80,
240 .bMaxPower = 50,
241 .nif = 1,
242 .ifs = &desc_iface_tablet2,
243 },
244 },
245};
246
247static const USBDescDevice desc_device_keyboard = {
248 .bcdUSB = 0x0100,
249 .bMaxPacketSize0 = 8,
250 .bNumConfigurations = 1,
251 .confs = (USBDescConfig[]) {
252 {
253 .bNumInterfaces = 1,
254 .bConfigurationValue = 1,
255 .iConfiguration = STR_CONFIG_KEYBOARD,
256 .bmAttributes = 0xa0,
257 .bMaxPower = 50,
258 .nif = 1,
259 .ifs = &desc_iface_keyboard,
260 },
261 },
262};
263
264static const USBDesc desc_mouse = {
265 .id = {
266 .idVendor = 0x0627,
267 .idProduct = 0x0001,
268 .bcdDevice = 0,
269 .iManufacturer = STR_MANUFACTURER,
270 .iProduct = STR_PRODUCT_MOUSE,
271 .iSerialNumber = STR_SERIALNUMBER,
272 },
273 .full = &desc_device_mouse,
274 .str = desc_strings,
275};
276
277static const USBDesc desc_tablet = {
278 .id = {
279 .idVendor = 0x0627,
280 .idProduct = 0x0001,
281 .bcdDevice = 0,
282 .iManufacturer = STR_MANUFACTURER,
283 .iProduct = STR_PRODUCT_TABLET,
284 .iSerialNumber = STR_SERIALNUMBER,
285 },
286 .full = &desc_device_tablet,
287 .str = desc_strings,
288};
289
290static const USBDesc desc_tablet2 = {
291 .id = {
292 .idVendor = 0x0627,
293 .idProduct = 0x0001,
294 .bcdDevice = 0,
295 .iManufacturer = STR_MANUFACTURER,
296 .iProduct = STR_PRODUCT_TABLET,
297 .iSerialNumber = STR_SERIALNUMBER,
298 },
299 .full = &desc_device_tablet,
300 .high = &desc_device_tablet2,
301 .str = desc_strings,
302};
303
304static const USBDesc desc_keyboard = {
305 .id = {
306 .idVendor = 0x0627,
307 .idProduct = 0x0001,
308 .bcdDevice = 0,
309 .iManufacturer = STR_MANUFACTURER,
310 .iProduct = STR_PRODUCT_KEYBOARD,
311 .iSerialNumber = STR_SERIALNUMBER,
312 },
313 .full = &desc_device_keyboard,
314 .str = desc_strings,
315};
316
317static const uint8_t qemu_mouse_hid_report_descriptor[] = {
318 0x05, 0x01,
319 0x09, 0x02,
320 0xa1, 0x01,
321 0x09, 0x01,
322 0xa1, 0x00,
323 0x05, 0x09,
324 0x19, 0x01,
325 0x29, 0x03,
326 0x15, 0x00,
327 0x25, 0x01,
328 0x95, 0x03,
329 0x75, 0x01,
330 0x81, 0x02,
331 0x95, 0x01,
332 0x75, 0x05,
333 0x81, 0x01,
334 0x05, 0x01,
335 0x09, 0x30,
336 0x09, 0x31,
337 0x09, 0x38,
338 0x15, 0x81,
339 0x25, 0x7f,
340 0x75, 0x08,
341 0x95, 0x03,
342 0x81, 0x06,
343 0xc0,
344 0xc0,
345};
346
347static const uint8_t qemu_tablet_hid_report_descriptor[] = {
348 0x05, 0x01,
349 0x09, 0x01,
350 0xa1, 0x01,
351 0x09, 0x01,
352 0xa1, 0x00,
353 0x05, 0x09,
354 0x19, 0x01,
355 0x29, 0x03,
356 0x15, 0x00,
357 0x25, 0x01,
358 0x95, 0x03,
359 0x75, 0x01,
360 0x81, 0x02,
361 0x95, 0x01,
362 0x75, 0x05,
363 0x81, 0x01,
364 0x05, 0x01,
365 0x09, 0x30,
366 0x09, 0x31,
367 0x15, 0x00,
368 0x26, 0xff, 0x7f,
369 0x35, 0x00,
370 0x46, 0xff, 0x7f,
371 0x75, 0x10,
372 0x95, 0x02,
373 0x81, 0x02,
374 0x05, 0x01,
375 0x09, 0x38,
376 0x15, 0x81,
377 0x25, 0x7f,
378 0x35, 0x00,
379 0x45, 0x00,
380 0x75, 0x08,
381 0x95, 0x01,
382 0x81, 0x06,
383 0xc0,
384 0xc0,
385};
386
387static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
388 0x05, 0x01,
389 0x09, 0x06,
390 0xa1, 0x01,
391 0x75, 0x01,
392 0x95, 0x08,
393 0x05, 0x07,
394 0x19, 0xe0,
395 0x29, 0xe7,
396 0x15, 0x00,
397 0x25, 0x01,
398 0x81, 0x02,
399 0x95, 0x01,
400 0x75, 0x08,
401 0x81, 0x01,
402 0x95, 0x05,
403 0x75, 0x01,
404 0x05, 0x08,
405 0x19, 0x01,
406 0x29, 0x05,
407 0x91, 0x02,
408 0x95, 0x01,
409 0x75, 0x03,
410 0x91, 0x01,
411 0x95, 0x06,
412 0x75, 0x08,
413 0x15, 0x00,
414 0x25, 0xff,
415 0x05, 0x07,
416 0x19, 0x00,
417 0x29, 0xff,
418 0x81, 0x00,
419 0xc0,
420};
421
422static void usb_hid_changed(HIDState *hs)
423{
424 USBHIDState *us = container_of(hs, USBHIDState, hid);
425
426 usb_wakeup(us->intr, 0);
427}
428
429static void usb_hid_handle_reset(USBDevice *dev)
430{
431 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
432
433 hid_reset(&us->hid);
434}
435
436static void usb_hid_handle_control(USBDevice *dev, USBPacket *p,
437 int request, int value, int index, int length, uint8_t *data)
438{
439 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
440 HIDState *hs = &us->hid;
441 int ret;
442
443 ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
444 if (ret >= 0) {
445 return;
446 }
447
448 switch (request) {
449
450 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
451 switch (value >> 8) {
452 case 0x22:
453 if (hs->kind == HID_MOUSE) {
454 memcpy(data, qemu_mouse_hid_report_descriptor,
455 sizeof(qemu_mouse_hid_report_descriptor));
456 p->actual_length = sizeof(qemu_mouse_hid_report_descriptor);
457 } else if (hs->kind == HID_TABLET) {
458 memcpy(data, qemu_tablet_hid_report_descriptor,
459 sizeof(qemu_tablet_hid_report_descriptor));
460 p->actual_length = sizeof(qemu_tablet_hid_report_descriptor);
461 } else if (hs->kind == HID_KEYBOARD) {
462 memcpy(data, qemu_keyboard_hid_report_descriptor,
463 sizeof(qemu_keyboard_hid_report_descriptor));
464 p->actual_length = sizeof(qemu_keyboard_hid_report_descriptor);
465 }
466 break;
467 default:
468 goto fail;
469 }
470 break;
471 case GET_REPORT:
472 if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
473 p->actual_length = hid_pointer_poll(hs, data, length);
474 } else if (hs->kind == HID_KEYBOARD) {
475 p->actual_length = hid_keyboard_poll(hs, data, length);
476 }
477 break;
478 case SET_REPORT:
479 if (hs->kind == HID_KEYBOARD) {
480 p->actual_length = hid_keyboard_write(hs, data, length);
481 } else {
482 goto fail;
483 }
484 break;
485 case GET_PROTOCOL:
486 if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
487 goto fail;
488 }
489 data[0] = hs->protocol;
490 p->actual_length = 1;
491 break;
492 case SET_PROTOCOL:
493 if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
494 goto fail;
495 }
496 hs->protocol = value;
497 break;
498 case GET_IDLE:
499 data[0] = hs->idle;
500 p->actual_length = 1;
501 break;
502 case SET_IDLE:
503 hs->idle = (uint8_t) (value >> 8);
504 hid_set_next_idle(hs);
505 if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
506 hid_pointer_activate(hs);
507 }
508 break;
509 default:
510 fail:
511 p->status = USB_RET_STALL;
512 break;
513 }
514}
515
516static void usb_hid_handle_data(USBDevice *dev, USBPacket *p)
517{
518 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
519 HIDState *hs = &us->hid;
520 uint8_t buf[p->iov.size];
521 int len = 0;
522
523 switch (p->pid) {
524 case USB_TOKEN_IN:
525 if (p->ep->nr == 1) {
526 if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
527 hid_pointer_activate(hs);
528 }
529 if (!hid_has_events(hs)) {
530 p->status = USB_RET_NAK;
531 return;
532 }
533 hid_set_next_idle(hs);
534 if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
535 len = hid_pointer_poll(hs, buf, p->iov.size);
536 } else if (hs->kind == HID_KEYBOARD) {
537 len = hid_keyboard_poll(hs, buf, p->iov.size);
538 }
539 usb_packet_copy(p, buf, len);
540 } else {
541 goto fail;
542 }
543 break;
544 case USB_TOKEN_OUT:
545 default:
546 fail:
547 p->status = USB_RET_STALL;
548 break;
549 }
550}
551
552static void usb_hid_handle_destroy(USBDevice *dev)
553{
554 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
555
556 hid_free(&us->hid);
557}
558
559static int usb_hid_initfn(USBDevice *dev, int kind)
560{
561 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
562
563 if (dev->serial) {
564 usb_desc_set_string(dev, STR_SERIALNUMBER, dev->serial);
565 }
566 usb_desc_init(dev);
567 us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
568 hid_init(&us->hid, kind, usb_hid_changed);
569 return 0;
570}
571
572static int usb_tablet_initfn(USBDevice *dev)
573{
574 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
575
576 switch (us->usb_version) {
577 case 1:
578 dev->usb_desc = &desc_tablet;
579 break;
580 case 2:
581 dev->usb_desc = &desc_tablet2;
582 break;
583 default:
584 error_report("Invalid usb version %d for usb-tabler (must be 1 or 2)",
585 us->usb_version);
586 return -1;
587 }
588
589 return usb_hid_initfn(dev, HID_TABLET);
590}
591
592static int usb_mouse_initfn(USBDevice *dev)
593{
594 return usb_hid_initfn(dev, HID_MOUSE);
595}
596
597static int usb_keyboard_initfn(USBDevice *dev)
598{
599 return usb_hid_initfn(dev, HID_KEYBOARD);
600}
601
602static int usb_ptr_post_load(void *opaque, int version_id)
603{
604 USBHIDState *s = opaque;
605
606 if (s->dev.remote_wakeup) {
607 hid_pointer_activate(&s->hid);
608 }
609 return 0;
610}
611
612static const VMStateDescription vmstate_usb_ptr = {
613 .name = "usb-ptr",
614 .version_id = 1,
615 .minimum_version_id = 1,
616 .post_load = usb_ptr_post_load,
617 .fields = (VMStateField []) {
618 VMSTATE_USB_DEVICE(dev, USBHIDState),
619 VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
620 VMSTATE_END_OF_LIST()
621 }
622};
623
624static const VMStateDescription vmstate_usb_kbd = {
625 .name = "usb-kbd",
626 .version_id = 1,
627 .minimum_version_id = 1,
628 .fields = (VMStateField []) {
629 VMSTATE_USB_DEVICE(dev, USBHIDState),
630 VMSTATE_HID_KEYBOARD_DEVICE(hid, USBHIDState),
631 VMSTATE_END_OF_LIST()
632 }
633};
634
635static void usb_hid_class_initfn(ObjectClass *klass, void *data)
636{
637 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
638
639 uc->handle_reset = usb_hid_handle_reset;
640 uc->handle_control = usb_hid_handle_control;
641 uc->handle_data = usb_hid_handle_data;
642 uc->handle_destroy = usb_hid_handle_destroy;
643 uc->handle_attach = usb_desc_attach;
644}
645
646static Property usb_tablet_properties[] = {
647 DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
648 DEFINE_PROP_END_OF_LIST(),
649};
650
651static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
652{
653 DeviceClass *dc = DEVICE_CLASS(klass);
654 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
655
656 usb_hid_class_initfn(klass, data);
657 uc->init = usb_tablet_initfn;
658 uc->product_desc = "QEMU USB Tablet";
659 dc->vmsd = &vmstate_usb_ptr;
660 dc->props = usb_tablet_properties;
661 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
662}
663
664static const TypeInfo usb_tablet_info = {
665 .name = "usb-tablet",
666 .parent = TYPE_USB_DEVICE,
667 .instance_size = sizeof(USBHIDState),
668 .class_init = usb_tablet_class_initfn,
669};
670
671static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
672{
673 DeviceClass *dc = DEVICE_CLASS(klass);
674 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
675
676 usb_hid_class_initfn(klass, data);
677 uc->init = usb_mouse_initfn;
678 uc->product_desc = "QEMU USB Mouse";
679 uc->usb_desc = &desc_mouse;
680 dc->vmsd = &vmstate_usb_ptr;
681 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
682}
683
684static const TypeInfo usb_mouse_info = {
685 .name = "usb-mouse",
686 .parent = TYPE_USB_DEVICE,
687 .instance_size = sizeof(USBHIDState),
688 .class_init = usb_mouse_class_initfn,
689};
690
691static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
692{
693 DeviceClass *dc = DEVICE_CLASS(klass);
694 USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
695
696 usb_hid_class_initfn(klass, data);
697 uc->init = usb_keyboard_initfn;
698 uc->product_desc = "QEMU USB Keyboard";
699 uc->usb_desc = &desc_keyboard;
700 dc->vmsd = &vmstate_usb_kbd;
701 set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
702}
703
704static const TypeInfo usb_keyboard_info = {
705 .name = "usb-kbd",
706 .parent = TYPE_USB_DEVICE,
707 .instance_size = sizeof(USBHIDState),
708 .class_init = usb_keyboard_class_initfn,
709};
710
711static void usb_hid_register_types(void)
712{
713 type_register_static(&usb_tablet_info);
714 usb_legacy_register("usb-tablet", "tablet", NULL);
715 type_register_static(&usb_mouse_info);
716 usb_legacy_register("usb-mouse", "mouse", NULL);
717 type_register_static(&usb_keyboard_info);
718 usb_legacy_register("usb-kbd", "keyboard", NULL);
719}
720
721type_init(usb_hid_register_types)
722