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