softfloat: use GCC builtins to count the leading zeros
[qemu.git] / hw / usb-hid.c
blob89c293c466aba43fdc29d510db012899a27176dc
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 .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 .ifs = &desc_iface_tablet,
235 static const USBDescDevice desc_device_keyboard = {
236 .bcdUSB = 0x0100,
237 .bMaxPacketSize0 = 8,
238 .bNumConfigurations = 1,
239 .confs = (USBDescConfig[]) {
241 .bNumInterfaces = 1,
242 .bConfigurationValue = 1,
243 .iConfiguration = STR_CONFIG_KEYBOARD,
244 .bmAttributes = 0xa0,
245 .bMaxPower = 50,
246 .ifs = &desc_iface_keyboard,
251 static const USBDesc desc_mouse = {
252 .id = {
253 .idVendor = 0x0627,
254 .idProduct = 0x0001,
255 .bcdDevice = 0,
256 .iManufacturer = STR_MANUFACTURER,
257 .iProduct = STR_PRODUCT_MOUSE,
258 .iSerialNumber = STR_SERIALNUMBER,
260 .full = &desc_device_mouse,
261 .str = desc_strings,
264 static const USBDesc desc_tablet = {
265 .id = {
266 .idVendor = 0x0627,
267 .idProduct = 0x0001,
268 .bcdDevice = 0,
269 .iManufacturer = STR_MANUFACTURER,
270 .iProduct = STR_PRODUCT_TABLET,
271 .iSerialNumber = STR_SERIALNUMBER,
273 .full = &desc_device_tablet,
274 .str = desc_strings,
277 static const USBDesc desc_keyboard = {
278 .id = {
279 .idVendor = 0x0627,
280 .idProduct = 0x0001,
281 .bcdDevice = 0,
282 .iManufacturer = STR_MANUFACTURER,
283 .iProduct = STR_PRODUCT_KEYBOARD,
284 .iSerialNumber = STR_SERIALNUMBER,
286 .full = &desc_device_keyboard,
287 .str = desc_strings,
290 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
291 0x05, 0x01, /* Usage Page (Generic Desktop) */
292 0x09, 0x02, /* Usage (Mouse) */
293 0xa1, 0x01, /* Collection (Application) */
294 0x09, 0x01, /* Usage (Pointer) */
295 0xa1, 0x00, /* Collection (Physical) */
296 0x05, 0x09, /* Usage Page (Button) */
297 0x19, 0x01, /* Usage Minimum (1) */
298 0x29, 0x03, /* Usage Maximum (3) */
299 0x15, 0x00, /* Logical Minimum (0) */
300 0x25, 0x01, /* Logical Maximum (1) */
301 0x95, 0x03, /* Report Count (3) */
302 0x75, 0x01, /* Report Size (1) */
303 0x81, 0x02, /* Input (Data, Variable, Absolute) */
304 0x95, 0x01, /* Report Count (1) */
305 0x75, 0x05, /* Report Size (5) */
306 0x81, 0x01, /* Input (Constant) */
307 0x05, 0x01, /* Usage Page (Generic Desktop) */
308 0x09, 0x30, /* Usage (X) */
309 0x09, 0x31, /* Usage (Y) */
310 0x09, 0x38, /* Usage (Wheel) */
311 0x15, 0x81, /* Logical Minimum (-0x7f) */
312 0x25, 0x7f, /* Logical Maximum (0x7f) */
313 0x75, 0x08, /* Report Size (8) */
314 0x95, 0x03, /* Report Count (3) */
315 0x81, 0x06, /* Input (Data, Variable, Relative) */
316 0xc0, /* End Collection */
317 0xc0, /* End Collection */
320 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
321 0x05, 0x01, /* Usage Page (Generic Desktop) */
322 0x09, 0x01, /* Usage (Pointer) */
323 0xa1, 0x01, /* Collection (Application) */
324 0x09, 0x01, /* Usage (Pointer) */
325 0xa1, 0x00, /* Collection (Physical) */
326 0x05, 0x09, /* Usage Page (Button) */
327 0x19, 0x01, /* Usage Minimum (1) */
328 0x29, 0x03, /* Usage Maximum (3) */
329 0x15, 0x00, /* Logical Minimum (0) */
330 0x25, 0x01, /* Logical Maximum (1) */
331 0x95, 0x03, /* Report Count (3) */
332 0x75, 0x01, /* Report Size (1) */
333 0x81, 0x02, /* Input (Data, Variable, Absolute) */
334 0x95, 0x01, /* Report Count (1) */
335 0x75, 0x05, /* Report Size (5) */
336 0x81, 0x01, /* Input (Constant) */
337 0x05, 0x01, /* Usage Page (Generic Desktop) */
338 0x09, 0x30, /* Usage (X) */
339 0x09, 0x31, /* Usage (Y) */
340 0x15, 0x00, /* Logical Minimum (0) */
341 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
342 0x35, 0x00, /* Physical Minimum (0) */
343 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
344 0x75, 0x10, /* Report Size (16) */
345 0x95, 0x02, /* Report Count (2) */
346 0x81, 0x02, /* Input (Data, Variable, Absolute) */
347 0x05, 0x01, /* Usage Page (Generic Desktop) */
348 0x09, 0x38, /* Usage (Wheel) */
349 0x15, 0x81, /* Logical Minimum (-0x7f) */
350 0x25, 0x7f, /* Logical Maximum (0x7f) */
351 0x35, 0x00, /* Physical Minimum (same as logical) */
352 0x45, 0x00, /* Physical Maximum (same as logical) */
353 0x75, 0x08, /* Report Size (8) */
354 0x95, 0x01, /* Report Count (1) */
355 0x81, 0x06, /* Input (Data, Variable, Relative) */
356 0xc0, /* End Collection */
357 0xc0, /* End Collection */
360 static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
361 0x05, 0x01, /* Usage Page (Generic Desktop) */
362 0x09, 0x06, /* Usage (Keyboard) */
363 0xa1, 0x01, /* Collection (Application) */
364 0x75, 0x01, /* Report Size (1) */
365 0x95, 0x08, /* Report Count (8) */
366 0x05, 0x07, /* Usage Page (Key Codes) */
367 0x19, 0xe0, /* Usage Minimum (224) */
368 0x29, 0xe7, /* Usage Maximum (231) */
369 0x15, 0x00, /* Logical Minimum (0) */
370 0x25, 0x01, /* Logical Maximum (1) */
371 0x81, 0x02, /* Input (Data, Variable, Absolute) */
372 0x95, 0x01, /* Report Count (1) */
373 0x75, 0x08, /* Report Size (8) */
374 0x81, 0x01, /* Input (Constant) */
375 0x95, 0x05, /* Report Count (5) */
376 0x75, 0x01, /* Report Size (1) */
377 0x05, 0x08, /* Usage Page (LEDs) */
378 0x19, 0x01, /* Usage Minimum (1) */
379 0x29, 0x05, /* Usage Maximum (5) */
380 0x91, 0x02, /* Output (Data, Variable, Absolute) */
381 0x95, 0x01, /* Report Count (1) */
382 0x75, 0x03, /* Report Size (3) */
383 0x91, 0x01, /* Output (Constant) */
384 0x95, 0x06, /* Report Count (6) */
385 0x75, 0x08, /* Report Size (8) */
386 0x15, 0x00, /* Logical Minimum (0) */
387 0x25, 0xff, /* Logical Maximum (255) */
388 0x05, 0x07, /* Usage Page (Key Codes) */
389 0x19, 0x00, /* Usage Minimum (0) */
390 0x29, 0xff, /* Usage Maximum (255) */
391 0x81, 0x00, /* Input (Data, Array) */
392 0xc0, /* End Collection */
395 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
396 #define USB_HID_USAGE_POSTFAIL 0x02
397 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
399 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
400 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
401 static const uint8_t usb_hid_usage_keys[0x100] = {
402 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
403 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
404 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
405 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
406 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
407 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
408 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
409 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
410 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
411 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
412 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
413 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
414 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
417 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
426 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
428 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
429 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 static void usb_hid_changed(USBHIDState *hs)
439 hs->changed = 1;
441 if (hs->datain)
442 hs->datain(hs->datain_opaque);
444 usb_wakeup(&hs->dev);
447 static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
448 e->xdx = e->ydy = e->dz = 0;
449 e->buttons_state = buttons;
452 static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,
453 int x1, int y1, int z1) {
454 if (xyrel) {
455 e->xdx += x1;
456 e->ydy += y1;
457 } else {
458 e->xdx = x1;
459 e->ydy = y1;
461 e->dz += z1;
464 static void usb_pointer_event(void *opaque,
465 int x1, int y1, int z1, int buttons_state)
467 USBHIDState *hs = opaque;
468 USBMouseState *s = &hs->ptr;
469 unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
470 unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
472 /* We combine events where feasible to keep the queue small. We shouldn't
473 * combine anything with the first event of a particular button state, as
474 * that would change the location of the button state change. When the
475 * queue is empty, a second event is needed because we don't know if
476 * the first event changed the button state. */
477 if (hs->n == QUEUE_LENGTH) {
478 /* Queue full. Discard old button state, combine motion normally. */
479 s->queue[use_slot].buttons_state = buttons_state;
480 } else if (hs->n < 2 ||
481 s->queue[use_slot].buttons_state != buttons_state ||
482 s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
483 /* Cannot or should not combine, so add an empty item to the queue. */
484 QUEUE_INCR(use_slot);
485 hs->n++;
486 usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
488 usb_pointer_event_combine(&s->queue[use_slot],
489 hs->kind == USB_MOUSE,
490 x1, y1, z1);
491 usb_hid_changed(hs);
494 static void usb_keyboard_event(void *opaque, int keycode)
496 USBHIDState *hs = opaque;
497 USBKeyboardState *s = &hs->kbd;
498 int slot;
500 if (hs->n == QUEUE_LENGTH) {
501 fprintf(stderr, "usb-kbd: warning: key event queue full\n");
502 return;
504 slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
505 s->keycodes[slot] = keycode;
506 usb_hid_changed(hs);
509 static void usb_keyboard_process_keycode(USBHIDState *hs)
511 USBKeyboardState *s = &hs->kbd;
512 uint8_t hid_code, key;
513 int i, keycode, slot;
515 if (hs->n == 0) {
516 return;
518 slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
519 keycode = s->keycodes[slot];
521 key = keycode & 0x7f;
522 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
523 s->modifiers &= ~(1 << 8);
525 switch (hid_code) {
526 case 0x00:
527 return;
529 case 0xe0:
530 if (s->modifiers & (1 << 9)) {
531 s->modifiers ^= 3 << 8;
532 usb_hid_changed(hs);
533 return;
535 case 0xe1 ... 0xe7:
536 if (keycode & (1 << 7)) {
537 s->modifiers &= ~(1 << (hid_code & 0x0f));
538 usb_hid_changed(hs);
539 return;
541 case 0xe8 ... 0xef:
542 s->modifiers |= 1 << (hid_code & 0x0f);
543 usb_hid_changed(hs);
544 return;
547 if (keycode & (1 << 7)) {
548 for (i = s->keys - 1; i >= 0; i --)
549 if (s->key[i] == hid_code) {
550 s->key[i] = s->key[-- s->keys];
551 s->key[s->keys] = 0x00;
552 break;
554 if (i < 0)
555 return;
556 } else {
557 for (i = s->keys - 1; i >= 0; i --)
558 if (s->key[i] == hid_code)
559 break;
560 if (i < 0) {
561 if (s->keys < sizeof(s->key))
562 s->key[s->keys ++] = hid_code;
563 } else
564 return;
568 static inline int int_clamp(int val, int vmin, int vmax)
570 if (val < vmin)
571 return vmin;
572 else if (val > vmax)
573 return vmax;
574 else
575 return val;
578 static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
580 int dx, dy, dz, b, l;
581 int index;
582 USBMouseState *s = &hs->ptr;
583 USBPointerEvent *e;
585 if (!s->mouse_grabbed) {
586 qemu_activate_mouse_event_handler(s->eh_entry);
587 s->mouse_grabbed = 1;
590 /* When the buffer is empty, return the last event. Relative
591 movements will all be zero. */
592 index = (hs->n ? hs->head : hs->head - 1);
593 e = &s->queue[index & QUEUE_MASK];
595 if (hs->kind == USB_MOUSE) {
596 dx = int_clamp(e->xdx, -127, 127);
597 dy = int_clamp(e->ydy, -127, 127);
598 e->xdx -= dx;
599 e->ydy -= dy;
600 } else {
601 dx = e->xdx;
602 dy = e->ydy;
604 dz = int_clamp(e->dz, -127, 127);
605 e->dz -= dz;
607 b = 0;
608 if (e->buttons_state & MOUSE_EVENT_LBUTTON)
609 b |= 0x01;
610 if (e->buttons_state & MOUSE_EVENT_RBUTTON)
611 b |= 0x02;
612 if (e->buttons_state & MOUSE_EVENT_MBUTTON)
613 b |= 0x04;
615 if (hs->n &&
616 !e->dz &&
617 (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
618 /* that deals with this event */
619 QUEUE_INCR(hs->head);
620 hs->n--;
623 /* Appears we have to invert the wheel direction */
624 dz = 0 - dz;
625 l = 0;
626 switch (hs->kind) {
627 case USB_MOUSE:
628 if (len > l)
629 buf[l++] = b;
630 if (len > l)
631 buf[l++] = dx;
632 if (len > l)
633 buf[l++] = dy;
634 if (len > l)
635 buf[l++] = dz;
636 break;
638 case USB_TABLET:
639 if (len > l)
640 buf[l++] = b;
641 if (len > l)
642 buf[l++] = dx & 0xff;
643 if (len > l)
644 buf[l++] = dx >> 8;
645 if (len > l)
646 buf[l++] = dy & 0xff;
647 if (len > l)
648 buf[l++] = dy >> 8;
649 if (len > l)
650 buf[l++] = dz;
651 break;
653 default:
654 abort();
657 return l;
660 static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
662 USBKeyboardState *s = &hs->kbd;
663 if (len < 2)
664 return 0;
666 usb_keyboard_process_keycode(hs);
668 buf[0] = s->modifiers & 0xff;
669 buf[1] = 0;
670 if (s->keys > 6)
671 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
672 else
673 memcpy(buf + 2, s->key, MIN(8, len) - 2);
675 return MIN(8, len);
678 static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
680 if (len > 0) {
681 int ledstate = 0;
682 /* 0x01: Num Lock LED
683 * 0x02: Caps Lock LED
684 * 0x04: Scroll Lock LED
685 * 0x08: Compose LED
686 * 0x10: Kana LED */
687 s->leds = buf[0];
688 if (s->leds & 0x04)
689 ledstate |= QEMU_SCROLL_LOCK_LED;
690 if (s->leds & 0x01)
691 ledstate |= QEMU_NUM_LOCK_LED;
692 if (s->leds & 0x02)
693 ledstate |= QEMU_CAPS_LOCK_LED;
694 kbd_put_ledstate(ledstate);
696 return 0;
699 static void usb_mouse_handle_reset(USBDevice *dev)
701 USBHIDState *s = (USBHIDState *)dev;
703 memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
704 s->head = 0;
705 s->n = 0;
706 s->protocol = 1;
709 static void usb_keyboard_handle_reset(USBDevice *dev)
711 USBHIDState *s = (USBHIDState *)dev;
713 qemu_add_kbd_event_handler(usb_keyboard_event, s);
714 memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
715 s->head = 0;
716 s->n = 0;
717 memset(s->kbd.key, 0, sizeof (s->kbd.key));
718 s->kbd.keys = 0;
719 s->protocol = 1;
722 static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
724 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
727 static int usb_hid_handle_control(USBDevice *dev, int request, int value,
728 int index, int length, uint8_t *data)
730 USBHIDState *s = (USBHIDState *)dev;
731 int ret;
733 ret = usb_desc_handle_control(dev, request, value, index, length, data);
734 if (ret >= 0) {
735 return ret;
738 ret = 0;
739 switch(request) {
740 case DeviceRequest | USB_REQ_GET_INTERFACE:
741 data[0] = 0;
742 ret = 1;
743 break;
744 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
745 ret = 0;
746 break;
747 /* hid specific requests */
748 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
749 switch(value >> 8) {
750 case 0x22:
751 if (s->kind == USB_MOUSE) {
752 memcpy(data, qemu_mouse_hid_report_descriptor,
753 sizeof(qemu_mouse_hid_report_descriptor));
754 ret = sizeof(qemu_mouse_hid_report_descriptor);
755 } else if (s->kind == USB_TABLET) {
756 memcpy(data, qemu_tablet_hid_report_descriptor,
757 sizeof(qemu_tablet_hid_report_descriptor));
758 ret = sizeof(qemu_tablet_hid_report_descriptor);
759 } else if (s->kind == USB_KEYBOARD) {
760 memcpy(data, qemu_keyboard_hid_report_descriptor,
761 sizeof(qemu_keyboard_hid_report_descriptor));
762 ret = sizeof(qemu_keyboard_hid_report_descriptor);
764 break;
765 default:
766 goto fail;
768 break;
769 case GET_REPORT:
770 if (s->kind == USB_MOUSE || s->kind == USB_TABLET)
771 ret = usb_pointer_poll(s, data, length);
772 else if (s->kind == USB_KEYBOARD)
773 ret = usb_keyboard_poll(s, data, length);
774 break;
775 case SET_REPORT:
776 if (s->kind == USB_KEYBOARD)
777 ret = usb_keyboard_write(&s->kbd, data, length);
778 else
779 goto fail;
780 break;
781 case GET_PROTOCOL:
782 if (s->kind != USB_KEYBOARD)
783 goto fail;
784 ret = 1;
785 data[0] = s->protocol;
786 break;
787 case SET_PROTOCOL:
788 if (s->kind != USB_KEYBOARD)
789 goto fail;
790 ret = 0;
791 s->protocol = value;
792 break;
793 case GET_IDLE:
794 ret = 1;
795 data[0] = s->idle;
796 break;
797 case SET_IDLE:
798 s->idle = (uint8_t) (value >> 8);
799 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
800 ret = 0;
801 break;
802 default:
803 fail:
804 ret = USB_RET_STALL;
805 break;
807 return ret;
810 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
812 USBHIDState *s = (USBHIDState *)dev;
813 int ret = 0;
815 switch(p->pid) {
816 case USB_TOKEN_IN:
817 if (p->devep == 1) {
818 int64_t curtime = qemu_get_clock_ns(vm_clock);
819 if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
820 return USB_RET_NAK;
821 usb_hid_set_next_idle(s, curtime);
822 if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
823 ret = usb_pointer_poll(s, p->data, p->len);
825 else if (s->kind == USB_KEYBOARD) {
826 ret = usb_keyboard_poll(s, p->data, p->len);
828 s->changed = s->n > 0;
829 } else {
830 goto fail;
832 break;
833 case USB_TOKEN_OUT:
834 default:
835 fail:
836 ret = USB_RET_STALL;
837 break;
839 return ret;
842 static void usb_hid_handle_destroy(USBDevice *dev)
844 USBHIDState *s = (USBHIDState *)dev;
846 switch(s->kind) {
847 case USB_KEYBOARD:
848 qemu_remove_kbd_event_handler();
849 break;
850 default:
851 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
855 static int usb_hid_initfn(USBDevice *dev, int kind)
857 USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
859 usb_desc_init(dev);
860 s->kind = kind;
862 if (s->kind == USB_MOUSE) {
863 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
864 0, "QEMU USB Mouse");
865 } else if (s->kind == USB_TABLET) {
866 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
867 1, "QEMU USB Tablet");
870 /* Force poll routine to be run and grab input the first time. */
871 s->changed = 1;
872 return 0;
875 static int usb_tablet_initfn(USBDevice *dev)
877 return usb_hid_initfn(dev, USB_TABLET);
880 static int usb_mouse_initfn(USBDevice *dev)
882 return usb_hid_initfn(dev, USB_MOUSE);
885 static int usb_keyboard_initfn(USBDevice *dev)
887 return usb_hid_initfn(dev, USB_KEYBOARD);
890 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
892 USBHIDState *s = (USBHIDState *)dev;
894 s->datain_opaque = opaque;
895 s->datain = datain;
898 static int usb_hid_post_load(void *opaque, int version_id)
900 USBHIDState *s = opaque;
902 if (s->idle) {
903 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
905 return 0;
908 static const VMStateDescription vmstate_usb_ptr_queue = {
909 .name = "usb-ptr-queue",
910 .version_id = 1,
911 .minimum_version_id = 1,
912 .fields = (VMStateField []) {
913 VMSTATE_INT32(xdx, USBPointerEvent),
914 VMSTATE_INT32(ydy, USBPointerEvent),
915 VMSTATE_INT32(dz, USBPointerEvent),
916 VMSTATE_INT32(buttons_state, USBPointerEvent),
917 VMSTATE_END_OF_LIST()
920 static const VMStateDescription vmstate_usb_ptr = {
921 .name = "usb-ptr",
922 .version_id = 1,
923 .minimum_version_id = 1,
924 .post_load = usb_hid_post_load,
925 .fields = (VMStateField []) {
926 VMSTATE_USB_DEVICE(dev, USBHIDState),
927 VMSTATE_STRUCT_ARRAY(ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
928 vmstate_usb_ptr_queue, USBPointerEvent),
929 VMSTATE_UINT32(head, USBHIDState),
930 VMSTATE_UINT32(n, USBHIDState),
931 VMSTATE_INT32(protocol, USBHIDState),
932 VMSTATE_UINT8(idle, USBHIDState),
933 VMSTATE_END_OF_LIST()
937 static const VMStateDescription vmstate_usb_kbd = {
938 .name = "usb-kbd",
939 .version_id = 1,
940 .minimum_version_id = 1,
941 .post_load = usb_hid_post_load,
942 .fields = (VMStateField []) {
943 VMSTATE_USB_DEVICE(dev, USBHIDState),
944 VMSTATE_UINT32_ARRAY(kbd.keycodes, USBHIDState, QUEUE_LENGTH),
945 VMSTATE_UINT32(head, USBHIDState),
946 VMSTATE_UINT32(n, USBHIDState),
947 VMSTATE_UINT16(kbd.modifiers, USBHIDState),
948 VMSTATE_UINT8(kbd.leds, USBHIDState),
949 VMSTATE_UINT8_ARRAY(kbd.key, USBHIDState, 16),
950 VMSTATE_INT32(kbd.keys, USBHIDState),
951 VMSTATE_INT32(protocol, USBHIDState),
952 VMSTATE_UINT8(idle, USBHIDState),
953 VMSTATE_END_OF_LIST()
957 static struct USBDeviceInfo hid_info[] = {
959 .product_desc = "QEMU USB Tablet",
960 .qdev.name = "usb-tablet",
961 .usbdevice_name = "tablet",
962 .qdev.size = sizeof(USBHIDState),
963 .qdev.vmsd = &vmstate_usb_ptr,
964 .usb_desc = &desc_tablet,
965 .init = usb_tablet_initfn,
966 .handle_packet = usb_generic_handle_packet,
967 .handle_reset = usb_mouse_handle_reset,
968 .handle_control = usb_hid_handle_control,
969 .handle_data = usb_hid_handle_data,
970 .handle_destroy = usb_hid_handle_destroy,
972 .product_desc = "QEMU USB Mouse",
973 .qdev.name = "usb-mouse",
974 .usbdevice_name = "mouse",
975 .qdev.size = sizeof(USBHIDState),
976 .qdev.vmsd = &vmstate_usb_ptr,
977 .usb_desc = &desc_mouse,
978 .init = usb_mouse_initfn,
979 .handle_packet = usb_generic_handle_packet,
980 .handle_reset = usb_mouse_handle_reset,
981 .handle_control = usb_hid_handle_control,
982 .handle_data = usb_hid_handle_data,
983 .handle_destroy = usb_hid_handle_destroy,
985 .product_desc = "QEMU USB Keyboard",
986 .qdev.name = "usb-kbd",
987 .usbdevice_name = "keyboard",
988 .qdev.size = sizeof(USBHIDState),
989 .qdev.vmsd = &vmstate_usb_kbd,
990 .usb_desc = &desc_keyboard,
991 .init = usb_keyboard_initfn,
992 .handle_packet = usb_generic_handle_packet,
993 .handle_reset = usb_keyboard_handle_reset,
994 .handle_control = usb_hid_handle_control,
995 .handle_data = usb_hid_handle_data,
996 .handle_destroy = usb_hid_handle_destroy,
998 /* end of list */
1002 static void usb_hid_register_devices(void)
1004 usb_qdev_register_many(hid_info);
1006 device_init(usb_hid_register_devices)