Merge remote-tracking branch 'stefanha/trivial-patches' into staging
[qemu/wangdongxu.git] / hw / usb-hid.c
blob53b261c3b95069474f19644b1c374c52c8f2d1c4
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 .bInterfaceSubClass = 0x01, /* boot */
146 .bInterfaceProtocol = 0x02,
147 .ndesc = 1,
148 .descs = (USBDescOther[]) {
150 /* HID descriptor */
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 */
158 74, 0, /* u16 len */
162 .eps = (USBDescEndpoint[]) {
164 .bEndpointAddress = USB_DIR_IN | 0x01,
165 .bmAttributes = USB_ENDPOINT_XFER_INT,
166 .wMaxPacketSize = 8,
167 .bInterval = 0x0a,
172 static const USBDescIface desc_iface_keyboard = {
173 .bInterfaceNumber = 0,
174 .bNumEndpoints = 1,
175 .bInterfaceClass = USB_CLASS_HID,
176 .bInterfaceSubClass = 0x01, /* boot */
177 .bInterfaceProtocol = 0x01, /* keyboard */
178 .ndesc = 1,
179 .descs = (USBDescOther[]) {
181 /* HID descriptor */
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,
197 .wMaxPacketSize = 8,
198 .bInterval = 0x0a,
203 static const USBDescDevice desc_device_mouse = {
204 .bcdUSB = 0x0100,
205 .bMaxPacketSize0 = 8,
206 .bNumConfigurations = 1,
207 .confs = (USBDescConfig[]) {
209 .bNumInterfaces = 1,
210 .bConfigurationValue = 1,
211 .iConfiguration = STR_CONFIG_MOUSE,
212 .bmAttributes = 0xa0,
213 .bMaxPower = 50,
214 .nif = 1,
215 .ifs = &desc_iface_mouse,
220 static const USBDescDevice desc_device_tablet = {
221 .bcdUSB = 0x0100,
222 .bMaxPacketSize0 = 8,
223 .bNumConfigurations = 1,
224 .confs = (USBDescConfig[]) {
226 .bNumInterfaces = 1,
227 .bConfigurationValue = 1,
228 .iConfiguration = STR_CONFIG_TABLET,
229 .bmAttributes = 0xa0,
230 .bMaxPower = 50,
231 .nif = 1,
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 .nif = 1,
249 .ifs = &desc_iface_keyboard,
254 static const USBDesc desc_mouse = {
255 .id = {
256 .idVendor = 0x0627,
257 .idProduct = 0x0001,
258 .bcdDevice = 0,
259 .iManufacturer = STR_MANUFACTURER,
260 .iProduct = STR_PRODUCT_MOUSE,
261 .iSerialNumber = STR_SERIALNUMBER,
263 .full = &desc_device_mouse,
264 .str = desc_strings,
267 static const USBDesc desc_tablet = {
268 .id = {
269 .idVendor = 0x0627,
270 .idProduct = 0x0001,
271 .bcdDevice = 0,
272 .iManufacturer = STR_MANUFACTURER,
273 .iProduct = STR_PRODUCT_TABLET,
274 .iSerialNumber = STR_SERIALNUMBER,
276 .full = &desc_device_tablet,
277 .str = desc_strings,
280 static const USBDesc desc_keyboard = {
281 .id = {
282 .idVendor = 0x0627,
283 .idProduct = 0x0001,
284 .bcdDevice = 0,
285 .iManufacturer = STR_MANUFACTURER,
286 .iProduct = STR_PRODUCT_KEYBOARD,
287 .iSerialNumber = STR_SERIALNUMBER,
289 .full = &desc_device_keyboard,
290 .str = desc_strings,
293 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
294 0x05, 0x01, /* Usage Page (Generic Desktop) */
295 0x09, 0x02, /* Usage (Mouse) */
296 0xa1, 0x01, /* Collection (Application) */
297 0x09, 0x01, /* Usage (Pointer) */
298 0xa1, 0x00, /* Collection (Physical) */
299 0x05, 0x09, /* Usage Page (Button) */
300 0x19, 0x01, /* Usage Minimum (1) */
301 0x29, 0x03, /* Usage Maximum (3) */
302 0x15, 0x00, /* Logical Minimum (0) */
303 0x25, 0x01, /* Logical Maximum (1) */
304 0x95, 0x03, /* Report Count (3) */
305 0x75, 0x01, /* Report Size (1) */
306 0x81, 0x02, /* Input (Data, Variable, Absolute) */
307 0x95, 0x01, /* Report Count (1) */
308 0x75, 0x05, /* Report Size (5) */
309 0x81, 0x01, /* Input (Constant) */
310 0x05, 0x01, /* Usage Page (Generic Desktop) */
311 0x09, 0x30, /* Usage (X) */
312 0x09, 0x31, /* Usage (Y) */
313 0x09, 0x38, /* Usage (Wheel) */
314 0x15, 0x81, /* Logical Minimum (-0x7f) */
315 0x25, 0x7f, /* Logical Maximum (0x7f) */
316 0x75, 0x08, /* Report Size (8) */
317 0x95, 0x03, /* Report Count (3) */
318 0x81, 0x06, /* Input (Data, Variable, Relative) */
319 0xc0, /* End Collection */
320 0xc0, /* End Collection */
323 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
324 0x05, 0x01, /* Usage Page (Generic Desktop) */
325 0x09, 0x01, /* Usage (Pointer) */
326 0xa1, 0x01, /* Collection (Application) */
327 0x09, 0x01, /* Usage (Pointer) */
328 0xa1, 0x00, /* Collection (Physical) */
329 0x05, 0x09, /* Usage Page (Button) */
330 0x19, 0x01, /* Usage Minimum (1) */
331 0x29, 0x03, /* Usage Maximum (3) */
332 0x15, 0x00, /* Logical Minimum (0) */
333 0x25, 0x01, /* Logical Maximum (1) */
334 0x95, 0x03, /* Report Count (3) */
335 0x75, 0x01, /* Report Size (1) */
336 0x81, 0x02, /* Input (Data, Variable, Absolute) */
337 0x95, 0x01, /* Report Count (1) */
338 0x75, 0x05, /* Report Size (5) */
339 0x81, 0x01, /* Input (Constant) */
340 0x05, 0x01, /* Usage Page (Generic Desktop) */
341 0x09, 0x30, /* Usage (X) */
342 0x09, 0x31, /* Usage (Y) */
343 0x15, 0x00, /* Logical Minimum (0) */
344 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
345 0x35, 0x00, /* Physical Minimum (0) */
346 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
347 0x75, 0x10, /* Report Size (16) */
348 0x95, 0x02, /* Report Count (2) */
349 0x81, 0x02, /* Input (Data, Variable, Absolute) */
350 0x05, 0x01, /* Usage Page (Generic Desktop) */
351 0x09, 0x38, /* Usage (Wheel) */
352 0x15, 0x81, /* Logical Minimum (-0x7f) */
353 0x25, 0x7f, /* Logical Maximum (0x7f) */
354 0x35, 0x00, /* Physical Minimum (same as logical) */
355 0x45, 0x00, /* Physical Maximum (same as logical) */
356 0x75, 0x08, /* Report Size (8) */
357 0x95, 0x01, /* Report Count (1) */
358 0x81, 0x06, /* Input (Data, Variable, Relative) */
359 0xc0, /* End Collection */
360 0xc0, /* End Collection */
363 static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
364 0x05, 0x01, /* Usage Page (Generic Desktop) */
365 0x09, 0x06, /* Usage (Keyboard) */
366 0xa1, 0x01, /* Collection (Application) */
367 0x75, 0x01, /* Report Size (1) */
368 0x95, 0x08, /* Report Count (8) */
369 0x05, 0x07, /* Usage Page (Key Codes) */
370 0x19, 0xe0, /* Usage Minimum (224) */
371 0x29, 0xe7, /* Usage Maximum (231) */
372 0x15, 0x00, /* Logical Minimum (0) */
373 0x25, 0x01, /* Logical Maximum (1) */
374 0x81, 0x02, /* Input (Data, Variable, Absolute) */
375 0x95, 0x01, /* Report Count (1) */
376 0x75, 0x08, /* Report Size (8) */
377 0x81, 0x01, /* Input (Constant) */
378 0x95, 0x05, /* Report Count (5) */
379 0x75, 0x01, /* Report Size (1) */
380 0x05, 0x08, /* Usage Page (LEDs) */
381 0x19, 0x01, /* Usage Minimum (1) */
382 0x29, 0x05, /* Usage Maximum (5) */
383 0x91, 0x02, /* Output (Data, Variable, Absolute) */
384 0x95, 0x01, /* Report Count (1) */
385 0x75, 0x03, /* Report Size (3) */
386 0x91, 0x01, /* Output (Constant) */
387 0x95, 0x06, /* Report Count (6) */
388 0x75, 0x08, /* Report Size (8) */
389 0x15, 0x00, /* Logical Minimum (0) */
390 0x25, 0xff, /* Logical Maximum (255) */
391 0x05, 0x07, /* Usage Page (Key Codes) */
392 0x19, 0x00, /* Usage Minimum (0) */
393 0x29, 0xff, /* Usage Maximum (255) */
394 0x81, 0x00, /* Input (Data, Array) */
395 0xc0, /* End Collection */
398 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
399 #define USB_HID_USAGE_POSTFAIL 0x02
400 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
402 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
403 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
404 static const uint8_t usb_hid_usage_keys[0x100] = {
405 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
406 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
407 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
408 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
409 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
410 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
411 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
412 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
413 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
414 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
415 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
416 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
417 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
418 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x58, 0xe4, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
429 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
431 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
432 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
433 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 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,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 static void usb_hid_changed(USBHIDState *hs)
442 hs->changed = 1;
444 if (hs->datain)
445 hs->datain(hs->datain_opaque);
447 usb_wakeup(&hs->dev);
450 static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
451 e->xdx = e->ydy = e->dz = 0;
452 e->buttons_state = buttons;
455 static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,
456 int x1, int y1, int z1) {
457 if (xyrel) {
458 e->xdx += x1;
459 e->ydy += y1;
460 } else {
461 e->xdx = x1;
462 e->ydy = y1;
464 e->dz += z1;
467 static void usb_pointer_event(void *opaque,
468 int x1, int y1, int z1, int buttons_state)
470 USBHIDState *hs = opaque;
471 USBMouseState *s = &hs->ptr;
472 unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
473 unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
475 /* We combine events where feasible to keep the queue small. We shouldn't
476 * combine anything with the first event of a particular button state, as
477 * that would change the location of the button state change. When the
478 * queue is empty, a second event is needed because we don't know if
479 * the first event changed the button state. */
480 if (hs->n == QUEUE_LENGTH) {
481 /* Queue full. Discard old button state, combine motion normally. */
482 s->queue[use_slot].buttons_state = buttons_state;
483 } else if (hs->n < 2 ||
484 s->queue[use_slot].buttons_state != buttons_state ||
485 s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
486 /* Cannot or should not combine, so add an empty item to the queue. */
487 QUEUE_INCR(use_slot);
488 hs->n++;
489 usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
491 usb_pointer_event_combine(&s->queue[use_slot],
492 hs->kind == USB_MOUSE,
493 x1, y1, z1);
494 usb_hid_changed(hs);
497 static void usb_keyboard_event(void *opaque, int keycode)
499 USBHIDState *hs = opaque;
500 USBKeyboardState *s = &hs->kbd;
501 int slot;
503 if (hs->n == QUEUE_LENGTH) {
504 fprintf(stderr, "usb-kbd: warning: key event queue full\n");
505 return;
507 slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
508 s->keycodes[slot] = keycode;
509 usb_hid_changed(hs);
512 static void usb_keyboard_process_keycode(USBHIDState *hs)
514 USBKeyboardState *s = &hs->kbd;
515 uint8_t hid_code, key;
516 int i, keycode, slot;
518 if (hs->n == 0) {
519 return;
521 slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
522 keycode = s->keycodes[slot];
524 key = keycode & 0x7f;
525 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
526 s->modifiers &= ~(1 << 8);
528 switch (hid_code) {
529 case 0x00:
530 return;
532 case 0xe0:
533 if (s->modifiers & (1 << 9)) {
534 s->modifiers ^= 3 << 8;
535 usb_hid_changed(hs);
536 return;
538 case 0xe1 ... 0xe7:
539 if (keycode & (1 << 7)) {
540 s->modifiers &= ~(1 << (hid_code & 0x0f));
541 usb_hid_changed(hs);
542 return;
544 case 0xe8 ... 0xef:
545 s->modifiers |= 1 << (hid_code & 0x0f);
546 usb_hid_changed(hs);
547 return;
550 if (keycode & (1 << 7)) {
551 for (i = s->keys - 1; i >= 0; i --)
552 if (s->key[i] == hid_code) {
553 s->key[i] = s->key[-- s->keys];
554 s->key[s->keys] = 0x00;
555 break;
557 if (i < 0)
558 return;
559 } else {
560 for (i = s->keys - 1; i >= 0; i --)
561 if (s->key[i] == hid_code)
562 break;
563 if (i < 0) {
564 if (s->keys < sizeof(s->key))
565 s->key[s->keys ++] = hid_code;
566 } else
567 return;
571 static inline int int_clamp(int val, int vmin, int vmax)
573 if (val < vmin)
574 return vmin;
575 else if (val > vmax)
576 return vmax;
577 else
578 return val;
581 static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
583 int dx, dy, dz, b, l;
584 int index;
585 USBMouseState *s = &hs->ptr;
586 USBPointerEvent *e;
588 if (!s->mouse_grabbed) {
589 qemu_activate_mouse_event_handler(s->eh_entry);
590 s->mouse_grabbed = 1;
593 /* When the buffer is empty, return the last event. Relative
594 movements will all be zero. */
595 index = (hs->n ? hs->head : hs->head - 1);
596 e = &s->queue[index & QUEUE_MASK];
598 if (hs->kind == USB_MOUSE) {
599 dx = int_clamp(e->xdx, -127, 127);
600 dy = int_clamp(e->ydy, -127, 127);
601 e->xdx -= dx;
602 e->ydy -= dy;
603 } else {
604 dx = e->xdx;
605 dy = e->ydy;
607 dz = int_clamp(e->dz, -127, 127);
608 e->dz -= dz;
610 b = 0;
611 if (e->buttons_state & MOUSE_EVENT_LBUTTON)
612 b |= 0x01;
613 if (e->buttons_state & MOUSE_EVENT_RBUTTON)
614 b |= 0x02;
615 if (e->buttons_state & MOUSE_EVENT_MBUTTON)
616 b |= 0x04;
618 if (hs->n &&
619 !e->dz &&
620 (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
621 /* that deals with this event */
622 QUEUE_INCR(hs->head);
623 hs->n--;
626 /* Appears we have to invert the wheel direction */
627 dz = 0 - dz;
628 l = 0;
629 switch (hs->kind) {
630 case USB_MOUSE:
631 if (len > l)
632 buf[l++] = b;
633 if (len > l)
634 buf[l++] = dx;
635 if (len > l)
636 buf[l++] = dy;
637 if (len > l)
638 buf[l++] = dz;
639 break;
641 case USB_TABLET:
642 if (len > l)
643 buf[l++] = b;
644 if (len > l)
645 buf[l++] = dx & 0xff;
646 if (len > l)
647 buf[l++] = dx >> 8;
648 if (len > l)
649 buf[l++] = dy & 0xff;
650 if (len > l)
651 buf[l++] = dy >> 8;
652 if (len > l)
653 buf[l++] = dz;
654 break;
656 default:
657 abort();
660 return l;
663 static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
665 USBKeyboardState *s = &hs->kbd;
666 if (len < 2)
667 return 0;
669 usb_keyboard_process_keycode(hs);
671 buf[0] = s->modifiers & 0xff;
672 buf[1] = 0;
673 if (s->keys > 6)
674 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
675 else
676 memcpy(buf + 2, s->key, MIN(8, len) - 2);
678 return MIN(8, len);
681 static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
683 if (len > 0) {
684 int ledstate = 0;
685 /* 0x01: Num Lock LED
686 * 0x02: Caps Lock LED
687 * 0x04: Scroll Lock LED
688 * 0x08: Compose LED
689 * 0x10: Kana LED */
690 s->leds = buf[0];
691 if (s->leds & 0x04)
692 ledstate |= QEMU_SCROLL_LOCK_LED;
693 if (s->leds & 0x01)
694 ledstate |= QEMU_NUM_LOCK_LED;
695 if (s->leds & 0x02)
696 ledstate |= QEMU_CAPS_LOCK_LED;
697 kbd_put_ledstate(ledstate);
699 return 0;
702 static void usb_mouse_handle_reset(USBDevice *dev)
704 USBHIDState *s = (USBHIDState *)dev;
706 memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
707 s->head = 0;
708 s->n = 0;
709 s->protocol = 1;
712 static void usb_keyboard_handle_reset(USBDevice *dev)
714 USBHIDState *s = (USBHIDState *)dev;
716 qemu_add_kbd_event_handler(usb_keyboard_event, s);
717 memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
718 s->head = 0;
719 s->n = 0;
720 memset(s->kbd.key, 0, sizeof (s->kbd.key));
721 s->kbd.keys = 0;
722 s->protocol = 1;
725 static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
727 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
730 static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
731 int request, int value, int index, int length, uint8_t *data)
733 USBHIDState *s = (USBHIDState *)dev;
734 int ret;
736 ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
737 if (ret >= 0) {
738 return ret;
741 ret = 0;
742 switch(request) {
743 case DeviceRequest | USB_REQ_GET_INTERFACE:
744 data[0] = 0;
745 ret = 1;
746 break;
747 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
748 ret = 0;
749 break;
750 /* hid specific requests */
751 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
752 switch(value >> 8) {
753 case 0x22:
754 if (s->kind == USB_MOUSE) {
755 memcpy(data, qemu_mouse_hid_report_descriptor,
756 sizeof(qemu_mouse_hid_report_descriptor));
757 ret = sizeof(qemu_mouse_hid_report_descriptor);
758 } else if (s->kind == USB_TABLET) {
759 memcpy(data, qemu_tablet_hid_report_descriptor,
760 sizeof(qemu_tablet_hid_report_descriptor));
761 ret = sizeof(qemu_tablet_hid_report_descriptor);
762 } else if (s->kind == USB_KEYBOARD) {
763 memcpy(data, qemu_keyboard_hid_report_descriptor,
764 sizeof(qemu_keyboard_hid_report_descriptor));
765 ret = sizeof(qemu_keyboard_hid_report_descriptor);
767 break;
768 default:
769 goto fail;
771 break;
772 case GET_REPORT:
773 if (s->kind == USB_MOUSE || s->kind == USB_TABLET)
774 ret = usb_pointer_poll(s, data, length);
775 else if (s->kind == USB_KEYBOARD)
776 ret = usb_keyboard_poll(s, data, length);
777 break;
778 case SET_REPORT:
779 if (s->kind == USB_KEYBOARD)
780 ret = usb_keyboard_write(&s->kbd, data, length);
781 else
782 goto fail;
783 break;
784 case GET_PROTOCOL:
785 if (s->kind != USB_KEYBOARD)
786 goto fail;
787 ret = 1;
788 data[0] = s->protocol;
789 break;
790 case SET_PROTOCOL:
791 if (s->kind != USB_KEYBOARD)
792 goto fail;
793 ret = 0;
794 s->protocol = value;
795 break;
796 case GET_IDLE:
797 ret = 1;
798 data[0] = s->idle;
799 break;
800 case SET_IDLE:
801 s->idle = (uint8_t) (value >> 8);
802 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
803 ret = 0;
804 break;
805 default:
806 fail:
807 ret = USB_RET_STALL;
808 break;
810 return ret;
813 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
815 USBHIDState *s = (USBHIDState *)dev;
816 int ret = 0;
818 switch(p->pid) {
819 case USB_TOKEN_IN:
820 if (p->devep == 1) {
821 int64_t curtime = qemu_get_clock_ns(vm_clock);
822 if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
823 return USB_RET_NAK;
824 usb_hid_set_next_idle(s, curtime);
825 if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
826 ret = usb_pointer_poll(s, p->data, p->len);
828 else if (s->kind == USB_KEYBOARD) {
829 ret = usb_keyboard_poll(s, p->data, p->len);
831 s->changed = s->n > 0;
832 } else {
833 goto fail;
835 break;
836 case USB_TOKEN_OUT:
837 default:
838 fail:
839 ret = USB_RET_STALL;
840 break;
842 return ret;
845 static void usb_hid_handle_destroy(USBDevice *dev)
847 USBHIDState *s = (USBHIDState *)dev;
849 switch(s->kind) {
850 case USB_KEYBOARD:
851 qemu_remove_kbd_event_handler();
852 break;
853 default:
854 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
858 static int usb_hid_initfn(USBDevice *dev, int kind)
860 USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
862 usb_desc_init(dev);
863 s->kind = kind;
865 if (s->kind == USB_MOUSE) {
866 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
867 0, "QEMU USB Mouse");
868 } else if (s->kind == USB_TABLET) {
869 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
870 1, "QEMU USB Tablet");
873 /* Force poll routine to be run and grab input the first time. */
874 s->changed = 1;
875 return 0;
878 static int usb_tablet_initfn(USBDevice *dev)
880 return usb_hid_initfn(dev, USB_TABLET);
883 static int usb_mouse_initfn(USBDevice *dev)
885 return usb_hid_initfn(dev, USB_MOUSE);
888 static int usb_keyboard_initfn(USBDevice *dev)
890 return usb_hid_initfn(dev, USB_KEYBOARD);
893 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
895 USBHIDState *s = (USBHIDState *)dev;
897 s->datain_opaque = opaque;
898 s->datain = datain;
901 static int usb_hid_post_load(void *opaque, int version_id)
903 USBHIDState *s = opaque;
905 if (s->idle) {
906 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
908 return 0;
911 static const VMStateDescription vmstate_usb_ptr_queue = {
912 .name = "usb-ptr-queue",
913 .version_id = 1,
914 .minimum_version_id = 1,
915 .fields = (VMStateField []) {
916 VMSTATE_INT32(xdx, USBPointerEvent),
917 VMSTATE_INT32(ydy, USBPointerEvent),
918 VMSTATE_INT32(dz, USBPointerEvent),
919 VMSTATE_INT32(buttons_state, USBPointerEvent),
920 VMSTATE_END_OF_LIST()
923 static const VMStateDescription vmstate_usb_ptr = {
924 .name = "usb-ptr",
925 .version_id = 1,
926 .minimum_version_id = 1,
927 .post_load = usb_hid_post_load,
928 .fields = (VMStateField []) {
929 VMSTATE_USB_DEVICE(dev, USBHIDState),
930 VMSTATE_STRUCT_ARRAY(ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
931 vmstate_usb_ptr_queue, USBPointerEvent),
932 VMSTATE_UINT32(head, USBHIDState),
933 VMSTATE_UINT32(n, USBHIDState),
934 VMSTATE_INT32(protocol, USBHIDState),
935 VMSTATE_UINT8(idle, USBHIDState),
936 VMSTATE_END_OF_LIST()
940 static const VMStateDescription vmstate_usb_kbd = {
941 .name = "usb-kbd",
942 .version_id = 1,
943 .minimum_version_id = 1,
944 .post_load = usb_hid_post_load,
945 .fields = (VMStateField []) {
946 VMSTATE_USB_DEVICE(dev, USBHIDState),
947 VMSTATE_UINT32_ARRAY(kbd.keycodes, USBHIDState, QUEUE_LENGTH),
948 VMSTATE_UINT32(head, USBHIDState),
949 VMSTATE_UINT32(n, USBHIDState),
950 VMSTATE_UINT16(kbd.modifiers, USBHIDState),
951 VMSTATE_UINT8(kbd.leds, USBHIDState),
952 VMSTATE_UINT8_ARRAY(kbd.key, USBHIDState, 16),
953 VMSTATE_INT32(kbd.keys, USBHIDState),
954 VMSTATE_INT32(protocol, USBHIDState),
955 VMSTATE_UINT8(idle, USBHIDState),
956 VMSTATE_END_OF_LIST()
960 static struct USBDeviceInfo hid_info[] = {
962 .product_desc = "QEMU USB Tablet",
963 .qdev.name = "usb-tablet",
964 .usbdevice_name = "tablet",
965 .qdev.size = sizeof(USBHIDState),
966 .qdev.vmsd = &vmstate_usb_ptr,
967 .usb_desc = &desc_tablet,
968 .init = usb_tablet_initfn,
969 .handle_packet = usb_generic_handle_packet,
970 .handle_reset = usb_mouse_handle_reset,
971 .handle_control = usb_hid_handle_control,
972 .handle_data = usb_hid_handle_data,
973 .handle_destroy = usb_hid_handle_destroy,
975 .product_desc = "QEMU USB Mouse",
976 .qdev.name = "usb-mouse",
977 .usbdevice_name = "mouse",
978 .qdev.size = sizeof(USBHIDState),
979 .qdev.vmsd = &vmstate_usb_ptr,
980 .usb_desc = &desc_mouse,
981 .init = usb_mouse_initfn,
982 .handle_packet = usb_generic_handle_packet,
983 .handle_reset = usb_mouse_handle_reset,
984 .handle_control = usb_hid_handle_control,
985 .handle_data = usb_hid_handle_data,
986 .handle_destroy = usb_hid_handle_destroy,
988 .product_desc = "QEMU USB Keyboard",
989 .qdev.name = "usb-kbd",
990 .usbdevice_name = "keyboard",
991 .qdev.size = sizeof(USBHIDState),
992 .qdev.vmsd = &vmstate_usb_kbd,
993 .usb_desc = &desc_keyboard,
994 .init = usb_keyboard_initfn,
995 .handle_packet = usb_generic_handle_packet,
996 .handle_reset = usb_keyboard_handle_reset,
997 .handle_control = usb_hid_handle_control,
998 .handle_data = usb_hid_handle_data,
999 .handle_destroy = usb_hid_handle_destroy,
1001 /* end of list */
1005 static void usb_hid_register_devices(void)
1007 usb_qdev_register_many(hid_info);
1009 device_init(usb_hid_register_devices)