4 * Copyright (c) 2005 Fabrice Bellard
5 * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com)
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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
31 /* HID interface requests */
32 #define GET_REPORT 0xa101
33 #define GET_IDLE 0xa102
34 #define GET_PROTOCOL 0xa103
35 #define SET_REPORT 0x2109
36 #define SET_IDLE 0x210a
37 #define SET_PROTOCOL 0x210b
39 /* HID descriptor types */
40 #define USB_DT_HID 0x21
41 #define USB_DT_REPORT 0x22
42 #define USB_DT_PHY 0x23
46 #define USB_KEYBOARD 3
48 typedef struct USBPointerEvent
{
49 int32_t xdx
, ydy
; /* relative iff it's a mouse, otherwise absolute */
50 int32_t dz
, buttons_state
;
53 #define QUEUE_LENGTH 16 /* should be enough for a triple-click */
54 #define QUEUE_MASK (QUEUE_LENGTH-1u)
55 #define QUEUE_INCR(v) ((v)++, (v) &= QUEUE_MASK)
57 typedef struct USBMouseState
{
58 USBPointerEvent queue
[QUEUE_LENGTH
];
60 QEMUPutMouseEntry
*eh_entry
;
63 typedef struct USBKeyboardState
{
64 uint32_t keycodes
[QUEUE_LENGTH
];
71 typedef struct USBHIDState
{
77 uint32_t head
; /* index into circular queue */
82 int64_t next_idle_clock
;
85 void (*datain
)(void *);
99 static const USBDescStrings desc_strings
= {
100 [STR_MANUFACTURER
] = "QEMU " QEMU_VERSION
,
101 [STR_PRODUCT_MOUSE
] = "QEMU USB Mouse",
102 [STR_PRODUCT_TABLET
] = "QEMU USB Tablet",
103 [STR_PRODUCT_KEYBOARD
] = "QEMU USB Keyboard",
104 [STR_SERIALNUMBER
] = "42", /* == remote wakeup works */
105 [STR_CONFIG_MOUSE
] = "HID Mouse",
106 [STR_CONFIG_TABLET
] = "HID Tablet",
107 [STR_CONFIG_KEYBOARD
] = "HID Keyboard",
110 static const USBDescIface desc_iface_mouse
= {
111 .bInterfaceNumber
= 0,
113 .bInterfaceClass
= USB_CLASS_HID
,
114 .bInterfaceSubClass
= 0x01, /* boot */
115 .bInterfaceProtocol
= 0x02,
117 .descs
= (USBDescOther
[]) {
120 .data
= (uint8_t[]) {
121 0x09, /* u8 bLength */
122 USB_DT_HID
, /* u8 bDescriptorType */
123 0x01, 0x00, /* u16 HID_class */
124 0x00, /* u8 country_code */
125 0x01, /* u8 num_descriptors */
126 USB_DT_REPORT
, /* u8 type: Report */
131 .eps
= (USBDescEndpoint
[]) {
133 .bEndpointAddress
= USB_DIR_IN
| 0x01,
134 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
141 static const USBDescIface desc_iface_tablet
= {
142 .bInterfaceNumber
= 0,
144 .bInterfaceClass
= USB_CLASS_HID
,
145 .bInterfaceSubClass
= 0x01, /* boot */
146 .bInterfaceProtocol
= 0x02,
148 .descs
= (USBDescOther
[]) {
151 .data
= (uint8_t[]) {
152 0x09, /* u8 bLength */
153 USB_DT_HID
, /* u8 bDescriptorType */
154 0x01, 0x00, /* u16 HID_class */
155 0x00, /* u8 country_code */
156 0x01, /* u8 num_descriptors */
157 USB_DT_REPORT
, /* u8 type: Report */
162 .eps
= (USBDescEndpoint
[]) {
164 .bEndpointAddress
= USB_DIR_IN
| 0x01,
165 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
172 static const USBDescIface desc_iface_keyboard
= {
173 .bInterfaceNumber
= 0,
175 .bInterfaceClass
= USB_CLASS_HID
,
176 .bInterfaceSubClass
= 0x01, /* boot */
177 .bInterfaceProtocol
= 0x01, /* keyboard */
179 .descs
= (USBDescOther
[]) {
182 .data
= (uint8_t[]) {
183 0x09, /* u8 bLength */
184 USB_DT_HID
, /* u8 bDescriptorType */
185 0x11, 0x01, /* u16 HID_class */
186 0x00, /* u8 country_code */
187 0x01, /* u8 num_descriptors */
188 USB_DT_REPORT
, /* u8 type: Report */
189 0x3f, 0, /* u16 len */
193 .eps
= (USBDescEndpoint
[]) {
195 .bEndpointAddress
= USB_DIR_IN
| 0x01,
196 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
203 static const USBDescDevice desc_device_mouse
= {
205 .bMaxPacketSize0
= 8,
206 .bNumConfigurations
= 1,
207 .confs
= (USBDescConfig
[]) {
210 .bConfigurationValue
= 1,
211 .iConfiguration
= STR_CONFIG_MOUSE
,
212 .bmAttributes
= 0xa0,
214 .ifs
= &desc_iface_mouse
,
219 static const USBDescDevice desc_device_tablet
= {
221 .bMaxPacketSize0
= 8,
222 .bNumConfigurations
= 1,
223 .confs
= (USBDescConfig
[]) {
226 .bConfigurationValue
= 1,
227 .iConfiguration
= STR_CONFIG_TABLET
,
228 .bmAttributes
= 0xa0,
230 .ifs
= &desc_iface_tablet
,
235 static const USBDescDevice desc_device_keyboard
= {
237 .bMaxPacketSize0
= 8,
238 .bNumConfigurations
= 1,
239 .confs
= (USBDescConfig
[]) {
242 .bConfigurationValue
= 1,
243 .iConfiguration
= STR_CONFIG_KEYBOARD
,
244 .bmAttributes
= 0xa0,
246 .ifs
= &desc_iface_keyboard
,
251 static const USBDesc desc_mouse
= {
256 .iManufacturer
= STR_MANUFACTURER
,
257 .iProduct
= STR_PRODUCT_MOUSE
,
258 .iSerialNumber
= STR_SERIALNUMBER
,
260 .full
= &desc_device_mouse
,
264 static const USBDesc desc_tablet
= {
269 .iManufacturer
= STR_MANUFACTURER
,
270 .iProduct
= STR_PRODUCT_TABLET
,
271 .iSerialNumber
= STR_SERIALNUMBER
,
273 .full
= &desc_device_tablet
,
277 static const USBDesc desc_keyboard
= {
282 .iManufacturer
= STR_MANUFACTURER
,
283 .iProduct
= STR_PRODUCT_KEYBOARD
,
284 .iSerialNumber
= STR_SERIALNUMBER
,
286 .full
= &desc_device_keyboard
,
290 static const uint8_t qemu_mouse_hid_report_descriptor
[] = {
291 0x05, 0x01, /* Usage Page (Generic Desktop) */
292 0x09, 0x02, /* Usage (Mouse) */
293 0xa1, 0x01, /* Collection (Application) */
294 0x09, 0x01, /* Usage (Pointer) */
295 0xa1, 0x00, /* Collection (Physical) */
296 0x05, 0x09, /* Usage Page (Button) */
297 0x19, 0x01, /* Usage Minimum (1) */
298 0x29, 0x03, /* Usage Maximum (3) */
299 0x15, 0x00, /* Logical Minimum (0) */
300 0x25, 0x01, /* Logical Maximum (1) */
301 0x95, 0x03, /* Report Count (3) */
302 0x75, 0x01, /* Report Size (1) */
303 0x81, 0x02, /* Input (Data, Variable, Absolute) */
304 0x95, 0x01, /* Report Count (1) */
305 0x75, 0x05, /* Report Size (5) */
306 0x81, 0x01, /* Input (Constant) */
307 0x05, 0x01, /* Usage Page (Generic Desktop) */
308 0x09, 0x30, /* Usage (X) */
309 0x09, 0x31, /* Usage (Y) */
310 0x09, 0x38, /* Usage (Wheel) */
311 0x15, 0x81, /* Logical Minimum (-0x7f) */
312 0x25, 0x7f, /* Logical Maximum (0x7f) */
313 0x75, 0x08, /* Report Size (8) */
314 0x95, 0x03, /* Report Count (3) */
315 0x81, 0x06, /* Input (Data, Variable, Relative) */
316 0xc0, /* End Collection */
317 0xc0, /* End Collection */
320 static const uint8_t qemu_tablet_hid_report_descriptor
[] = {
321 0x05, 0x01, /* Usage Page (Generic Desktop) */
322 0x09, 0x01, /* Usage (Pointer) */
323 0xa1, 0x01, /* Collection (Application) */
324 0x09, 0x01, /* Usage (Pointer) */
325 0xa1, 0x00, /* Collection (Physical) */
326 0x05, 0x09, /* Usage Page (Button) */
327 0x19, 0x01, /* Usage Minimum (1) */
328 0x29, 0x03, /* Usage Maximum (3) */
329 0x15, 0x00, /* Logical Minimum (0) */
330 0x25, 0x01, /* Logical Maximum (1) */
331 0x95, 0x03, /* Report Count (3) */
332 0x75, 0x01, /* Report Size (1) */
333 0x81, 0x02, /* Input (Data, Variable, Absolute) */
334 0x95, 0x01, /* Report Count (1) */
335 0x75, 0x05, /* Report Size (5) */
336 0x81, 0x01, /* Input (Constant) */
337 0x05, 0x01, /* Usage Page (Generic Desktop) */
338 0x09, 0x30, /* Usage (X) */
339 0x09, 0x31, /* Usage (Y) */
340 0x15, 0x00, /* Logical Minimum (0) */
341 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
342 0x35, 0x00, /* Physical Minimum (0) */
343 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
344 0x75, 0x10, /* Report Size (16) */
345 0x95, 0x02, /* Report Count (2) */
346 0x81, 0x02, /* Input (Data, Variable, Absolute) */
347 0x05, 0x01, /* Usage Page (Generic Desktop) */
348 0x09, 0x38, /* Usage (Wheel) */
349 0x15, 0x81, /* Logical Minimum (-0x7f) */
350 0x25, 0x7f, /* Logical Maximum (0x7f) */
351 0x35, 0x00, /* Physical Minimum (same as logical) */
352 0x45, 0x00, /* Physical Maximum (same as logical) */
353 0x75, 0x08, /* Report Size (8) */
354 0x95, 0x01, /* Report Count (1) */
355 0x81, 0x06, /* Input (Data, Variable, Relative) */
356 0xc0, /* End Collection */
357 0xc0, /* End Collection */
360 static const uint8_t qemu_keyboard_hid_report_descriptor
[] = {
361 0x05, 0x01, /* Usage Page (Generic Desktop) */
362 0x09, 0x06, /* Usage (Keyboard) */
363 0xa1, 0x01, /* Collection (Application) */
364 0x75, 0x01, /* Report Size (1) */
365 0x95, 0x08, /* Report Count (8) */
366 0x05, 0x07, /* Usage Page (Key Codes) */
367 0x19, 0xe0, /* Usage Minimum (224) */
368 0x29, 0xe7, /* Usage Maximum (231) */
369 0x15, 0x00, /* Logical Minimum (0) */
370 0x25, 0x01, /* Logical Maximum (1) */
371 0x81, 0x02, /* Input (Data, Variable, Absolute) */
372 0x95, 0x01, /* Report Count (1) */
373 0x75, 0x08, /* Report Size (8) */
374 0x81, 0x01, /* Input (Constant) */
375 0x95, 0x05, /* Report Count (5) */
376 0x75, 0x01, /* Report Size (1) */
377 0x05, 0x08, /* Usage Page (LEDs) */
378 0x19, 0x01, /* Usage Minimum (1) */
379 0x29, 0x05, /* Usage Maximum (5) */
380 0x91, 0x02, /* Output (Data, Variable, Absolute) */
381 0x95, 0x01, /* Report Count (1) */
382 0x75, 0x03, /* Report Size (3) */
383 0x91, 0x01, /* Output (Constant) */
384 0x95, 0x06, /* Report Count (6) */
385 0x75, 0x08, /* Report Size (8) */
386 0x15, 0x00, /* Logical Minimum (0) */
387 0x25, 0xff, /* Logical Maximum (255) */
388 0x05, 0x07, /* Usage Page (Key Codes) */
389 0x19, 0x00, /* Usage Minimum (0) */
390 0x29, 0xff, /* Usage Maximum (255) */
391 0x81, 0x00, /* Input (Data, Array) */
392 0xc0, /* End Collection */
395 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
396 #define USB_HID_USAGE_POSTFAIL 0x02
397 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
399 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
400 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
401 static const uint8_t usb_hid_usage_keys
[0x100] = {
402 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
403 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
404 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
405 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
406 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
407 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
408 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
409 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
410 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
411 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
412 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
413 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
414 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
426 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
428 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
429 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 static void usb_hid_changed(USBHIDState
*hs
)
442 hs
->datain(hs
->datain_opaque
);
444 usb_wakeup(&hs
->dev
);
447 static void usb_pointer_event_clear(USBPointerEvent
*e
, int buttons
) {
448 e
->xdx
= e
->ydy
= e
->dz
= 0;
449 e
->buttons_state
= buttons
;
452 static void usb_pointer_event_combine(USBPointerEvent
*e
, int xyrel
,
453 int x1
, int y1
, int z1
) {
464 static void usb_pointer_event(void *opaque
,
465 int x1
, int y1
, int z1
, int buttons_state
)
467 USBHIDState
*hs
= opaque
;
468 USBMouseState
*s
= &hs
->ptr
;
469 unsigned use_slot
= (hs
->head
+ hs
->n
- 1) & QUEUE_MASK
;
470 unsigned previous_slot
= (use_slot
- 1) & QUEUE_MASK
;
472 /* We combine events where feasible to keep the queue small. We shouldn't
473 * combine anything with the first event of a particular button state, as
474 * that would change the location of the button state change. When the
475 * queue is empty, a second event is needed because we don't know if
476 * the first event changed the button state. */
477 if (hs
->n
== QUEUE_LENGTH
) {
478 /* Queue full. Discard old button state, combine motion normally. */
479 s
->queue
[use_slot
].buttons_state
= buttons_state
;
480 } else if (hs
->n
< 2 ||
481 s
->queue
[use_slot
].buttons_state
!= buttons_state
||
482 s
->queue
[previous_slot
].buttons_state
!= s
->queue
[use_slot
].buttons_state
) {
483 /* Cannot or should not combine, so add an empty item to the queue. */
484 QUEUE_INCR(use_slot
);
486 usb_pointer_event_clear(&s
->queue
[use_slot
], buttons_state
);
488 usb_pointer_event_combine(&s
->queue
[use_slot
],
489 hs
->kind
== USB_MOUSE
,
494 static void usb_keyboard_event(void *opaque
, int keycode
)
496 USBHIDState
*hs
= opaque
;
497 USBKeyboardState
*s
= &hs
->kbd
;
500 if (hs
->n
== QUEUE_LENGTH
) {
501 fprintf(stderr
, "usb-kbd: warning: key event queue full\n");
504 slot
= (hs
->head
+ hs
->n
) & QUEUE_MASK
; hs
->n
++;
505 s
->keycodes
[slot
] = keycode
;
509 static void usb_keyboard_process_keycode(USBHIDState
*hs
)
511 USBKeyboardState
*s
= &hs
->kbd
;
512 uint8_t hid_code
, key
;
513 int i
, keycode
, slot
;
518 slot
= hs
->head
& QUEUE_MASK
; QUEUE_INCR(hs
->head
); hs
->n
--;
519 keycode
= s
->keycodes
[slot
];
521 key
= keycode
& 0x7f;
522 hid_code
= usb_hid_usage_keys
[key
| ((s
->modifiers
>> 1) & (1 << 7))];
523 s
->modifiers
&= ~(1 << 8);
530 if (s
->modifiers
& (1 << 9)) {
531 s
->modifiers
^= 3 << 8;
536 if (keycode
& (1 << 7)) {
537 s
->modifiers
&= ~(1 << (hid_code
& 0x0f));
542 s
->modifiers
|= 1 << (hid_code
& 0x0f);
547 if (keycode
& (1 << 7)) {
548 for (i
= s
->keys
- 1; i
>= 0; i
--)
549 if (s
->key
[i
] == hid_code
) {
550 s
->key
[i
] = s
->key
[-- s
->keys
];
551 s
->key
[s
->keys
] = 0x00;
557 for (i
= s
->keys
- 1; i
>= 0; i
--)
558 if (s
->key
[i
] == hid_code
)
561 if (s
->keys
< sizeof(s
->key
))
562 s
->key
[s
->keys
++] = hid_code
;
568 static inline int int_clamp(int val
, int vmin
, int vmax
)
578 static int usb_pointer_poll(USBHIDState
*hs
, uint8_t *buf
, int len
)
580 int dx
, dy
, dz
, b
, l
;
582 USBMouseState
*s
= &hs
->ptr
;
585 if (!s
->mouse_grabbed
) {
586 qemu_activate_mouse_event_handler(s
->eh_entry
);
587 s
->mouse_grabbed
= 1;
590 /* When the buffer is empty, return the last event. Relative
591 movements will all be zero. */
592 index
= (hs
->n
? hs
->head
: hs
->head
- 1);
593 e
= &s
->queue
[index
& QUEUE_MASK
];
595 if (hs
->kind
== USB_MOUSE
) {
596 dx
= int_clamp(e
->xdx
, -127, 127);
597 dy
= int_clamp(e
->ydy
, -127, 127);
604 dz
= int_clamp(e
->dz
, -127, 127);
608 if (e
->buttons_state
& MOUSE_EVENT_LBUTTON
)
610 if (e
->buttons_state
& MOUSE_EVENT_RBUTTON
)
612 if (e
->buttons_state
& MOUSE_EVENT_MBUTTON
)
617 (hs
->kind
== USB_TABLET
|| (!e
->xdx
&& !e
->ydy
))) {
618 /* that deals with this event */
619 QUEUE_INCR(hs
->head
);
623 /* Appears we have to invert the wheel direction */
642 buf
[l
++] = dx
& 0xff;
646 buf
[l
++] = dy
& 0xff;
660 static int usb_keyboard_poll(USBHIDState
*hs
, uint8_t *buf
, int len
)
662 USBKeyboardState
*s
= &hs
->kbd
;
666 usb_keyboard_process_keycode(hs
);
668 buf
[0] = s
->modifiers
& 0xff;
671 memset(buf
+ 2, USB_HID_USAGE_ERROR_ROLLOVER
, MIN(8, len
) - 2);
673 memcpy(buf
+ 2, s
->key
, MIN(8, len
) - 2);
678 static int usb_keyboard_write(USBKeyboardState
*s
, uint8_t *buf
, int len
)
682 /* 0x01: Num Lock LED
683 * 0x02: Caps Lock LED
684 * 0x04: Scroll Lock LED
689 ledstate
|= QEMU_SCROLL_LOCK_LED
;
691 ledstate
|= QEMU_NUM_LOCK_LED
;
693 ledstate
|= QEMU_CAPS_LOCK_LED
;
694 kbd_put_ledstate(ledstate
);
699 static void usb_mouse_handle_reset(USBDevice
*dev
)
701 USBHIDState
*s
= (USBHIDState
*)dev
;
703 memset(s
->ptr
.queue
, 0, sizeof (s
->ptr
.queue
));
709 static void usb_keyboard_handle_reset(USBDevice
*dev
)
711 USBHIDState
*s
= (USBHIDState
*)dev
;
713 qemu_add_kbd_event_handler(usb_keyboard_event
, s
);
714 memset(s
->kbd
.keycodes
, 0, sizeof (s
->kbd
.keycodes
));
717 memset(s
->kbd
.key
, 0, sizeof (s
->kbd
.key
));
722 static void usb_hid_set_next_idle(USBHIDState
*s
, int64_t curtime
)
724 s
->next_idle_clock
= curtime
+ (get_ticks_per_sec() * s
->idle
* 4) / 1000;
727 static int usb_hid_handle_control(USBDevice
*dev
, int request
, int value
,
728 int index
, int length
, uint8_t *data
)
730 USBHIDState
*s
= (USBHIDState
*)dev
;
733 ret
= usb_desc_handle_control(dev
, request
, value
, index
, length
, data
);
740 case DeviceRequest
| USB_REQ_GET_INTERFACE
:
744 case DeviceOutRequest
| USB_REQ_SET_INTERFACE
:
747 /* hid specific requests */
748 case InterfaceRequest
| USB_REQ_GET_DESCRIPTOR
:
751 if (s
->kind
== USB_MOUSE
) {
752 memcpy(data
, qemu_mouse_hid_report_descriptor
,
753 sizeof(qemu_mouse_hid_report_descriptor
));
754 ret
= sizeof(qemu_mouse_hid_report_descriptor
);
755 } else if (s
->kind
== USB_TABLET
) {
756 memcpy(data
, qemu_tablet_hid_report_descriptor
,
757 sizeof(qemu_tablet_hid_report_descriptor
));
758 ret
= sizeof(qemu_tablet_hid_report_descriptor
);
759 } else if (s
->kind
== USB_KEYBOARD
) {
760 memcpy(data
, qemu_keyboard_hid_report_descriptor
,
761 sizeof(qemu_keyboard_hid_report_descriptor
));
762 ret
= sizeof(qemu_keyboard_hid_report_descriptor
);
770 if (s
->kind
== USB_MOUSE
|| s
->kind
== USB_TABLET
)
771 ret
= usb_pointer_poll(s
, data
, length
);
772 else if (s
->kind
== USB_KEYBOARD
)
773 ret
= usb_keyboard_poll(s
, data
, length
);
776 if (s
->kind
== USB_KEYBOARD
)
777 ret
= usb_keyboard_write(&s
->kbd
, data
, length
);
782 if (s
->kind
!= USB_KEYBOARD
)
785 data
[0] = s
->protocol
;
788 if (s
->kind
!= USB_KEYBOARD
)
798 s
->idle
= (uint8_t) (value
>> 8);
799 usb_hid_set_next_idle(s
, qemu_get_clock(vm_clock
));
810 static int usb_hid_handle_data(USBDevice
*dev
, USBPacket
*p
)
812 USBHIDState
*s
= (USBHIDState
*)dev
;
818 int64_t curtime
= qemu_get_clock(vm_clock
);
819 if (!s
->changed
&& (!s
->idle
|| s
->next_idle_clock
- curtime
> 0))
821 usb_hid_set_next_idle(s
, curtime
);
822 if (s
->kind
== USB_MOUSE
|| s
->kind
== USB_TABLET
) {
823 ret
= usb_pointer_poll(s
, p
->data
, p
->len
);
825 else if (s
->kind
== USB_KEYBOARD
) {
826 ret
= usb_keyboard_poll(s
, p
->data
, p
->len
);
828 s
->changed
= s
->n
> 0;
842 static void usb_hid_handle_destroy(USBDevice
*dev
)
844 USBHIDState
*s
= (USBHIDState
*)dev
;
848 qemu_remove_kbd_event_handler();
851 qemu_remove_mouse_event_handler(s
->ptr
.eh_entry
);
855 static int usb_hid_initfn(USBDevice
*dev
, int kind
)
857 USBHIDState
*s
= DO_UPCAST(USBHIDState
, dev
, dev
);
862 if (s
->kind
== USB_MOUSE
) {
863 s
->ptr
.eh_entry
= qemu_add_mouse_event_handler(usb_pointer_event
, s
,
864 0, "QEMU USB Mouse");
865 } else if (s
->kind
== USB_TABLET
) {
866 s
->ptr
.eh_entry
= qemu_add_mouse_event_handler(usb_pointer_event
, s
,
867 1, "QEMU USB Tablet");
870 /* Force poll routine to be run and grab input the first time. */
875 static int usb_tablet_initfn(USBDevice
*dev
)
877 return usb_hid_initfn(dev
, USB_TABLET
);
880 static int usb_mouse_initfn(USBDevice
*dev
)
882 return usb_hid_initfn(dev
, USB_MOUSE
);
885 static int usb_keyboard_initfn(USBDevice
*dev
)
887 return usb_hid_initfn(dev
, USB_KEYBOARD
);
890 void usb_hid_datain_cb(USBDevice
*dev
, void *opaque
, void (*datain
)(void *))
892 USBHIDState
*s
= (USBHIDState
*)dev
;
894 s
->datain_opaque
= opaque
;
898 static int usb_hid_post_load(void *opaque
, int version_id
)
900 USBHIDState
*s
= opaque
;
903 usb_hid_set_next_idle(s
, qemu_get_clock(vm_clock
));
908 static const VMStateDescription vmstate_usb_ptr_queue
= {
909 .name
= "usb-ptr-queue",
911 .minimum_version_id
= 1,
912 .fields
= (VMStateField
[]) {
913 VMSTATE_INT32(xdx
, USBPointerEvent
),
914 VMSTATE_INT32(ydy
, USBPointerEvent
),
915 VMSTATE_INT32(dz
, USBPointerEvent
),
916 VMSTATE_INT32(buttons_state
, USBPointerEvent
),
917 VMSTATE_END_OF_LIST()
920 static const VMStateDescription vmstate_usb_ptr
= {
923 .minimum_version_id
= 1,
924 .post_load
= usb_hid_post_load
,
925 .fields
= (VMStateField
[]) {
926 VMSTATE_USB_DEVICE(dev
, USBHIDState
),
927 VMSTATE_STRUCT_ARRAY(ptr
.queue
, USBHIDState
, QUEUE_LENGTH
, 0,
928 vmstate_usb_ptr_queue
, USBPointerEvent
),
929 VMSTATE_UINT32(head
, USBHIDState
),
930 VMSTATE_UINT32(n
, USBHIDState
),
931 VMSTATE_INT32(protocol
, USBHIDState
),
932 VMSTATE_UINT8(idle
, USBHIDState
),
933 VMSTATE_END_OF_LIST()
937 static const VMStateDescription vmstate_usb_kbd
= {
940 .minimum_version_id
= 1,
941 .post_load
= usb_hid_post_load
,
942 .fields
= (VMStateField
[]) {
943 VMSTATE_USB_DEVICE(dev
, USBHIDState
),
944 VMSTATE_UINT32_ARRAY(kbd
.keycodes
, USBHIDState
, QUEUE_LENGTH
),
945 VMSTATE_UINT32(head
, USBHIDState
),
946 VMSTATE_UINT32(n
, USBHIDState
),
947 VMSTATE_UINT16(kbd
.modifiers
, USBHIDState
),
948 VMSTATE_UINT8(kbd
.leds
, USBHIDState
),
949 VMSTATE_UINT8_ARRAY(kbd
.key
, USBHIDState
, 16),
950 VMSTATE_INT32(kbd
.keys
, USBHIDState
),
951 VMSTATE_INT32(protocol
, USBHIDState
),
952 VMSTATE_UINT8(idle
, USBHIDState
),
953 VMSTATE_END_OF_LIST()
957 static struct USBDeviceInfo hid_info
[] = {
959 .product_desc
= "QEMU USB Tablet",
960 .qdev
.name
= "usb-tablet",
961 .usbdevice_name
= "tablet",
962 .qdev
.size
= sizeof(USBHIDState
),
963 .qdev
.vmsd
= &vmstate_usb_ptr
,
964 .usb_desc
= &desc_tablet
,
965 .init
= usb_tablet_initfn
,
966 .handle_packet
= usb_generic_handle_packet
,
967 .handle_reset
= usb_mouse_handle_reset
,
968 .handle_control
= usb_hid_handle_control
,
969 .handle_data
= usb_hid_handle_data
,
970 .handle_destroy
= usb_hid_handle_destroy
,
972 .product_desc
= "QEMU USB Mouse",
973 .qdev
.name
= "usb-mouse",
974 .usbdevice_name
= "mouse",
975 .qdev
.size
= sizeof(USBHIDState
),
976 .qdev
.vmsd
= &vmstate_usb_ptr
,
977 .usb_desc
= &desc_mouse
,
978 .init
= usb_mouse_initfn
,
979 .handle_packet
= usb_generic_handle_packet
,
980 .handle_reset
= usb_mouse_handle_reset
,
981 .handle_control
= usb_hid_handle_control
,
982 .handle_data
= usb_hid_handle_data
,
983 .handle_destroy
= usb_hid_handle_destroy
,
985 .product_desc
= "QEMU USB Keyboard",
986 .qdev
.name
= "usb-kbd",
987 .usbdevice_name
= "keyboard",
988 .qdev
.size
= sizeof(USBHIDState
),
989 .qdev
.vmsd
= &vmstate_usb_kbd
,
990 .usb_desc
= &desc_keyboard
,
991 .init
= usb_keyboard_initfn
,
992 .handle_packet
= usb_generic_handle_packet
,
993 .handle_reset
= usb_keyboard_handle_reset
,
994 .handle_control
= usb_hid_handle_control
,
995 .handle_data
= usb_hid_handle_data
,
996 .handle_destroy
= usb_hid_handle_destroy
,
1002 static void usb_hid_register_devices(void)
1004 usb_qdev_register_many(hid_info
);
1006 device_init(usb_hid_register_devices
)