usb keyboard: add event event queue
[qemu.git] / hw / usb-hid.c
blob5f1451b6854ff1ce1b63d9dbcbaf10be98327291
1 /*
2 * QEMU USB HID devices
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
23 * THE SOFTWARE.
25 #include "hw.h"
26 #include "console.h"
27 #include "usb.h"
28 #include "usb-desc.h"
29 #include "sysemu.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
44 #define USB_MOUSE 1
45 #define USB_TABLET 2
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;
51 } USBPointerEvent;
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];
59 uint32_t head; /* index into circular queue */
60 uint32_t n;
61 int mouse_grabbed;
62 QEMUPutMouseEntry *eh_entry;
63 } USBMouseState;
65 typedef struct USBKeyboardState {
66 uint32_t keycodes[QUEUE_LENGTH];
67 uint32_t head; /* index into circular queue */
68 uint32_t n;
69 uint16_t modifiers;
70 uint8_t leds;
71 uint8_t key[16];
72 int keys;
73 } USBKeyboardState;
75 typedef struct USBHIDState {
76 USBDevice dev;
77 union {
78 USBMouseState ptr;
79 USBKeyboardState kbd;
81 int kind;
82 int protocol;
83 uint8_t idle;
84 int64_t next_idle_clock;
85 int changed;
86 void *datain_opaque;
87 void (*datain)(void *);
88 } USBHIDState;
90 enum {
91 STR_MANUFACTURER = 1,
92 STR_PRODUCT_MOUSE,
93 STR_PRODUCT_TABLET,
94 STR_PRODUCT_KEYBOARD,
95 STR_SERIALNUMBER,
96 STR_CONFIG_MOUSE,
97 STR_CONFIG_TABLET,
98 STR_CONFIG_KEYBOARD,
101 static const USBDescStrings desc_strings = {
102 [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
103 [STR_PRODUCT_MOUSE] = "QEMU USB Mouse",
104 [STR_PRODUCT_TABLET] = "QEMU USB Tablet",
105 [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
106 [STR_SERIALNUMBER] = "42", /* == remote wakeup works */
107 [STR_CONFIG_MOUSE] = "HID Mouse",
108 [STR_CONFIG_TABLET] = "HID Tablet",
109 [STR_CONFIG_KEYBOARD] = "HID Keyboard",
112 static const USBDescIface desc_iface_mouse = {
113 .bInterfaceNumber = 0,
114 .bNumEndpoints = 1,
115 .bInterfaceClass = USB_CLASS_HID,
116 .bInterfaceSubClass = 0x01, /* boot */
117 .bInterfaceProtocol = 0x02,
118 .ndesc = 1,
119 .descs = (USBDescOther[]) {
121 /* HID descriptor */
122 .data = (uint8_t[]) {
123 0x09, /* u8 bLength */
124 USB_DT_HID, /* u8 bDescriptorType */
125 0x01, 0x00, /* u16 HID_class */
126 0x00, /* u8 country_code */
127 0x01, /* u8 num_descriptors */
128 USB_DT_REPORT, /* u8 type: Report */
129 52, 0, /* u16 len */
133 .eps = (USBDescEndpoint[]) {
135 .bEndpointAddress = USB_DIR_IN | 0x01,
136 .bmAttributes = USB_ENDPOINT_XFER_INT,
137 .wMaxPacketSize = 4,
138 .bInterval = 0x0a,
143 static const USBDescIface desc_iface_tablet = {
144 .bInterfaceNumber = 0,
145 .bNumEndpoints = 1,
146 .bInterfaceClass = USB_CLASS_HID,
147 .bInterfaceSubClass = 0x01, /* boot */
148 .bInterfaceProtocol = 0x02,
149 .ndesc = 1,
150 .descs = (USBDescOther[]) {
152 /* HID descriptor */
153 .data = (uint8_t[]) {
154 0x09, /* u8 bLength */
155 USB_DT_HID, /* u8 bDescriptorType */
156 0x01, 0x00, /* u16 HID_class */
157 0x00, /* u8 country_code */
158 0x01, /* u8 num_descriptors */
159 USB_DT_REPORT, /* u8 type: Report */
160 74, 0, /* u16 len */
164 .eps = (USBDescEndpoint[]) {
166 .bEndpointAddress = USB_DIR_IN | 0x01,
167 .bmAttributes = USB_ENDPOINT_XFER_INT,
168 .wMaxPacketSize = 8,
169 .bInterval = 0x0a,
174 static const USBDescIface desc_iface_keyboard = {
175 .bInterfaceNumber = 0,
176 .bNumEndpoints = 1,
177 .bInterfaceClass = USB_CLASS_HID,
178 .bInterfaceSubClass = 0x01, /* boot */
179 .bInterfaceProtocol = 0x01, /* keyboard */
180 .ndesc = 1,
181 .descs = (USBDescOther[]) {
183 /* HID descriptor */
184 .data = (uint8_t[]) {
185 0x09, /* u8 bLength */
186 USB_DT_HID, /* u8 bDescriptorType */
187 0x11, 0x01, /* u16 HID_class */
188 0x00, /* u8 country_code */
189 0x01, /* u8 num_descriptors */
190 USB_DT_REPORT, /* u8 type: Report */
191 0x3f, 0, /* u16 len */
195 .eps = (USBDescEndpoint[]) {
197 .bEndpointAddress = USB_DIR_IN | 0x01,
198 .bmAttributes = USB_ENDPOINT_XFER_INT,
199 .wMaxPacketSize = 8,
200 .bInterval = 0x0a,
205 static const USBDescDevice desc_device_mouse = {
206 .bcdUSB = 0x0100,
207 .bMaxPacketSize0 = 8,
208 .bNumConfigurations = 1,
209 .confs = (USBDescConfig[]) {
211 .bNumInterfaces = 1,
212 .bConfigurationValue = 1,
213 .iConfiguration = STR_CONFIG_MOUSE,
214 .bmAttributes = 0xa0,
215 .bMaxPower = 50,
216 .ifs = &desc_iface_mouse,
221 static const USBDescDevice desc_device_tablet = {
222 .bcdUSB = 0x0100,
223 .bMaxPacketSize0 = 8,
224 .bNumConfigurations = 1,
225 .confs = (USBDescConfig[]) {
227 .bNumInterfaces = 1,
228 .bConfigurationValue = 1,
229 .iConfiguration = STR_CONFIG_TABLET,
230 .bmAttributes = 0xa0,
231 .bMaxPower = 50,
232 .ifs = &desc_iface_tablet,
237 static const USBDescDevice desc_device_keyboard = {
238 .bcdUSB = 0x0100,
239 .bMaxPacketSize0 = 8,
240 .bNumConfigurations = 1,
241 .confs = (USBDescConfig[]) {
243 .bNumInterfaces = 1,
244 .bConfigurationValue = 1,
245 .iConfiguration = STR_CONFIG_KEYBOARD,
246 .bmAttributes = 0xa0,
247 .bMaxPower = 50,
248 .ifs = &desc_iface_keyboard,
253 static const USBDesc desc_mouse = {
254 .id = {
255 .idVendor = 0x0627,
256 .idProduct = 0x0001,
257 .bcdDevice = 0,
258 .iManufacturer = STR_MANUFACTURER,
259 .iProduct = STR_PRODUCT_MOUSE,
260 .iSerialNumber = STR_SERIALNUMBER,
262 .full = &desc_device_mouse,
263 .str = desc_strings,
266 static const USBDesc desc_tablet = {
267 .id = {
268 .idVendor = 0x0627,
269 .idProduct = 0x0001,
270 .bcdDevice = 0,
271 .iManufacturer = STR_MANUFACTURER,
272 .iProduct = STR_PRODUCT_TABLET,
273 .iSerialNumber = STR_SERIALNUMBER,
275 .full = &desc_device_tablet,
276 .str = desc_strings,
279 static const USBDesc desc_keyboard = {
280 .id = {
281 .idVendor = 0x0627,
282 .idProduct = 0x0001,
283 .bcdDevice = 0,
284 .iManufacturer = STR_MANUFACTURER,
285 .iProduct = STR_PRODUCT_KEYBOARD,
286 .iSerialNumber = STR_SERIALNUMBER,
288 .full = &desc_device_keyboard,
289 .str = desc_strings,
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)
441 hs->changed = 1;
443 if (hs->datain)
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) {
456 if (xyrel) {
457 e->xdx += x1;
458 e->ydy += y1;
459 } else {
460 e->xdx = x1;
461 e->ydy = y1;
463 e->dz += 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 = (s->head + s->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 (s->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 (s->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);
487 s->n++;
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,
492 x1, y1, z1);
493 usb_hid_changed(hs);
496 static void usb_keyboard_event(void *opaque, int keycode)
498 USBHIDState *hs = opaque;
499 USBKeyboardState *s = &hs->kbd;
500 int slot;
502 if (s->n == QUEUE_LENGTH) {
503 fprintf(stderr, "usb-kbd: warning: key event queue full\n");
504 return;
506 slot = (s->head + s->n) & QUEUE_MASK; s->n++;
507 s->keycodes[slot] = keycode;
508 usb_hid_changed(hs);
511 static void usb_keyboard_process_keycode(USBKeyboardState *s)
513 uint8_t hid_code, key;
514 int i, keycode, slot;
516 if (s->n == 0) {
517 return;
519 slot = s->head & QUEUE_MASK; QUEUE_INCR(s->head); s->n--;
520 keycode = s->keycodes[slot];
522 key = keycode & 0x7f;
523 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
524 s->modifiers &= ~(1 << 8);
526 switch (hid_code) {
527 case 0x00:
528 return;
530 case 0xe0:
531 if (s->modifiers & (1 << 9)) {
532 s->modifiers ^= 3 << 8;
533 usb_hid_changed(hs);
534 return;
536 case 0xe1 ... 0xe7:
537 if (keycode & (1 << 7)) {
538 s->modifiers &= ~(1 << (hid_code & 0x0f));
539 usb_hid_changed(hs);
540 return;
542 case 0xe8 ... 0xef:
543 s->modifiers |= 1 << (hid_code & 0x0f);
544 usb_hid_changed(hs);
545 return;
548 if (keycode & (1 << 7)) {
549 for (i = s->keys - 1; i >= 0; i --)
550 if (s->key[i] == hid_code) {
551 s->key[i] = s->key[-- s->keys];
552 s->key[s->keys] = 0x00;
553 break;
555 if (i < 0)
556 return;
557 } else {
558 for (i = s->keys - 1; i >= 0; i --)
559 if (s->key[i] == hid_code)
560 break;
561 if (i < 0) {
562 if (s->keys < sizeof(s->key))
563 s->key[s->keys ++] = hid_code;
564 } else
565 return;
569 static inline int int_clamp(int val, int vmin, int vmax)
571 if (val < vmin)
572 return vmin;
573 else if (val > vmax)
574 return vmax;
575 else
576 return val;
579 static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
581 int dx, dy, dz, b, l;
582 int index;
583 USBMouseState *s = &hs->ptr;
584 USBPointerEvent *e;
586 if (!s->mouse_grabbed) {
587 qemu_activate_mouse_event_handler(s->eh_entry);
588 s->mouse_grabbed = 1;
591 /* When the buffer is empty, return the last event. Relative
592 movements will all be zero. */
593 index = (s->n ? s->head : s->head - 1);
594 e = &s->queue[index & QUEUE_MASK];
596 if (hs->kind == USB_MOUSE) {
597 dx = int_clamp(e->xdx, -127, 127);
598 dy = int_clamp(e->ydy, -127, 127);
599 e->xdx -= dx;
600 e->ydy -= dy;
601 } else {
602 dx = e->xdx;
603 dy = e->ydy;
605 dz = int_clamp(e->dz, -127, 127);
606 e->dz -= dz;
608 b = 0;
609 if (e->buttons_state & MOUSE_EVENT_LBUTTON)
610 b |= 0x01;
611 if (e->buttons_state & MOUSE_EVENT_RBUTTON)
612 b |= 0x02;
613 if (e->buttons_state & MOUSE_EVENT_MBUTTON)
614 b |= 0x04;
616 if (s->n &&
617 !e->dz &&
618 (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
619 /* that deals with this event */
620 QUEUE_INCR(s->head);
621 s->n--;
624 /* Appears we have to invert the wheel direction */
625 dz = 0 - dz;
626 l = 0;
627 switch (hs->kind) {
628 case USB_MOUSE:
629 if (len > l)
630 buf[l++] = b;
631 if (len > l)
632 buf[l++] = dx;
633 if (len > l)
634 buf[l++] = dy;
635 if (len > l)
636 buf[l++] = dz;
637 break;
639 case USB_TABLET:
640 if (len > l)
641 buf[l++] = b;
642 if (len > l)
643 buf[l++] = dx & 0xff;
644 if (len > l)
645 buf[l++] = dx >> 8;
646 if (len > l)
647 buf[l++] = dy & 0xff;
648 if (len > l)
649 buf[l++] = dy >> 8;
650 if (len > l)
651 buf[l++] = dz;
652 break;
654 default:
655 abort();
658 return l;
661 static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
663 USBKeyboardState *s = &hs->kbd;
664 if (len < 2)
665 return 0;
667 usb_keyboard_process_keycode(s);
669 buf[0] = s->modifiers & 0xff;
670 buf[1] = 0;
671 if (s->keys > 6)
672 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
673 else
674 memcpy(buf + 2, s->key, MIN(8, len) - 2);
676 return MIN(8, len);
679 static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
681 if (len > 0) {
682 int ledstate = 0;
683 /* 0x01: Num Lock LED
684 * 0x02: Caps Lock LED
685 * 0x04: Scroll Lock LED
686 * 0x08: Compose LED
687 * 0x10: Kana LED */
688 s->leds = buf[0];
689 if (s->leds & 0x04)
690 ledstate |= QEMU_SCROLL_LOCK_LED;
691 if (s->leds & 0x01)
692 ledstate |= QEMU_NUM_LOCK_LED;
693 if (s->leds & 0x02)
694 ledstate |= QEMU_CAPS_LOCK_LED;
695 kbd_put_ledstate(ledstate);
697 return 0;
700 static void usb_mouse_handle_reset(USBDevice *dev)
702 USBHIDState *s = (USBHIDState *)dev;
704 memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
705 s->ptr.head = 0;
706 s->ptr.n = 0;
707 s->protocol = 1;
710 static void usb_keyboard_handle_reset(USBDevice *dev)
712 USBHIDState *s = (USBHIDState *)dev;
714 qemu_add_kbd_event_handler(usb_keyboard_event, s);
715 memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
716 s->kbd.head = 0;
717 s->kbd.n = 0;
718 memset(s->kbd.key, 0, sizeof (s->kbd.key));
719 s->kbd.keys = 0;
720 s->protocol = 1;
723 static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
725 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
728 static int usb_hid_handle_control(USBDevice *dev, int request, int value,
729 int index, int length, uint8_t *data)
731 USBHIDState *s = (USBHIDState *)dev;
732 int ret;
734 ret = usb_desc_handle_control(dev, request, value, index, length, data);
735 if (ret >= 0) {
736 return ret;
739 ret = 0;
740 switch(request) {
741 case DeviceRequest | USB_REQ_GET_INTERFACE:
742 data[0] = 0;
743 ret = 1;
744 break;
745 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
746 ret = 0;
747 break;
748 /* hid specific requests */
749 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
750 switch(value >> 8) {
751 case 0x22:
752 if (s->kind == USB_MOUSE) {
753 memcpy(data, qemu_mouse_hid_report_descriptor,
754 sizeof(qemu_mouse_hid_report_descriptor));
755 ret = sizeof(qemu_mouse_hid_report_descriptor);
756 } else if (s->kind == USB_TABLET) {
757 memcpy(data, qemu_tablet_hid_report_descriptor,
758 sizeof(qemu_tablet_hid_report_descriptor));
759 ret = sizeof(qemu_tablet_hid_report_descriptor);
760 } else if (s->kind == USB_KEYBOARD) {
761 memcpy(data, qemu_keyboard_hid_report_descriptor,
762 sizeof(qemu_keyboard_hid_report_descriptor));
763 ret = sizeof(qemu_keyboard_hid_report_descriptor);
765 break;
766 default:
767 goto fail;
769 break;
770 case GET_REPORT:
771 if (s->kind == USB_MOUSE || s->kind == USB_TABLET)
772 ret = usb_pointer_poll(s, data, length);
773 else if (s->kind == USB_KEYBOARD)
774 ret = usb_keyboard_poll(s, data, length);
775 break;
776 case SET_REPORT:
777 if (s->kind == USB_KEYBOARD)
778 ret = usb_keyboard_write(&s->kbd, data, length);
779 else
780 goto fail;
781 break;
782 case GET_PROTOCOL:
783 if (s->kind != USB_KEYBOARD)
784 goto fail;
785 ret = 1;
786 data[0] = s->protocol;
787 break;
788 case SET_PROTOCOL:
789 if (s->kind != USB_KEYBOARD)
790 goto fail;
791 ret = 0;
792 s->protocol = value;
793 break;
794 case GET_IDLE:
795 ret = 1;
796 data[0] = s->idle;
797 break;
798 case SET_IDLE:
799 s->idle = (uint8_t) (value >> 8);
800 usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
801 ret = 0;
802 break;
803 default:
804 fail:
805 ret = USB_RET_STALL;
806 break;
808 return ret;
811 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
813 USBHIDState *s = (USBHIDState *)dev;
814 int ret = 0;
816 switch(p->pid) {
817 case USB_TOKEN_IN:
818 if (p->devep == 1) {
819 int64_t curtime = qemu_get_clock(vm_clock);
820 if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
821 return USB_RET_NAK;
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);
825 s->changed = s->ptr.n > 0;
827 else if (s->kind == USB_KEYBOARD) {
828 ret = usb_keyboard_poll(s, p->data, p->len);
829 s->changed = s->kbd.n > 0;
831 } else {
832 goto fail;
834 break;
835 case USB_TOKEN_OUT:
836 default:
837 fail:
838 ret = USB_RET_STALL;
839 break;
841 return ret;
844 static void usb_hid_handle_destroy(USBDevice *dev)
846 USBHIDState *s = (USBHIDState *)dev;
848 switch(s->kind) {
849 case USB_KEYBOARD:
850 qemu_remove_kbd_event_handler();
851 break;
852 default:
853 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
857 static int usb_hid_initfn(USBDevice *dev, int kind)
859 USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
861 usb_desc_init(dev);
862 s->kind = kind;
864 if (s->kind == USB_MOUSE) {
865 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
866 0, "QEMU USB Mouse");
867 } else if (s->kind == USB_TABLET) {
868 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
869 1, "QEMU USB Tablet");
872 /* Force poll routine to be run and grab input the first time. */
873 s->changed = 1;
874 return 0;
877 static int usb_tablet_initfn(USBDevice *dev)
879 return usb_hid_initfn(dev, USB_TABLET);
882 static int usb_mouse_initfn(USBDevice *dev)
884 return usb_hid_initfn(dev, USB_MOUSE);
887 static int usb_keyboard_initfn(USBDevice *dev)
889 return usb_hid_initfn(dev, USB_KEYBOARD);
892 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
894 USBHIDState *s = (USBHIDState *)dev;
896 s->datain_opaque = opaque;
897 s->datain = datain;
900 static struct USBDeviceInfo hid_info[] = {
902 .product_desc = "QEMU USB Tablet",
903 .qdev.name = "usb-tablet",
904 .usbdevice_name = "tablet",
905 .qdev.size = sizeof(USBHIDState),
906 .usb_desc = &desc_tablet,
907 .init = usb_tablet_initfn,
908 .handle_packet = usb_generic_handle_packet,
909 .handle_reset = usb_mouse_handle_reset,
910 .handle_control = usb_hid_handle_control,
911 .handle_data = usb_hid_handle_data,
912 .handle_destroy = usb_hid_handle_destroy,
914 .product_desc = "QEMU USB Mouse",
915 .qdev.name = "usb-mouse",
916 .usbdevice_name = "mouse",
917 .qdev.size = sizeof(USBHIDState),
918 .usb_desc = &desc_mouse,
919 .init = usb_mouse_initfn,
920 .handle_packet = usb_generic_handle_packet,
921 .handle_reset = usb_mouse_handle_reset,
922 .handle_control = usb_hid_handle_control,
923 .handle_data = usb_hid_handle_data,
924 .handle_destroy = usb_hid_handle_destroy,
926 .product_desc = "QEMU USB Keyboard",
927 .qdev.name = "usb-kbd",
928 .usbdevice_name = "keyboard",
929 .qdev.size = sizeof(USBHIDState),
930 .usb_desc = &desc_keyboard,
931 .init = usb_keyboard_initfn,
932 .handle_packet = usb_generic_handle_packet,
933 .handle_reset = usb_keyboard_handle_reset,
934 .handle_control = usb_hid_handle_control,
935 .handle_data = usb_hid_handle_data,
936 .handle_destroy = usb_hid_handle_destroy,
938 /* end of list */
942 static void usb_hid_register_devices(void)
944 usb_qdev_register_many(hid_info);
946 device_init(usb_hid_register_devices)