guest agent: add --enable-guest-agent config option
[qemu.git] / hw / usb-hid.c
blob9008320c863905e40e3ce312eb7b1e7c88217ade
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 "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
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 int mouse_grabbed;
60 QEMUPutMouseEntry *eh_entry;
61 } USBMouseState;
63 typedef struct USBKeyboardState {
64 uint32_t keycodes[QUEUE_LENGTH];
65 uint16_t modifiers;
66 uint8_t leds;
67 uint8_t key[16];
68 int32_t keys;
69 } USBKeyboardState;
71 typedef struct USBHIDState {
72 USBDevice dev;
73 union {
74 USBMouseState ptr;
75 USBKeyboardState kbd;
77 uint32_t head; /* index into circular queue */
78 uint32_t n;
79 int kind;
80 int32_t protocol;
81 uint8_t idle;
82 int64_t next_idle_clock;
83 int changed;
84 void *datain_opaque;
85 void (*datain)(void *);
86 } USBHIDState;
88 enum {
89 STR_MANUFACTURER = 1,
90 STR_PRODUCT_MOUSE,
91 STR_PRODUCT_TABLET,
92 STR_PRODUCT_KEYBOARD,
93 STR_SERIALNUMBER,
94 STR_CONFIG_MOUSE,
95 STR_CONFIG_TABLET,
96 STR_CONFIG_KEYBOARD,
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,
112 .bNumEndpoints = 1,
113 .bInterfaceClass = USB_CLASS_HID,
114 .bInterfaceSubClass = 0x01, /* boot */
115 .bInterfaceProtocol = 0x02,
116 .ndesc = 1,
117 .descs = (USBDescOther[]) {
119 /* HID descriptor */
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 */
127 52, 0, /* u16 len */
131 .eps = (USBDescEndpoint[]) {
133 .bEndpointAddress = USB_DIR_IN | 0x01,
134 .bmAttributes = USB_ENDPOINT_XFER_INT,
135 .wMaxPacketSize = 4,
136 .bInterval = 0x0a,
141 static const USBDescIface desc_iface_tablet = {
142 .bInterfaceNumber = 0,
143 .bNumEndpoints = 1,
144 .bInterfaceClass = USB_CLASS_HID,
145 .bInterfaceProtocol = 0x02,
146 .ndesc = 1,
147 .descs = (USBDescOther[]) {
149 /* HID descriptor */
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 */
157 74, 0, /* u16 len */
161 .eps = (USBDescEndpoint[]) {
163 .bEndpointAddress = USB_DIR_IN | 0x01,
164 .bmAttributes = USB_ENDPOINT_XFER_INT,
165 .wMaxPacketSize = 8,
166 .bInterval = 0x0a,
171 static const USBDescIface desc_iface_keyboard = {
172 .bInterfaceNumber = 0,
173 .bNumEndpoints = 1,
174 .bInterfaceClass = USB_CLASS_HID,
175 .bInterfaceSubClass = 0x01, /* boot */
176 .bInterfaceProtocol = 0x01, /* keyboard */
177 .ndesc = 1,
178 .descs = (USBDescOther[]) {
180 /* HID descriptor */
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,
196 .wMaxPacketSize = 8,
197 .bInterval = 0x0a,
202 static const USBDescDevice desc_device_mouse = {
203 .bcdUSB = 0x0100,
204 .bMaxPacketSize0 = 8,
205 .bNumConfigurations = 1,
206 .confs = (USBDescConfig[]) {
208 .bNumInterfaces = 1,
209 .bConfigurationValue = 1,
210 .iConfiguration = STR_CONFIG_MOUSE,
211 .bmAttributes = 0xa0,
212 .bMaxPower = 50,
213 .nif = 1,
214 .ifs = &desc_iface_mouse,
219 static const USBDescDevice desc_device_tablet = {
220 .bcdUSB = 0x0100,
221 .bMaxPacketSize0 = 8,
222 .bNumConfigurations = 1,
223 .confs = (USBDescConfig[]) {
225 .bNumInterfaces = 1,
226 .bConfigurationValue = 1,
227 .iConfiguration = STR_CONFIG_TABLET,
228 .bmAttributes = 0xa0,
229 .bMaxPower = 50,
230 .nif = 1,
231 .ifs = &desc_iface_tablet,
236 static const USBDescDevice desc_device_keyboard = {
237 .bcdUSB = 0x0100,
238 .bMaxPacketSize0 = 8,
239 .bNumConfigurations = 1,
240 .confs = (USBDescConfig[]) {
242 .bNumInterfaces = 1,
243 .bConfigurationValue = 1,
244 .iConfiguration = STR_CONFIG_KEYBOARD,
245 .bmAttributes = 0xa0,
246 .bMaxPower = 50,
247 .nif = 1,
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;
462 /* Windows drivers do not like the 0/0 position and ignore such
463 * events. */
464 if (!(x1 | y1)) {
465 x1 = 1;
468 e->dz += z1;
471 static void usb_pointer_event(void *opaque,
472 int x1, int y1, int z1, int buttons_state)
474 USBHIDState *hs = opaque;
475 USBMouseState *s = &hs->ptr;
476 unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
477 unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
479 /* We combine events where feasible to keep the queue small. We shouldn't
480 * combine anything with the first event of a particular button state, as
481 * that would change the location of the button state change. When the
482 * queue is empty, a second event is needed because we don't know if
483 * the first event changed the button state. */
484 if (hs->n == QUEUE_LENGTH) {
485 /* Queue full. Discard old button state, combine motion normally. */
486 s->queue[use_slot].buttons_state = buttons_state;
487 } else if (hs->n < 2 ||
488 s->queue[use_slot].buttons_state != buttons_state ||
489 s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
490 /* Cannot or should not combine, so add an empty item to the queue. */
491 QUEUE_INCR(use_slot);
492 hs->n++;
493 usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
495 usb_pointer_event_combine(&s->queue[use_slot],
496 hs->kind == USB_MOUSE,
497 x1, y1, z1);
498 usb_hid_changed(hs);
501 static void usb_keyboard_event(void *opaque, int keycode)
503 USBHIDState *hs = opaque;
504 USBKeyboardState *s = &hs->kbd;
505 int slot;
507 if (hs->n == QUEUE_LENGTH) {
508 fprintf(stderr, "usb-kbd: warning: key event queue full\n");
509 return;
511 slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
512 s->keycodes[slot] = keycode;
513 usb_hid_changed(hs);
516 static void usb_keyboard_process_keycode(USBHIDState *hs)
518 USBKeyboardState *s = &hs->kbd;
519 uint8_t hid_code, key;
520 int i, keycode, slot;
522 if (hs->n == 0) {
523 return;
525 slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
526 keycode = s->keycodes[slot];
528 key = keycode & 0x7f;
529 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
530 s->modifiers &= ~(1 << 8);
532 switch (hid_code) {
533 case 0x00:
534 return;
536 case 0xe0:
537 if (s->modifiers & (1 << 9)) {
538 s->modifiers ^= 3 << 8;
539 return;
541 case 0xe1 ... 0xe7:
542 if (keycode & (1 << 7)) {
543 s->modifiers &= ~(1 << (hid_code & 0x0f));
544 return;
546 case 0xe8 ... 0xef:
547 s->modifiers |= 1 << (hid_code & 0x0f);
548 return;
551 if (keycode & (1 << 7)) {
552 for (i = s->keys - 1; i >= 0; i --)
553 if (s->key[i] == hid_code) {
554 s->key[i] = s->key[-- s->keys];
555 s->key[s->keys] = 0x00;
556 break;
558 if (i < 0)
559 return;
560 } else {
561 for (i = s->keys - 1; i >= 0; i --)
562 if (s->key[i] == hid_code)
563 break;
564 if (i < 0) {
565 if (s->keys < sizeof(s->key))
566 s->key[s->keys ++] = hid_code;
567 } else
568 return;
572 static inline int int_clamp(int val, int vmin, int vmax)
574 if (val < vmin)
575 return vmin;
576 else if (val > vmax)
577 return vmax;
578 else
579 return val;
582 static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
584 int dx, dy, dz, b, l;
585 int index;
586 USBMouseState *s = &hs->ptr;
587 USBPointerEvent *e;
589 if (!s->mouse_grabbed) {
590 qemu_activate_mouse_event_handler(s->eh_entry);
591 s->mouse_grabbed = 1;
594 /* When the buffer is empty, return the last event. Relative
595 movements will all be zero. */
596 index = (hs->n ? hs->head : hs->head - 1);
597 e = &s->queue[index & QUEUE_MASK];
599 if (hs->kind == USB_MOUSE) {
600 dx = int_clamp(e->xdx, -127, 127);
601 dy = int_clamp(e->ydy, -127, 127);
602 e->xdx -= dx;
603 e->ydy -= dy;
604 } else {
605 dx = e->xdx;
606 dy = e->ydy;
608 dz = int_clamp(e->dz, -127, 127);
609 e->dz -= dz;
611 b = 0;
612 if (e->buttons_state & MOUSE_EVENT_LBUTTON)
613 b |= 0x01;
614 if (e->buttons_state & MOUSE_EVENT_RBUTTON)
615 b |= 0x02;
616 if (e->buttons_state & MOUSE_EVENT_MBUTTON)
617 b |= 0x04;
619 if (hs->n &&
620 !e->dz &&
621 (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
622 /* that deals with this event */
623 QUEUE_INCR(hs->head);
624 hs->n--;
627 /* Appears we have to invert the wheel direction */
628 dz = 0 - dz;
629 l = 0;
630 switch (hs->kind) {
631 case USB_MOUSE:
632 if (len > l)
633 buf[l++] = b;
634 if (len > l)
635 buf[l++] = dx;
636 if (len > l)
637 buf[l++] = dy;
638 if (len > l)
639 buf[l++] = dz;
640 break;
642 case USB_TABLET:
643 if (len > l)
644 buf[l++] = b;
645 if (len > l)
646 buf[l++] = dx & 0xff;
647 if (len > l)
648 buf[l++] = dx >> 8;
649 if (len > l)
650 buf[l++] = dy & 0xff;
651 if (len > l)
652 buf[l++] = dy >> 8;
653 if (len > l)
654 buf[l++] = dz;
655 break;
657 default:
658 abort();
661 return l;
664 static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
666 USBKeyboardState *s = &hs->kbd;
667 if (len < 2)
668 return 0;
670 usb_keyboard_process_keycode(hs);
672 buf[0] = s->modifiers & 0xff;
673 buf[1] = 0;
674 if (s->keys > 6)
675 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
676 else
677 memcpy(buf + 2, s->key, MIN(8, len) - 2);
679 return MIN(8, len);
682 static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
684 if (len > 0) {
685 int ledstate = 0;
686 /* 0x01: Num Lock LED
687 * 0x02: Caps Lock LED
688 * 0x04: Scroll Lock LED
689 * 0x08: Compose LED
690 * 0x10: Kana LED */
691 s->leds = buf[0];
692 if (s->leds & 0x04)
693 ledstate |= QEMU_SCROLL_LOCK_LED;
694 if (s->leds & 0x01)
695 ledstate |= QEMU_NUM_LOCK_LED;
696 if (s->leds & 0x02)
697 ledstate |= QEMU_CAPS_LOCK_LED;
698 kbd_put_ledstate(ledstate);
700 return 0;
703 static void usb_mouse_handle_reset(USBDevice *dev)
705 USBHIDState *s = (USBHIDState *)dev;
707 memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
708 s->head = 0;
709 s->n = 0;
710 s->protocol = 1;
713 static void usb_keyboard_handle_reset(USBDevice *dev)
715 USBHIDState *s = (USBHIDState *)dev;
717 qemu_add_kbd_event_handler(usb_keyboard_event, s);
718 memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
719 s->head = 0;
720 s->n = 0;
721 memset(s->kbd.key, 0, sizeof (s->kbd.key));
722 s->kbd.keys = 0;
723 s->protocol = 1;
726 static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
728 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
731 static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
732 int request, int value, int index, int length, uint8_t *data)
734 USBHIDState *s = (USBHIDState *)dev;
735 int ret;
737 ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
738 if (ret >= 0) {
739 return ret;
742 ret = 0;
743 switch(request) {
744 case DeviceRequest | USB_REQ_GET_INTERFACE:
745 data[0] = 0;
746 ret = 1;
747 break;
748 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
749 ret = 0;
750 break;
751 /* hid specific requests */
752 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
753 switch(value >> 8) {
754 case 0x22:
755 if (s->kind == USB_MOUSE) {
756 memcpy(data, qemu_mouse_hid_report_descriptor,
757 sizeof(qemu_mouse_hid_report_descriptor));
758 ret = sizeof(qemu_mouse_hid_report_descriptor);
759 } else if (s->kind == USB_TABLET) {
760 memcpy(data, qemu_tablet_hid_report_descriptor,
761 sizeof(qemu_tablet_hid_report_descriptor));
762 ret = sizeof(qemu_tablet_hid_report_descriptor);
763 } else if (s->kind == USB_KEYBOARD) {
764 memcpy(data, qemu_keyboard_hid_report_descriptor,
765 sizeof(qemu_keyboard_hid_report_descriptor));
766 ret = sizeof(qemu_keyboard_hid_report_descriptor);
768 break;
769 default:
770 goto fail;
772 break;
773 case GET_REPORT:
774 if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
775 ret = usb_pointer_poll(s, data, length);
776 } else if (s->kind == USB_KEYBOARD) {
777 ret = usb_keyboard_poll(s, data, length);
779 s->changed = s->n > 0;
780 break;
781 case SET_REPORT:
782 if (s->kind == USB_KEYBOARD)
783 ret = usb_keyboard_write(&s->kbd, data, length);
784 else
785 goto fail;
786 break;
787 case GET_PROTOCOL:
788 if (s->kind != USB_KEYBOARD && s->kind != USB_MOUSE)
789 goto fail;
790 ret = 1;
791 data[0] = s->protocol;
792 break;
793 case SET_PROTOCOL:
794 if (s->kind != USB_KEYBOARD && s->kind != USB_MOUSE)
795 goto fail;
796 ret = 0;
797 s->protocol = value;
798 break;
799 case GET_IDLE:
800 ret = 1;
801 data[0] = s->idle;
802 break;
803 case SET_IDLE:
804 s->idle = (uint8_t) (value >> 8);
805 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
806 ret = 0;
807 break;
808 default:
809 fail:
810 ret = USB_RET_STALL;
811 break;
813 return ret;
816 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
818 USBHIDState *s = (USBHIDState *)dev;
819 int ret = 0;
821 switch(p->pid) {
822 case USB_TOKEN_IN:
823 if (p->devep == 1) {
824 int64_t curtime = qemu_get_clock_ns(vm_clock);
825 if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
826 return USB_RET_NAK;
827 usb_hid_set_next_idle(s, curtime);
828 if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
829 ret = usb_pointer_poll(s, p->data, p->len);
831 else if (s->kind == USB_KEYBOARD) {
832 ret = usb_keyboard_poll(s, p->data, p->len);
834 s->changed = s->n > 0;
835 } else {
836 goto fail;
838 break;
839 case USB_TOKEN_OUT:
840 default:
841 fail:
842 ret = USB_RET_STALL;
843 break;
845 return ret;
848 static void usb_hid_handle_destroy(USBDevice *dev)
850 USBHIDState *s = (USBHIDState *)dev;
852 switch(s->kind) {
853 case USB_KEYBOARD:
854 qemu_remove_kbd_event_handler();
855 break;
856 default:
857 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
861 static int usb_hid_initfn(USBDevice *dev, int kind)
863 USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
865 usb_desc_init(dev);
866 s->kind = kind;
868 if (s->kind == USB_MOUSE) {
869 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
870 0, "QEMU USB Mouse");
871 } else if (s->kind == USB_TABLET) {
872 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
873 1, "QEMU USB Tablet");
876 /* Force poll routine to be run and grab input the first time. */
877 s->changed = 1;
878 return 0;
881 static int usb_tablet_initfn(USBDevice *dev)
883 return usb_hid_initfn(dev, USB_TABLET);
886 static int usb_mouse_initfn(USBDevice *dev)
888 return usb_hid_initfn(dev, USB_MOUSE);
891 static int usb_keyboard_initfn(USBDevice *dev)
893 return usb_hid_initfn(dev, USB_KEYBOARD);
896 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
898 USBHIDState *s = (USBHIDState *)dev;
900 s->datain_opaque = opaque;
901 s->datain = datain;
904 static int usb_hid_post_load(void *opaque, int version_id)
906 USBHIDState *s = opaque;
908 if (s->idle) {
909 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
911 return 0;
914 static const VMStateDescription vmstate_usb_ptr_queue = {
915 .name = "usb-ptr-queue",
916 .version_id = 1,
917 .minimum_version_id = 1,
918 .fields = (VMStateField []) {
919 VMSTATE_INT32(xdx, USBPointerEvent),
920 VMSTATE_INT32(ydy, USBPointerEvent),
921 VMSTATE_INT32(dz, USBPointerEvent),
922 VMSTATE_INT32(buttons_state, USBPointerEvent),
923 VMSTATE_END_OF_LIST()
926 static const VMStateDescription vmstate_usb_ptr = {
927 .name = "usb-ptr",
928 .version_id = 1,
929 .minimum_version_id = 1,
930 .post_load = usb_hid_post_load,
931 .fields = (VMStateField []) {
932 VMSTATE_USB_DEVICE(dev, USBHIDState),
933 VMSTATE_STRUCT_ARRAY(ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
934 vmstate_usb_ptr_queue, USBPointerEvent),
935 VMSTATE_UINT32(head, USBHIDState),
936 VMSTATE_UINT32(n, USBHIDState),
937 VMSTATE_INT32(protocol, USBHIDState),
938 VMSTATE_UINT8(idle, USBHIDState),
939 VMSTATE_END_OF_LIST()
943 static const VMStateDescription vmstate_usb_kbd = {
944 .name = "usb-kbd",
945 .version_id = 1,
946 .minimum_version_id = 1,
947 .post_load = usb_hid_post_load,
948 .fields = (VMStateField []) {
949 VMSTATE_USB_DEVICE(dev, USBHIDState),
950 VMSTATE_UINT32_ARRAY(kbd.keycodes, USBHIDState, QUEUE_LENGTH),
951 VMSTATE_UINT32(head, USBHIDState),
952 VMSTATE_UINT32(n, USBHIDState),
953 VMSTATE_UINT16(kbd.modifiers, USBHIDState),
954 VMSTATE_UINT8(kbd.leds, USBHIDState),
955 VMSTATE_UINT8_ARRAY(kbd.key, USBHIDState, 16),
956 VMSTATE_INT32(kbd.keys, USBHIDState),
957 VMSTATE_INT32(protocol, USBHIDState),
958 VMSTATE_UINT8(idle, USBHIDState),
959 VMSTATE_END_OF_LIST()
963 static struct USBDeviceInfo hid_info[] = {
965 .product_desc = "QEMU USB Tablet",
966 .qdev.name = "usb-tablet",
967 .usbdevice_name = "tablet",
968 .qdev.size = sizeof(USBHIDState),
969 .qdev.vmsd = &vmstate_usb_ptr,
970 .usb_desc = &desc_tablet,
971 .init = usb_tablet_initfn,
972 .handle_packet = usb_generic_handle_packet,
973 .handle_reset = usb_mouse_handle_reset,
974 .handle_control = usb_hid_handle_control,
975 .handle_data = usb_hid_handle_data,
976 .handle_destroy = usb_hid_handle_destroy,
978 .product_desc = "QEMU USB Mouse",
979 .qdev.name = "usb-mouse",
980 .usbdevice_name = "mouse",
981 .qdev.size = sizeof(USBHIDState),
982 .qdev.vmsd = &vmstate_usb_ptr,
983 .usb_desc = &desc_mouse,
984 .init = usb_mouse_initfn,
985 .handle_packet = usb_generic_handle_packet,
986 .handle_reset = usb_mouse_handle_reset,
987 .handle_control = usb_hid_handle_control,
988 .handle_data = usb_hid_handle_data,
989 .handle_destroy = usb_hid_handle_destroy,
991 .product_desc = "QEMU USB Keyboard",
992 .qdev.name = "usb-kbd",
993 .usbdevice_name = "keyboard",
994 .qdev.size = sizeof(USBHIDState),
995 .qdev.vmsd = &vmstate_usb_kbd,
996 .usb_desc = &desc_keyboard,
997 .init = usb_keyboard_initfn,
998 .handle_packet = usb_generic_handle_packet,
999 .handle_reset = usb_keyboard_handle_reset,
1000 .handle_control = usb_hid_handle_control,
1001 .handle_data = usb_hid_handle_data,
1002 .handle_destroy = usb_hid_handle_destroy,
1004 /* end of list */
1008 static void usb_hid_register_devices(void)
1010 usb_qdev_register_many(hid_info);
1012 device_init(usb_hid_register_devices)