xref: /openbmc/qemu/hw/usb/dev-hid.c (revision 95faaa73)
1 /*
2  * QEMU USB HID devices
3  *
4  * Copyright (c) 2005 Fabrice Bellard
5  * Copyright (c) 2007 OpenMoko, Inc.  (andrew@openedhand.com)
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
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 /* HID interface requests */
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 /* HID descriptor types */
41 #define USB_DT_HID    0x21
42 #define USB_DT_REPORT 0x22
43 #define USB_DT_PHY    0x23
44 
45 typedef 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 enum {
55     STR_MANUFACTURER = 1,
56     STR_PRODUCT_MOUSE,
57     STR_PRODUCT_TABLET,
58     STR_PRODUCT_KEYBOARD,
59     STR_SERIALNUMBER,
60     STR_CONFIG_MOUSE,
61     STR_CONFIG_TABLET,
62     STR_CONFIG_KEYBOARD,
63 };
64 
65 static 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_SERIALNUMBER]     = "42", /* == remote wakeup works */
71     [STR_CONFIG_MOUSE]     = "HID Mouse",
72     [STR_CONFIG_TABLET]    = "HID Tablet",
73     [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
74 };
75 
76 static const USBDescIface desc_iface_mouse = {
77     .bInterfaceNumber              = 0,
78     .bNumEndpoints                 = 1,
79     .bInterfaceClass               = USB_CLASS_HID,
80     .bInterfaceSubClass            = 0x01, /* boot */
81     .bInterfaceProtocol            = 0x02,
82     .ndesc                         = 1,
83     .descs = (USBDescOther[]) {
84         {
85             /* HID descriptor */
86             .data = (uint8_t[]) {
87                 0x09,          /*  u8  bLength */
88                 USB_DT_HID,    /*  u8  bDescriptorType */
89                 0x01, 0x00,    /*  u16 HID_class */
90                 0x00,          /*  u8  country_code */
91                 0x01,          /*  u8  num_descriptors */
92                 USB_DT_REPORT, /*  u8  type: Report */
93                 52, 0,         /*  u16 len */
94             },
95         },
96     },
97     .eps = (USBDescEndpoint[]) {
98         {
99             .bEndpointAddress      = USB_DIR_IN | 0x01,
100             .bmAttributes          = USB_ENDPOINT_XFER_INT,
101             .wMaxPacketSize        = 4,
102             .bInterval             = 0x0a,
103         },
104     },
105 };
106 
107 static const USBDescIface desc_iface_tablet = {
108     .bInterfaceNumber              = 0,
109     .bNumEndpoints                 = 1,
110     .bInterfaceClass               = USB_CLASS_HID,
111     .bInterfaceProtocol            = 0x02,
112     .ndesc                         = 1,
113     .descs = (USBDescOther[]) {
114         {
115             /* HID descriptor */
116             .data = (uint8_t[]) {
117                 0x09,          /*  u8  bLength */
118                 USB_DT_HID,    /*  u8  bDescriptorType */
119                 0x01, 0x00,    /*  u16 HID_class */
120                 0x00,          /*  u8  country_code */
121                 0x01,          /*  u8  num_descriptors */
122                 USB_DT_REPORT, /*  u8  type: Report */
123                 74, 0,         /*  u16 len */
124             },
125         },
126     },
127     .eps = (USBDescEndpoint[]) {
128         {
129             .bEndpointAddress      = USB_DIR_IN | 0x01,
130             .bmAttributes          = USB_ENDPOINT_XFER_INT,
131             .wMaxPacketSize        = 8,
132             .bInterval             = 0x0a,
133         },
134     },
135 };
136 
137 static const USBDescIface desc_iface_tablet2 = {
138     .bInterfaceNumber              = 0,
139     .bNumEndpoints                 = 1,
140     .bInterfaceClass               = USB_CLASS_HID,
141     .bInterfaceProtocol            = 0x02,
142     .ndesc                         = 1,
143     .descs = (USBDescOther[]) {
144         {
145             /* HID descriptor */
146             .data = (uint8_t[]) {
147                 0x09,          /*  u8  bLength */
148                 USB_DT_HID,    /*  u8  bDescriptorType */
149                 0x01, 0x00,    /*  u16 HID_class */
150                 0x00,          /*  u8  country_code */
151                 0x01,          /*  u8  num_descriptors */
152                 USB_DT_REPORT, /*  u8  type: Report */
153                 74, 0,         /*  u16 len */
154             },
155         },
156     },
157     .eps = (USBDescEndpoint[]) {
158         {
159             .bEndpointAddress      = USB_DIR_IN | 0x01,
160             .bmAttributes          = USB_ENDPOINT_XFER_INT,
161             .wMaxPacketSize        = 8,
162             .bInterval             = 4, /* 2 ^ (4-1) * 125 usecs = 1 ms */
163         },
164     },
165 };
166 
167 static const USBDescIface desc_iface_keyboard = {
168     .bInterfaceNumber              = 0,
169     .bNumEndpoints                 = 1,
170     .bInterfaceClass               = USB_CLASS_HID,
171     .bInterfaceSubClass            = 0x01, /* boot */
172     .bInterfaceProtocol            = 0x01, /* keyboard */
173     .ndesc                         = 1,
174     .descs = (USBDescOther[]) {
175         {
176             /* HID descriptor */
177             .data = (uint8_t[]) {
178                 0x09,          /*  u8  bLength */
179                 USB_DT_HID,    /*  u8  bDescriptorType */
180                 0x11, 0x01,    /*  u16 HID_class */
181                 0x00,          /*  u8  country_code */
182                 0x01,          /*  u8  num_descriptors */
183                 USB_DT_REPORT, /*  u8  type: Report */
184                 0x3f, 0,       /*  u16 len */
185             },
186         },
187     },
188     .eps = (USBDescEndpoint[]) {
189         {
190             .bEndpointAddress      = USB_DIR_IN | 0x01,
191             .bmAttributes          = USB_ENDPOINT_XFER_INT,
192             .wMaxPacketSize        = 8,
193             .bInterval             = 0x0a,
194         },
195     },
196 };
197 
198 static const USBDescDevice desc_device_mouse = {
199     .bcdUSB                        = 0x0100,
200     .bMaxPacketSize0               = 8,
201     .bNumConfigurations            = 1,
202     .confs = (USBDescConfig[]) {
203         {
204             .bNumInterfaces        = 1,
205             .bConfigurationValue   = 1,
206             .iConfiguration        = STR_CONFIG_MOUSE,
207             .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
208             .bMaxPower             = 50,
209             .nif = 1,
210             .ifs = &desc_iface_mouse,
211         },
212     },
213 };
214 
215 static const USBDescDevice desc_device_tablet = {
216     .bcdUSB                        = 0x0100,
217     .bMaxPacketSize0               = 8,
218     .bNumConfigurations            = 1,
219     .confs = (USBDescConfig[]) {
220         {
221             .bNumInterfaces        = 1,
222             .bConfigurationValue   = 1,
223             .iConfiguration        = STR_CONFIG_TABLET,
224             .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
225             .bMaxPower             = 50,
226             .nif = 1,
227             .ifs = &desc_iface_tablet,
228         },
229     },
230 };
231 
232 static const USBDescDevice desc_device_tablet2 = {
233     .bcdUSB                        = 0x0200,
234     .bMaxPacketSize0               = 64,
235     .bNumConfigurations            = 1,
236     .confs = (USBDescConfig[]) {
237         {
238             .bNumInterfaces        = 1,
239             .bConfigurationValue   = 1,
240             .iConfiguration        = STR_CONFIG_TABLET,
241             .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
242             .bMaxPower             = 50,
243             .nif = 1,
244             .ifs = &desc_iface_tablet2,
245         },
246     },
247 };
248 
249 static const USBDescDevice desc_device_keyboard = {
250     .bcdUSB                        = 0x0100,
251     .bMaxPacketSize0               = 8,
252     .bNumConfigurations            = 1,
253     .confs = (USBDescConfig[]) {
254         {
255             .bNumInterfaces        = 1,
256             .bConfigurationValue   = 1,
257             .iConfiguration        = STR_CONFIG_KEYBOARD,
258             .bmAttributes          = USB_CFG_ATT_ONE | USB_CFG_ATT_WAKEUP,
259             .bMaxPower             = 50,
260             .nif = 1,
261             .ifs = &desc_iface_keyboard,
262         },
263     },
264 };
265 
266 static const USBDescMSOS desc_msos_suspend = {
267     .SelectiveSuspendEnabled = true,
268 };
269 
270 static const USBDesc desc_mouse = {
271     .id = {
272         .idVendor          = 0x0627,
273         .idProduct         = 0x0001,
274         .bcdDevice         = 0,
275         .iManufacturer     = STR_MANUFACTURER,
276         .iProduct          = STR_PRODUCT_MOUSE,
277         .iSerialNumber     = STR_SERIALNUMBER,
278     },
279     .full = &desc_device_mouse,
280     .str  = desc_strings,
281     .msos = &desc_msos_suspend,
282 };
283 
284 static const USBDesc desc_tablet = {
285     .id = {
286         .idVendor          = 0x0627,
287         .idProduct         = 0x0001,
288         .bcdDevice         = 0,
289         .iManufacturer     = STR_MANUFACTURER,
290         .iProduct          = STR_PRODUCT_TABLET,
291         .iSerialNumber     = STR_SERIALNUMBER,
292     },
293     .full = &desc_device_tablet,
294     .str  = desc_strings,
295     .msos = &desc_msos_suspend,
296 };
297 
298 static const USBDesc desc_tablet2 = {
299     .id = {
300         .idVendor          = 0x0627,
301         .idProduct         = 0x0001,
302         .bcdDevice         = 0,
303         .iManufacturer     = STR_MANUFACTURER,
304         .iProduct          = STR_PRODUCT_TABLET,
305         .iSerialNumber     = STR_SERIALNUMBER,
306     },
307     .full = &desc_device_tablet,
308     .high = &desc_device_tablet2,
309     .str  = desc_strings,
310     .msos = &desc_msos_suspend,
311 };
312 
313 static const USBDesc desc_keyboard = {
314     .id = {
315         .idVendor          = 0x0627,
316         .idProduct         = 0x0001,
317         .bcdDevice         = 0,
318         .iManufacturer     = STR_MANUFACTURER,
319         .iProduct          = STR_PRODUCT_KEYBOARD,
320         .iSerialNumber     = STR_SERIALNUMBER,
321     },
322     .full = &desc_device_keyboard,
323     .str  = desc_strings,
324     .msos = &desc_msos_suspend,
325 };
326 
327 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
328     0x05, 0x01,		/* Usage Page (Generic Desktop) */
329     0x09, 0x02,		/* Usage (Mouse) */
330     0xa1, 0x01,		/* Collection (Application) */
331     0x09, 0x01,		/*   Usage (Pointer) */
332     0xa1, 0x00,		/*   Collection (Physical) */
333     0x05, 0x09,		/*     Usage Page (Button) */
334     0x19, 0x01,		/*     Usage Minimum (1) */
335     0x29, 0x03,		/*     Usage Maximum (3) */
336     0x15, 0x00,		/*     Logical Minimum (0) */
337     0x25, 0x01,		/*     Logical Maximum (1) */
338     0x95, 0x03,		/*     Report Count (3) */
339     0x75, 0x01,		/*     Report Size (1) */
340     0x81, 0x02,		/*     Input (Data, Variable, Absolute) */
341     0x95, 0x01,		/*     Report Count (1) */
342     0x75, 0x05,		/*     Report Size (5) */
343     0x81, 0x01,		/*     Input (Constant) */
344     0x05, 0x01,		/*     Usage Page (Generic Desktop) */
345     0x09, 0x30,		/*     Usage (X) */
346     0x09, 0x31,		/*     Usage (Y) */
347     0x09, 0x38,		/*     Usage (Wheel) */
348     0x15, 0x81,		/*     Logical Minimum (-0x7f) */
349     0x25, 0x7f,		/*     Logical Maximum (0x7f) */
350     0x75, 0x08,		/*     Report Size (8) */
351     0x95, 0x03,		/*     Report Count (3) */
352     0x81, 0x06,		/*     Input (Data, Variable, Relative) */
353     0xc0,		/*   End Collection */
354     0xc0,		/* End Collection */
355 };
356 
357 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
358     0x05, 0x01,		/* Usage Page (Generic Desktop) */
359     0x09, 0x01,		/* Usage (Pointer) */
360     0xa1, 0x01,		/* Collection (Application) */
361     0x09, 0x01,		/*   Usage (Pointer) */
362     0xa1, 0x00,		/*   Collection (Physical) */
363     0x05, 0x09,		/*     Usage Page (Button) */
364     0x19, 0x01,		/*     Usage Minimum (1) */
365     0x29, 0x03,		/*     Usage Maximum (3) */
366     0x15, 0x00,		/*     Logical Minimum (0) */
367     0x25, 0x01,		/*     Logical Maximum (1) */
368     0x95, 0x03,		/*     Report Count (3) */
369     0x75, 0x01,		/*     Report Size (1) */
370     0x81, 0x02,		/*     Input (Data, Variable, Absolute) */
371     0x95, 0x01,		/*     Report Count (1) */
372     0x75, 0x05,		/*     Report Size (5) */
373     0x81, 0x01,		/*     Input (Constant) */
374     0x05, 0x01,		/*     Usage Page (Generic Desktop) */
375     0x09, 0x30,		/*     Usage (X) */
376     0x09, 0x31,		/*     Usage (Y) */
377     0x15, 0x00,		/*     Logical Minimum (0) */
378     0x26, 0xff, 0x7f,	/*     Logical Maximum (0x7fff) */
379     0x35, 0x00,		/*     Physical Minimum (0) */
380     0x46, 0xff, 0x7f,	/*     Physical Maximum (0x7fff) */
381     0x75, 0x10,		/*     Report Size (16) */
382     0x95, 0x02,		/*     Report Count (2) */
383     0x81, 0x02,		/*     Input (Data, Variable, Absolute) */
384     0x05, 0x01,		/*     Usage Page (Generic Desktop) */
385     0x09, 0x38,		/*     Usage (Wheel) */
386     0x15, 0x81,		/*     Logical Minimum (-0x7f) */
387     0x25, 0x7f,		/*     Logical Maximum (0x7f) */
388     0x35, 0x00,		/*     Physical Minimum (same as logical) */
389     0x45, 0x00,		/*     Physical Maximum (same as logical) */
390     0x75, 0x08,		/*     Report Size (8) */
391     0x95, 0x01,		/*     Report Count (1) */
392     0x81, 0x06,		/*     Input (Data, Variable, Relative) */
393     0xc0,		/*   End Collection */
394     0xc0,		/* End Collection */
395 };
396 
397 static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
398     0x05, 0x01,		/* Usage Page (Generic Desktop) */
399     0x09, 0x06,		/* Usage (Keyboard) */
400     0xa1, 0x01,		/* Collection (Application) */
401     0x75, 0x01,		/*   Report Size (1) */
402     0x95, 0x08,		/*   Report Count (8) */
403     0x05, 0x07,		/*   Usage Page (Key Codes) */
404     0x19, 0xe0,		/*   Usage Minimum (224) */
405     0x29, 0xe7,		/*   Usage Maximum (231) */
406     0x15, 0x00,		/*   Logical Minimum (0) */
407     0x25, 0x01,		/*   Logical Maximum (1) */
408     0x81, 0x02,		/*   Input (Data, Variable, Absolute) */
409     0x95, 0x01,		/*   Report Count (1) */
410     0x75, 0x08,		/*   Report Size (8) */
411     0x81, 0x01,		/*   Input (Constant) */
412     0x95, 0x05,		/*   Report Count (5) */
413     0x75, 0x01,		/*   Report Size (1) */
414     0x05, 0x08,		/*   Usage Page (LEDs) */
415     0x19, 0x01,		/*   Usage Minimum (1) */
416     0x29, 0x05,		/*   Usage Maximum (5) */
417     0x91, 0x02,		/*   Output (Data, Variable, Absolute) */
418     0x95, 0x01,		/*   Report Count (1) */
419     0x75, 0x03,		/*   Report Size (3) */
420     0x91, 0x01,		/*   Output (Constant) */
421     0x95, 0x06,		/*   Report Count (6) */
422     0x75, 0x08,		/*   Report Size (8) */
423     0x15, 0x00,		/*   Logical Minimum (0) */
424     0x25, 0xff,		/*   Logical Maximum (255) */
425     0x05, 0x07,		/*   Usage Page (Key Codes) */
426     0x19, 0x00,		/*   Usage Minimum (0) */
427     0x29, 0xff,		/*   Usage Maximum (255) */
428     0x81, 0x00,		/*   Input (Data, Array) */
429     0xc0,		/* End Collection */
430 };
431 
432 static void usb_hid_changed(HIDState *hs)
433 {
434     USBHIDState *us = container_of(hs, USBHIDState, hid);
435 
436     usb_wakeup(us->intr, 0);
437 }
438 
439 static void usb_hid_handle_reset(USBDevice *dev)
440 {
441     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
442 
443     hid_reset(&us->hid);
444 }
445 
446 static void usb_hid_handle_control(USBDevice *dev, USBPacket *p,
447                int request, int value, int index, int length, uint8_t *data)
448 {
449     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
450     HIDState *hs = &us->hid;
451     int ret;
452 
453     ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
454     if (ret >= 0) {
455         return;
456     }
457 
458     switch (request) {
459         /* hid specific requests */
460     case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
461         switch (value >> 8) {
462         case 0x22:
463             if (hs->kind == HID_MOUSE) {
464 		memcpy(data, qemu_mouse_hid_report_descriptor,
465 		       sizeof(qemu_mouse_hid_report_descriptor));
466                 p->actual_length = sizeof(qemu_mouse_hid_report_descriptor);
467             } else if (hs->kind == HID_TABLET) {
468                 memcpy(data, qemu_tablet_hid_report_descriptor,
469 		       sizeof(qemu_tablet_hid_report_descriptor));
470                 p->actual_length = sizeof(qemu_tablet_hid_report_descriptor);
471             } else if (hs->kind == HID_KEYBOARD) {
472                 memcpy(data, qemu_keyboard_hid_report_descriptor,
473                        sizeof(qemu_keyboard_hid_report_descriptor));
474                 p->actual_length = sizeof(qemu_keyboard_hid_report_descriptor);
475             }
476             break;
477         default:
478             goto fail;
479         }
480         break;
481     case GET_REPORT:
482         if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
483             p->actual_length = hid_pointer_poll(hs, data, length);
484         } else if (hs->kind == HID_KEYBOARD) {
485             p->actual_length = hid_keyboard_poll(hs, data, length);
486         }
487         break;
488     case SET_REPORT:
489         if (hs->kind == HID_KEYBOARD) {
490             p->actual_length = hid_keyboard_write(hs, data, length);
491         } else {
492             goto fail;
493         }
494         break;
495     case GET_PROTOCOL:
496         if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
497             goto fail;
498         }
499         data[0] = hs->protocol;
500         p->actual_length = 1;
501         break;
502     case SET_PROTOCOL:
503         if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
504             goto fail;
505         }
506         hs->protocol = value;
507         break;
508     case GET_IDLE:
509         data[0] = hs->idle;
510         p->actual_length = 1;
511         break;
512     case SET_IDLE:
513         hs->idle = (uint8_t) (value >> 8);
514         hid_set_next_idle(hs);
515         if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
516             hid_pointer_activate(hs);
517         }
518         break;
519     default:
520     fail:
521         p->status = USB_RET_STALL;
522         break;
523     }
524 }
525 
526 static void usb_hid_handle_data(USBDevice *dev, USBPacket *p)
527 {
528     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
529     HIDState *hs = &us->hid;
530     uint8_t buf[p->iov.size];
531     int len = 0;
532 
533     switch (p->pid) {
534     case USB_TOKEN_IN:
535         if (p->ep->nr == 1) {
536             if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
537                 hid_pointer_activate(hs);
538             }
539             if (!hid_has_events(hs)) {
540                 p->status = USB_RET_NAK;
541                 return;
542             }
543             hid_set_next_idle(hs);
544             if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
545                 len = hid_pointer_poll(hs, buf, p->iov.size);
546             } else if (hs->kind == HID_KEYBOARD) {
547                 len = hid_keyboard_poll(hs, buf, p->iov.size);
548             }
549             usb_packet_copy(p, buf, len);
550         } else {
551             goto fail;
552         }
553         break;
554     case USB_TOKEN_OUT:
555     default:
556     fail:
557         p->status = USB_RET_STALL;
558         break;
559     }
560 }
561 
562 static void usb_hid_handle_destroy(USBDevice *dev)
563 {
564     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
565 
566     hid_free(&us->hid);
567 }
568 
569 static int usb_hid_initfn(USBDevice *dev, int kind)
570 {
571     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
572 
573     if (dev->serial) {
574         usb_desc_set_string(dev, STR_SERIALNUMBER, dev->serial);
575     }
576     usb_desc_init(dev);
577     us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
578     hid_init(&us->hid, kind, usb_hid_changed);
579     if (us->display && us->hid.s) {
580         qemu_input_handler_bind(us->hid.s, us->display, us->head, NULL);
581     }
582     return 0;
583 }
584 
585 static int usb_tablet_initfn(USBDevice *dev)
586 {
587     USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
588 
589     switch (us->usb_version) {
590     case 1:
591         dev->usb_desc = &desc_tablet;
592         break;
593     case 2:
594         dev->usb_desc = &desc_tablet2;
595         break;
596     default:
597         error_report("Invalid usb version %d for usb-tabler (must be 1 or 2)",
598                      us->usb_version);
599         return -1;
600     }
601 
602     return usb_hid_initfn(dev, HID_TABLET);
603 }
604 
605 static int usb_mouse_initfn(USBDevice *dev)
606 {
607     return usb_hid_initfn(dev, HID_MOUSE);
608 }
609 
610 static int usb_keyboard_initfn(USBDevice *dev)
611 {
612     return usb_hid_initfn(dev, HID_KEYBOARD);
613 }
614 
615 static int usb_ptr_post_load(void *opaque, int version_id)
616 {
617     USBHIDState *s = opaque;
618 
619     if (s->dev.remote_wakeup) {
620         hid_pointer_activate(&s->hid);
621     }
622     return 0;
623 }
624 
625 static const VMStateDescription vmstate_usb_ptr = {
626     .name = "usb-ptr",
627     .version_id = 1,
628     .minimum_version_id = 1,
629     .post_load = usb_ptr_post_load,
630     .fields = (VMStateField[]) {
631         VMSTATE_USB_DEVICE(dev, USBHIDState),
632         VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
633         VMSTATE_END_OF_LIST()
634     }
635 };
636 
637 static const VMStateDescription vmstate_usb_kbd = {
638     .name = "usb-kbd",
639     .version_id = 1,
640     .minimum_version_id = 1,
641     .fields = (VMStateField[]) {
642         VMSTATE_USB_DEVICE(dev, USBHIDState),
643         VMSTATE_HID_KEYBOARD_DEVICE(hid, USBHIDState),
644         VMSTATE_END_OF_LIST()
645     }
646 };
647 
648 static void usb_hid_class_initfn(ObjectClass *klass, void *data)
649 {
650     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
651 
652     uc->handle_reset   = usb_hid_handle_reset;
653     uc->handle_control = usb_hid_handle_control;
654     uc->handle_data    = usb_hid_handle_data;
655     uc->handle_destroy = usb_hid_handle_destroy;
656     uc->handle_attach  = usb_desc_attach;
657 }
658 
659 static Property usb_tablet_properties[] = {
660         DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
661         DEFINE_PROP_STRING("display", USBHIDState, display),
662         DEFINE_PROP_UINT32("head", USBHIDState, head, 0),
663         DEFINE_PROP_END_OF_LIST(),
664 };
665 
666 static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
667 {
668     DeviceClass *dc = DEVICE_CLASS(klass);
669     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
670 
671     usb_hid_class_initfn(klass, data);
672     uc->init           = usb_tablet_initfn;
673     uc->product_desc   = "QEMU USB Tablet";
674     dc->vmsd = &vmstate_usb_ptr;
675     dc->props = usb_tablet_properties;
676     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
677 }
678 
679 static const TypeInfo usb_tablet_info = {
680     .name          = "usb-tablet",
681     .parent        = TYPE_USB_DEVICE,
682     .instance_size = sizeof(USBHIDState),
683     .class_init    = usb_tablet_class_initfn,
684 };
685 
686 static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
687 {
688     DeviceClass *dc = DEVICE_CLASS(klass);
689     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
690 
691     usb_hid_class_initfn(klass, data);
692     uc->init           = usb_mouse_initfn;
693     uc->product_desc   = "QEMU USB Mouse";
694     uc->usb_desc       = &desc_mouse;
695     dc->vmsd = &vmstate_usb_ptr;
696     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
697 }
698 
699 static const TypeInfo usb_mouse_info = {
700     .name          = "usb-mouse",
701     .parent        = TYPE_USB_DEVICE,
702     .instance_size = sizeof(USBHIDState),
703     .class_init    = usb_mouse_class_initfn,
704 };
705 
706 static Property usb_keyboard_properties[] = {
707         DEFINE_PROP_STRING("display", USBHIDState, display),
708         DEFINE_PROP_END_OF_LIST(),
709 };
710 
711 static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
712 {
713     DeviceClass *dc = DEVICE_CLASS(klass);
714     USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
715 
716     usb_hid_class_initfn(klass, data);
717     uc->init           = usb_keyboard_initfn;
718     uc->product_desc   = "QEMU USB Keyboard";
719     uc->usb_desc       = &desc_keyboard;
720     dc->vmsd = &vmstate_usb_kbd;
721     dc->props = usb_keyboard_properties;
722     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
723 }
724 
725 static const TypeInfo usb_keyboard_info = {
726     .name          = "usb-kbd",
727     .parent        = TYPE_USB_DEVICE,
728     .instance_size = sizeof(USBHIDState),
729     .class_init    = usb_keyboard_class_initfn,
730 };
731 
732 static void usb_hid_register_types(void)
733 {
734     type_register_static(&usb_tablet_info);
735     usb_legacy_register("usb-tablet", "tablet", NULL);
736     type_register_static(&usb_mouse_info);
737     usb_legacy_register("usb-mouse", "mouse", NULL);
738     type_register_static(&usb_keyboard_info);
739     usb_legacy_register("usb-kbd", "keyboard", NULL);
740 }
741 
742 type_init(usb_hid_register_types)
743