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
29
#include "qemu-timer.h"
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
.bInterfaceProtocol = 0x02,
147
.descs = (USBDescOther[]) {
150
.data = (uint8_t[]) {
151
0x09, /* u8 bLength */
152
USB_DT_HID, /* u8 bDescriptorType */
153
0x01, 0x00, /* u16 HID_class */
154
0x00, /* u8 country_code */
155
0x01, /* u8 num_descriptors */
156
USB_DT_REPORT, /* u8 type: Report */
161
.eps = (USBDescEndpoint[]) {
163
.bEndpointAddress = USB_DIR_IN | 0x01,
164
.bmAttributes = USB_ENDPOINT_XFER_INT,
171
static const USBDescIface desc_iface_keyboard = {
172
.bInterfaceNumber = 0,
174
.bInterfaceClass = USB_CLASS_HID,
175
.bInterfaceSubClass = 0x01, /* boot */
176
.bInterfaceProtocol = 0x01, /* keyboard */
178
.descs = (USBDescOther[]) {
181
.data = (uint8_t[]) {
182
0x09, /* u8 bLength */
183
USB_DT_HID, /* u8 bDescriptorType */
184
0x11, 0x01, /* u16 HID_class */
185
0x00, /* u8 country_code */
186
0x01, /* u8 num_descriptors */
187
USB_DT_REPORT, /* u8 type: Report */
188
0x3f, 0, /* u16 len */
192
.eps = (USBDescEndpoint[]) {
194
.bEndpointAddress = USB_DIR_IN | 0x01,
195
.bmAttributes = USB_ENDPOINT_XFER_INT,
202
static const USBDescDevice desc_device_mouse = {
204
.bMaxPacketSize0 = 8,
205
.bNumConfigurations = 1,
206
.confs = (USBDescConfig[]) {
209
.bConfigurationValue = 1,
210
.iConfiguration = STR_CONFIG_MOUSE,
211
.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,
231
.ifs = &desc_iface_tablet,
236
static const USBDescDevice desc_device_keyboard = {
238
.bMaxPacketSize0 = 8,
239
.bNumConfigurations = 1,
240
.confs = (USBDescConfig[]) {
243
.bConfigurationValue = 1,
244
.iConfiguration = STR_CONFIG_KEYBOARD,
245
.bmAttributes = 0xa0,
248
.ifs = &desc_iface_keyboard,
253
static const USBDesc desc_mouse = {
258
.iManufacturer = STR_MANUFACTURER,
259
.iProduct = STR_PRODUCT_MOUSE,
260
.iSerialNumber = STR_SERIALNUMBER,
262
.full = &desc_device_mouse,
266
static const USBDesc desc_tablet = {
271
.iManufacturer = STR_MANUFACTURER,
272
.iProduct = STR_PRODUCT_TABLET,
273
.iSerialNumber = STR_SERIALNUMBER,
275
.full = &desc_device_tablet,
279
static const USBDesc desc_keyboard = {
284
.iManufacturer = STR_MANUFACTURER,
285
.iProduct = STR_PRODUCT_KEYBOARD,
286
.iSerialNumber = STR_SERIALNUMBER,
288
.full = &desc_device_keyboard,
292
static const uint8_t qemu_mouse_hid_report_descriptor[] = {
293
0x05, 0x01, /* Usage Page (Generic Desktop) */
294
0x09, 0x02, /* Usage (Mouse) */
295
0xa1, 0x01, /* Collection (Application) */
296
0x09, 0x01, /* Usage (Pointer) */
297
0xa1, 0x00, /* Collection (Physical) */
298
0x05, 0x09, /* Usage Page (Button) */
299
0x19, 0x01, /* Usage Minimum (1) */
300
0x29, 0x03, /* Usage Maximum (3) */
301
0x15, 0x00, /* Logical Minimum (0) */
302
0x25, 0x01, /* Logical Maximum (1) */
303
0x95, 0x03, /* Report Count (3) */
304
0x75, 0x01, /* Report Size (1) */
305
0x81, 0x02, /* Input (Data, Variable, Absolute) */
306
0x95, 0x01, /* Report Count (1) */
307
0x75, 0x05, /* Report Size (5) */
308
0x81, 0x01, /* Input (Constant) */
309
0x05, 0x01, /* Usage Page (Generic Desktop) */
310
0x09, 0x30, /* Usage (X) */
311
0x09, 0x31, /* Usage (Y) */
312
0x09, 0x38, /* Usage (Wheel) */
313
0x15, 0x81, /* Logical Minimum (-0x7f) */
314
0x25, 0x7f, /* Logical Maximum (0x7f) */
315
0x75, 0x08, /* Report Size (8) */
316
0x95, 0x03, /* Report Count (3) */
317
0x81, 0x06, /* Input (Data, Variable, Relative) */
318
0xc0, /* End Collection */
319
0xc0, /* End Collection */
322
static const uint8_t qemu_tablet_hid_report_descriptor[] = {
323
0x05, 0x01, /* Usage Page (Generic Desktop) */
324
0x09, 0x01, /* Usage (Pointer) */
325
0xa1, 0x01, /* Collection (Application) */
326
0x09, 0x01, /* Usage (Pointer) */
327
0xa1, 0x00, /* Collection (Physical) */
328
0x05, 0x09, /* Usage Page (Button) */
329
0x19, 0x01, /* Usage Minimum (1) */
330
0x29, 0x03, /* Usage Maximum (3) */
331
0x15, 0x00, /* Logical Minimum (0) */
332
0x25, 0x01, /* Logical Maximum (1) */
333
0x95, 0x03, /* Report Count (3) */
334
0x75, 0x01, /* Report Size (1) */
335
0x81, 0x02, /* Input (Data, Variable, Absolute) */
336
0x95, 0x01, /* Report Count (1) */
337
0x75, 0x05, /* Report Size (5) */
338
0x81, 0x01, /* Input (Constant) */
339
0x05, 0x01, /* Usage Page (Generic Desktop) */
340
0x09, 0x30, /* Usage (X) */
341
0x09, 0x31, /* Usage (Y) */
342
0x15, 0x00, /* Logical Minimum (0) */
343
0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
344
0x35, 0x00, /* Physical Minimum (0) */
345
0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
346
0x75, 0x10, /* Report Size (16) */
347
0x95, 0x02, /* Report Count (2) */
348
0x81, 0x02, /* Input (Data, Variable, Absolute) */
349
0x05, 0x01, /* Usage Page (Generic Desktop) */
350
0x09, 0x38, /* Usage (Wheel) */
351
0x15, 0x81, /* Logical Minimum (-0x7f) */
352
0x25, 0x7f, /* Logical Maximum (0x7f) */
353
0x35, 0x00, /* Physical Minimum (same as logical) */
354
0x45, 0x00, /* Physical Maximum (same as logical) */
355
0x75, 0x08, /* Report Size (8) */
356
0x95, 0x01, /* Report Count (1) */
357
0x81, 0x06, /* Input (Data, Variable, Relative) */
358
0xc0, /* End Collection */
359
0xc0, /* End Collection */
362
static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
363
0x05, 0x01, /* Usage Page (Generic Desktop) */
364
0x09, 0x06, /* Usage (Keyboard) */
365
0xa1, 0x01, /* Collection (Application) */
366
0x75, 0x01, /* Report Size (1) */
367
0x95, 0x08, /* Report Count (8) */
368
0x05, 0x07, /* Usage Page (Key Codes) */
369
0x19, 0xe0, /* Usage Minimum (224) */
370
0x29, 0xe7, /* Usage Maximum (231) */
371
0x15, 0x00, /* Logical Minimum (0) */
372
0x25, 0x01, /* Logical Maximum (1) */
373
0x81, 0x02, /* Input (Data, Variable, Absolute) */
374
0x95, 0x01, /* Report Count (1) */
375
0x75, 0x08, /* Report Size (8) */
376
0x81, 0x01, /* Input (Constant) */
377
0x95, 0x05, /* Report Count (5) */
378
0x75, 0x01, /* Report Size (1) */
379
0x05, 0x08, /* Usage Page (LEDs) */
380
0x19, 0x01, /* Usage Minimum (1) */
381
0x29, 0x05, /* Usage Maximum (5) */
382
0x91, 0x02, /* Output (Data, Variable, Absolute) */
383
0x95, 0x01, /* Report Count (1) */
384
0x75, 0x03, /* Report Size (3) */
385
0x91, 0x01, /* Output (Constant) */
386
0x95, 0x06, /* Report Count (6) */
387
0x75, 0x08, /* Report Size (8) */
388
0x15, 0x00, /* Logical Minimum (0) */
389
0x25, 0xff, /* Logical Maximum (255) */
390
0x05, 0x07, /* Usage Page (Key Codes) */
391
0x19, 0x00, /* Usage Minimum (0) */
392
0x29, 0xff, /* Usage Maximum (255) */
393
0x81, 0x00, /* Input (Data, Array) */
394
0xc0, /* End Collection */
397
#define USB_HID_USAGE_ERROR_ROLLOVER 0x01
398
#define USB_HID_USAGE_POSTFAIL 0x02
399
#define USB_HID_USAGE_ERROR_UNDEFINED 0x03
401
/* Indices are QEMU keycodes, values are from HID Usage Table. Indices
402
* above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
403
static const uint8_t usb_hid_usage_keys[0x100] = {
404
0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
405
0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
406
0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
407
0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
408
0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
409
0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
410
0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
411
0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
412
0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
413
0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
414
0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
415
0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
416
0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
417
0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
418
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419
0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
421
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424
0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
425
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427
0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
428
0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
430
0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
431
0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
432
0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
433
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439
static void usb_hid_changed(USBHIDState *hs)
444
hs->datain(hs->datain_opaque);
446
usb_wakeup(&hs->dev);
449
static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
450
e->xdx = e->ydy = e->dz = 0;
451
e->buttons_state = buttons;
454
static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,
455
int x1, int y1, int z1) {
466
static void usb_pointer_event(void *opaque,
467
int x1, int y1, int z1, int buttons_state)
469
USBHIDState *hs = opaque;
470
USBMouseState *s = &hs->ptr;
471
unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
472
unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
474
/* We combine events where feasible to keep the queue small. We shouldn't
475
* combine anything with the first event of a particular button state, as
476
* that would change the location of the button state change. When the
477
* queue is empty, a second event is needed because we don't know if
478
* the first event changed the button state. */
479
if (hs->n == QUEUE_LENGTH) {
480
/* Queue full. Discard old button state, combine motion normally. */
481
s->queue[use_slot].buttons_state = buttons_state;
482
} else if (hs->n < 2 ||
483
s->queue[use_slot].buttons_state != buttons_state ||
484
s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
485
/* Cannot or should not combine, so add an empty item to the queue. */
486
QUEUE_INCR(use_slot);
488
usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
490
usb_pointer_event_combine(&s->queue[use_slot],
491
hs->kind == USB_MOUSE,
496
static void usb_keyboard_event(void *opaque, int keycode)
498
USBHIDState *hs = opaque;
499
USBKeyboardState *s = &hs->kbd;
502
if (hs->n == QUEUE_LENGTH) {
503
fprintf(stderr, "usb-kbd: warning: key event queue full\n");
506
slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
507
s->keycodes[slot] = keycode;
511
static void usb_keyboard_process_keycode(USBHIDState *hs)
513
USBKeyboardState *s = &hs->kbd;
514
uint8_t hid_code, key;
515
int i, keycode, slot;
520
slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
521
keycode = s->keycodes[slot];
523
key = keycode & 0x7f;
524
hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
525
s->modifiers &= ~(1 << 8);
532
if (s->modifiers & (1 << 9)) {
533
s->modifiers ^= 3 << 8;
537
if (keycode & (1 << 7)) {
538
s->modifiers &= ~(1 << (hid_code & 0x0f));
542
s->modifiers |= 1 << (hid_code & 0x0f);
546
if (keycode & (1 << 7)) {
547
for (i = s->keys - 1; i >= 0; i --)
548
if (s->key[i] == hid_code) {
549
s->key[i] = s->key[-- s->keys];
550
s->key[s->keys] = 0x00;
556
for (i = s->keys - 1; i >= 0; i --)
557
if (s->key[i] == hid_code)
560
if (s->keys < sizeof(s->key))
561
s->key[s->keys ++] = hid_code;
567
static inline int int_clamp(int val, int vmin, int vmax)
577
static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
579
int dx, dy, dz, b, l;
581
USBMouseState *s = &hs->ptr;
584
if (!s->mouse_grabbed) {
585
qemu_activate_mouse_event_handler(s->eh_entry);
586
s->mouse_grabbed = 1;
589
/* When the buffer is empty, return the last event. Relative
590
movements will all be zero. */
591
index = (hs->n ? hs->head : hs->head - 1);
592
e = &s->queue[index & QUEUE_MASK];
594
if (hs->kind == USB_MOUSE) {
595
dx = int_clamp(e->xdx, -127, 127);
596
dy = int_clamp(e->ydy, -127, 127);
603
dz = int_clamp(e->dz, -127, 127);
607
if (e->buttons_state & MOUSE_EVENT_LBUTTON)
609
if (e->buttons_state & MOUSE_EVENT_RBUTTON)
611
if (e->buttons_state & MOUSE_EVENT_MBUTTON)
616
(hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
617
/* that deals with this event */
618
QUEUE_INCR(hs->head);
622
/* Appears we have to invert the wheel direction */
641
buf[l++] = dx & 0xff;
645
buf[l++] = dy & 0xff;
659
static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
661
USBKeyboardState *s = &hs->kbd;
665
usb_keyboard_process_keycode(hs);
667
buf[0] = s->modifiers & 0xff;
670
memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
672
memcpy(buf + 2, s->key, MIN(8, len) - 2);
677
static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
681
/* 0x01: Num Lock LED
682
* 0x02: Caps Lock LED
683
* 0x04: Scroll Lock LED
688
ledstate |= QEMU_SCROLL_LOCK_LED;
690
ledstate |= QEMU_NUM_LOCK_LED;
692
ledstate |= QEMU_CAPS_LOCK_LED;
693
kbd_put_ledstate(ledstate);
698
static void usb_mouse_handle_reset(USBDevice *dev)
700
USBHIDState *s = (USBHIDState *)dev;
702
memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
708
static void usb_keyboard_handle_reset(USBDevice *dev)
710
USBHIDState *s = (USBHIDState *)dev;
712
qemu_add_kbd_event_handler(usb_keyboard_event, s);
713
memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
716
memset(s->kbd.key, 0, sizeof (s->kbd.key));
721
static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
723
s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
726
static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
727
int request, int value, int index, int length, uint8_t *data)
729
USBHIDState *s = (USBHIDState *)dev;
732
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
739
case DeviceRequest | USB_REQ_GET_INTERFACE:
743
case DeviceOutRequest | USB_REQ_SET_INTERFACE:
746
/* hid specific requests */
747
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
750
if (s->kind == USB_MOUSE) {
751
memcpy(data, qemu_mouse_hid_report_descriptor,
752
sizeof(qemu_mouse_hid_report_descriptor));
753
ret = sizeof(qemu_mouse_hid_report_descriptor);
754
} else if (s->kind == USB_TABLET) {
755
memcpy(data, qemu_tablet_hid_report_descriptor,
756
sizeof(qemu_tablet_hid_report_descriptor));
757
ret = sizeof(qemu_tablet_hid_report_descriptor);
758
} else if (s->kind == USB_KEYBOARD) {
759
memcpy(data, qemu_keyboard_hid_report_descriptor,
760
sizeof(qemu_keyboard_hid_report_descriptor));
761
ret = sizeof(qemu_keyboard_hid_report_descriptor);
769
if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
770
ret = usb_pointer_poll(s, data, length);
771
} else if (s->kind == USB_KEYBOARD) {
772
ret = usb_keyboard_poll(s, data, length);
774
s->changed = s->n > 0;
777
if (s->kind == USB_KEYBOARD)
778
ret = usb_keyboard_write(&s->kbd, data, length);
783
if (s->kind != USB_KEYBOARD && s->kind != USB_MOUSE)
786
data[0] = s->protocol;
789
if (s->kind != USB_KEYBOARD && s->kind != USB_MOUSE)
799
s->idle = (uint8_t) (value >> 8);
800
usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
811
static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
813
USBHIDState *s = (USBHIDState *)dev;
819
int64_t curtime = qemu_get_clock_ns(vm_clock);
820
if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
822
usb_hid_set_next_idle(s, curtime);
823
if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
824
ret = usb_pointer_poll(s, p->data, p->len);
826
else if (s->kind == USB_KEYBOARD) {
827
ret = usb_keyboard_poll(s, p->data, p->len);
829
s->changed = s->n > 0;
843
static void usb_hid_handle_destroy(USBDevice *dev)
845
USBHIDState *s = (USBHIDState *)dev;
849
qemu_remove_kbd_event_handler();
852
qemu_remove_mouse_event_handler(s->ptr.eh_entry);
856
static int usb_hid_initfn(USBDevice *dev, int kind)
858
USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
863
if (s->kind == USB_MOUSE) {
864
s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
865
0, "QEMU USB Mouse");
866
} else if (s->kind == USB_TABLET) {
867
s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
868
1, "QEMU USB Tablet");
871
/* Force poll routine to be run and grab input the first time. */
876
static int usb_tablet_initfn(USBDevice *dev)
878
return usb_hid_initfn(dev, USB_TABLET);
881
static int usb_mouse_initfn(USBDevice *dev)
883
return usb_hid_initfn(dev, USB_MOUSE);
886
static int usb_keyboard_initfn(USBDevice *dev)
888
return usb_hid_initfn(dev, USB_KEYBOARD);
891
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
893
USBHIDState *s = (USBHIDState *)dev;
895
s->datain_opaque = opaque;
899
static int usb_hid_post_load(void *opaque, int version_id)
901
USBHIDState *s = opaque;
904
usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
909
static const VMStateDescription vmstate_usb_ptr_queue = {
910
.name = "usb-ptr-queue",
912
.minimum_version_id = 1,
913
.fields = (VMStateField []) {
914
VMSTATE_INT32(xdx, USBPointerEvent),
915
VMSTATE_INT32(ydy, USBPointerEvent),
916
VMSTATE_INT32(dz, USBPointerEvent),
917
VMSTATE_INT32(buttons_state, USBPointerEvent),
918
VMSTATE_END_OF_LIST()
921
static const VMStateDescription vmstate_usb_ptr = {
924
.minimum_version_id = 1,
925
.post_load = usb_hid_post_load,
926
.fields = (VMStateField []) {
927
VMSTATE_USB_DEVICE(dev, USBHIDState),
928
VMSTATE_STRUCT_ARRAY(ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
929
vmstate_usb_ptr_queue, USBPointerEvent),
930
VMSTATE_UINT32(head, USBHIDState),
931
VMSTATE_UINT32(n, USBHIDState),
932
VMSTATE_INT32(protocol, USBHIDState),
933
VMSTATE_UINT8(idle, USBHIDState),
934
VMSTATE_END_OF_LIST()
938
static const VMStateDescription vmstate_usb_kbd = {
941
.minimum_version_id = 1,
942
.post_load = usb_hid_post_load,
943
.fields = (VMStateField []) {
944
VMSTATE_USB_DEVICE(dev, USBHIDState),
945
VMSTATE_UINT32_ARRAY(kbd.keycodes, USBHIDState, QUEUE_LENGTH),
946
VMSTATE_UINT32(head, USBHIDState),
947
VMSTATE_UINT32(n, USBHIDState),
948
VMSTATE_UINT16(kbd.modifiers, USBHIDState),
949
VMSTATE_UINT8(kbd.leds, USBHIDState),
950
VMSTATE_UINT8_ARRAY(kbd.key, USBHIDState, 16),
951
VMSTATE_INT32(kbd.keys, USBHIDState),
952
VMSTATE_INT32(protocol, USBHIDState),
953
VMSTATE_UINT8(idle, USBHIDState),
954
VMSTATE_END_OF_LIST()
958
static struct USBDeviceInfo hid_info[] = {
960
.product_desc = "QEMU USB Tablet",
961
.qdev.name = "usb-tablet",
962
.usbdevice_name = "tablet",
963
.qdev.size = sizeof(USBHIDState),
964
.qdev.vmsd = &vmstate_usb_ptr,
965
.usb_desc = &desc_tablet,
966
.init = usb_tablet_initfn,
967
.handle_packet = usb_generic_handle_packet,
968
.handle_reset = usb_mouse_handle_reset,
969
.handle_control = usb_hid_handle_control,
970
.handle_data = usb_hid_handle_data,
971
.handle_destroy = usb_hid_handle_destroy,
973
.product_desc = "QEMU USB Mouse",
974
.qdev.name = "usb-mouse",
975
.usbdevice_name = "mouse",
976
.qdev.size = sizeof(USBHIDState),
977
.qdev.vmsd = &vmstate_usb_ptr,
978
.usb_desc = &desc_mouse,
979
.init = usb_mouse_initfn,
980
.handle_packet = usb_generic_handle_packet,
981
.handle_reset = usb_mouse_handle_reset,
982
.handle_control = usb_hid_handle_control,
983
.handle_data = usb_hid_handle_data,
984
.handle_destroy = usb_hid_handle_destroy,
986
.product_desc = "QEMU USB Keyboard",
987
.qdev.name = "usb-kbd",
988
.usbdevice_name = "keyboard",
989
.qdev.size = sizeof(USBHIDState),
990
.qdev.vmsd = &vmstate_usb_kbd,
991
.usb_desc = &desc_keyboard,
992
.init = usb_keyboard_initfn,
993
.handle_packet = usb_generic_handle_packet,
994
.handle_reset = usb_keyboard_handle_reset,
995
.handle_control = usb_hid_handle_control,
996
.handle_data = usb_hid_handle_data,
997
.handle_destroy = usb_hid_handle_destroy,
1003
static void usb_hid_register_devices(void)
1005
usb_qdev_register_many(hid_info);
1007
device_init(usb_hid_register_devices)