]> git.proxmox.com Git - qemu.git/blame - hw/usb-hid.c
change all other clock references to use nanosecond resolution accessors
[qemu.git] / hw / usb-hid.c
CommitLineData
59ae540c
FB
1/*
2 * QEMU USB HID devices
5fafdf24 3 *
59ae540c 4 * Copyright (c) 2005 Fabrice Bellard
47b2d338 5 * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com)
5fafdf24 6 *
59ae540c
FB
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:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
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.
24 */
87ecb68b
PB
25#include "hw.h"
26#include "console.h"
27#include "usb.h"
0e4e9695 28#include "usb-desc.h"
666daa68 29#include "sysemu.h"
59ae540c
FB
30
31/* HID interface requests */
32#define GET_REPORT 0xa101
33#define GET_IDLE 0xa102
34#define GET_PROTOCOL 0xa103
47b2d338 35#define SET_REPORT 0x2109
59ae540c
FB
36#define SET_IDLE 0x210a
37#define SET_PROTOCOL 0x210b
38
47b2d338
AZ
39/* HID descriptor types */
40#define USB_DT_HID 0x21
41#define USB_DT_REPORT 0x22
42#define USB_DT_PHY 0x23
43
44#define USB_MOUSE 1
45#define USB_TABLET 2
46#define USB_KEYBOARD 3
09b26c5e 47
13f8b97a
PB
48typedef struct USBPointerEvent {
49 int32_t xdx, ydy; /* relative iff it's a mouse, otherwise absolute */
50 int32_t dz, buttons_state;
51} USBPointerEvent;
52
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)
56
59ae540c 57typedef struct USBMouseState {
13f8b97a 58 USBPointerEvent queue[QUEUE_LENGTH];
09b26c5e 59 int mouse_grabbed;
455204eb 60 QEMUPutMouseEntry *eh_entry;
59ae540c
FB
61} USBMouseState;
62
47b2d338 63typedef struct USBKeyboardState {
5fae51a9 64 uint32_t keycodes[QUEUE_LENGTH];
47b2d338
AZ
65 uint16_t modifiers;
66 uint8_t leds;
67 uint8_t key[16];
ee59e6b3 68 int32_t keys;
47b2d338
AZ
69} USBKeyboardState;
70
71typedef struct USBHIDState {
72 USBDevice dev;
73 union {
74 USBMouseState ptr;
75 USBKeyboardState kbd;
76 };
42292d4e
GH
77 uint32_t head; /* index into circular queue */
78 uint32_t n;
47b2d338 79 int kind;
ee59e6b3 80 int32_t protocol;
181a29c5 81 uint8_t idle;
68735b6c 82 int64_t next_idle_clock;
117b3ae6 83 int changed;
47e699dc
AZ
84 void *datain_opaque;
85 void (*datain)(void *);
47b2d338
AZ
86} USBHIDState;
87
0e4e9695
GH
88enum {
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,
59ae540c
FB
97};
98
0e4e9695
GH
99static 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",
7b074a22 104 [STR_SERIALNUMBER] = "42", /* == remote wakeup works */
0e4e9695
GH
105 [STR_CONFIG_MOUSE] = "HID Mouse",
106 [STR_CONFIG_TABLET] = "HID Tablet",
107 [STR_CONFIG_KEYBOARD] = "HID Keyboard",
09b26c5e
FB
108};
109
0e4e9695
GH
110static 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[]) {
118 {
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 */
128 },
129 },
130 },
131 .eps = (USBDescEndpoint[]) {
132 {
133 .bEndpointAddress = USB_DIR_IN | 0x01,
134 .bmAttributes = USB_ENDPOINT_XFER_INT,
135 .wMaxPacketSize = 4,
136 .bInterval = 0x0a,
137 },
138 },
59ae540c
FB
139};
140
0e4e9695
GH
141static 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[]) {
149 {
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 */
159 },
160 },
161 },
162 .eps = (USBDescEndpoint[]) {
163 {
164 .bEndpointAddress = USB_DIR_IN | 0x01,
165 .bmAttributes = USB_ENDPOINT_XFER_INT,
166 .wMaxPacketSize = 8,
167 .bInterval = 0x0a,
168 },
169 },
170};
171
172static 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[]) {
180 {
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 */
190 },
191 },
192 },
193 .eps = (USBDescEndpoint[]) {
194 {
195 .bEndpointAddress = USB_DIR_IN | 0x01,
196 .bmAttributes = USB_ENDPOINT_XFER_INT,
197 .wMaxPacketSize = 8,
198 .bInterval = 0x0a,
199 },
200 },
201};
202
203static const USBDescDevice desc_device_mouse = {
204 .bcdUSB = 0x0100,
205 .bMaxPacketSize0 = 8,
206 .bNumConfigurations = 1,
207 .confs = (USBDescConfig[]) {
208 {
209 .bNumInterfaces = 1,
210 .bConfigurationValue = 1,
211 .iConfiguration = STR_CONFIG_MOUSE,
212 .bmAttributes = 0xa0,
213 .bMaxPower = 50,
214 .ifs = &desc_iface_mouse,
215 },
216 },
217};
218
219static const USBDescDevice desc_device_tablet = {
220 .bcdUSB = 0x0100,
221 .bMaxPacketSize0 = 8,
222 .bNumConfigurations = 1,
223 .confs = (USBDescConfig[]) {
224 {
225 .bNumInterfaces = 1,
226 .bConfigurationValue = 1,
227 .iConfiguration = STR_CONFIG_TABLET,
228 .bmAttributes = 0xa0,
229 .bMaxPower = 50,
230 .ifs = &desc_iface_tablet,
231 },
232 },
233};
234
235static const USBDescDevice desc_device_keyboard = {
236 .bcdUSB = 0x0100,
237 .bMaxPacketSize0 = 8,
238 .bNumConfigurations = 1,
239 .confs = (USBDescConfig[]) {
240 {
241 .bNumInterfaces = 1,
242 .bConfigurationValue = 1,
243 .iConfiguration = STR_CONFIG_KEYBOARD,
244 .bmAttributes = 0xa0,
245 .bMaxPower = 50,
246 .ifs = &desc_iface_keyboard,
247 },
248 },
249};
250
251static 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,
259 },
260 .full = &desc_device_mouse,
261 .str = desc_strings,
262};
263
264static 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,
272 },
273 .full = &desc_device_tablet,
274 .str = desc_strings,
275};
276
277static 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,
285 },
286 .full = &desc_device_keyboard,
287 .str = desc_strings,
47b2d338
AZ
288};
289
59ae540c 290static const uint8_t qemu_mouse_hid_report_descriptor[] = {
976f8eef
AZ
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 */
59ae540c
FB
318};
319
09b26c5e 320static const uint8_t qemu_tablet_hid_report_descriptor[] = {
976f8eef
AZ
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) */
de5c2d0a 341 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
976f8eef 342 0x35, 0x00, /* Physical Minimum (0) */
de5c2d0a 343 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
976f8eef
AZ
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 */
09b26c5e
FB
358};
359
47b2d338
AZ
360static 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 */
393};
394
395#define USB_HID_USAGE_ERROR_ROLLOVER 0x01
396#define USB_HID_USAGE_POSTFAIL 0x02
397#define USB_HID_USAGE_ERROR_UNDEFINED 0x03
398
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. */
401static 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,
418
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,
a8fb7ff3 430 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
47b2d338
AZ
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,
435};
436
47e699dc
AZ
437static void usb_hid_changed(USBHIDState *hs)
438{
439 hs->changed = 1;
440
441 if (hs->datain)
442 hs->datain(hs->datain_opaque);
ac57bbb6
GH
443
444 usb_wakeup(&hs->dev);
47e699dc
AZ
445}
446
13f8b97a
PB
447static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
448 e->xdx = e->ydy = e->dz = 0;
449 e->buttons_state = buttons;
450}
47e699dc 451
13f8b97a
PB
452static 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;
460 }
461 e->dz += z1;
59ae540c
FB
462}
463
13f8b97a
PB
464static void usb_pointer_event(void *opaque,
465 int x1, int y1, int z1, int buttons_state)
09b26c5e 466{
117b3ae6
PB
467 USBHIDState *hs = opaque;
468 USBMouseState *s = &hs->ptr;
42292d4e 469 unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
13f8b97a
PB
470 unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
471
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. */
42292d4e 477 if (hs->n == QUEUE_LENGTH) {
13f8b97a
PB
478 /* Queue full. Discard old button state, combine motion normally. */
479 s->queue[use_slot].buttons_state = buttons_state;
42292d4e 480 } else if (hs->n < 2 ||
13f8b97a
PB
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);
42292d4e 485 hs->n++;
13f8b97a
PB
486 usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
487 }
488 usb_pointer_event_combine(&s->queue[use_slot],
489 hs->kind == USB_MOUSE,
490 x1, y1, z1);
47e699dc 491 usb_hid_changed(hs);
09b26c5e
FB
492}
493
47b2d338
AZ
494static void usb_keyboard_event(void *opaque, int keycode)
495{
117b3ae6
PB
496 USBHIDState *hs = opaque;
497 USBKeyboardState *s = &hs->kbd;
5fae51a9
GH
498 int slot;
499
42292d4e 500 if (hs->n == QUEUE_LENGTH) {
5fae51a9
GH
501 fprintf(stderr, "usb-kbd: warning: key event queue full\n");
502 return;
503 }
42292d4e 504 slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
5fae51a9
GH
505 s->keycodes[slot] = keycode;
506 usb_hid_changed(hs);
507}
508
42292d4e 509static void usb_keyboard_process_keycode(USBHIDState *hs)
5fae51a9 510{
42292d4e 511 USBKeyboardState *s = &hs->kbd;
47b2d338 512 uint8_t hid_code, key;
5fae51a9
GH
513 int i, keycode, slot;
514
42292d4e 515 if (hs->n == 0) {
5fae51a9
GH
516 return;
517 }
42292d4e 518 slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
5fae51a9 519 keycode = s->keycodes[slot];
47b2d338
AZ
520
521 key = keycode & 0x7f;
522 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
523 s->modifiers &= ~(1 << 8);
524
525 switch (hid_code) {
526 case 0x00:
527 return;
528
529 case 0xe0:
530 if (s->modifiers & (1 << 9)) {
531 s->modifiers ^= 3 << 8;
373dfc44 532 usb_hid_changed(hs);
47b2d338
AZ
533 return;
534 }
535 case 0xe1 ... 0xe7:
536 if (keycode & (1 << 7)) {
537 s->modifiers &= ~(1 << (hid_code & 0x0f));
373dfc44 538 usb_hid_changed(hs);
47b2d338
AZ
539 return;
540 }
541 case 0xe8 ... 0xef:
542 s->modifiers |= 1 << (hid_code & 0x0f);
373dfc44 543 usb_hid_changed(hs);
47b2d338
AZ
544 return;
545 }
546
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;
47e699dc 552 break;
47b2d338 553 }
47e699dc
AZ
554 if (i < 0)
555 return;
47b2d338
AZ
556 } else {
557 for (i = s->keys - 1; i >= 0; i --)
558 if (s->key[i] == hid_code)
47e699dc
AZ
559 break;
560 if (i < 0) {
561 if (s->keys < sizeof(s->key))
562 s->key[s->keys ++] = hid_code;
563 } else
564 return;
47b2d338
AZ
565 }
566}
567
59ae540c
FB
568static inline int int_clamp(int val, int vmin, int vmax)
569{
570 if (val < vmin)
571 return vmin;
572 else if (val > vmax)
573 return vmax;
574 else
575 return val;
576}
577
13f8b97a 578static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
59ae540c
FB
579{
580 int dx, dy, dz, b, l;
13f8b97a 581 int index;
117b3ae6 582 USBMouseState *s = &hs->ptr;
13f8b97a 583 USBPointerEvent *e;
59ae540c 584
09b26c5e 585 if (!s->mouse_grabbed) {
6fef28ee 586 qemu_activate_mouse_event_handler(s->eh_entry);
13f8b97a 587 s->mouse_grabbed = 1;
09b26c5e 588 }
3b46e624 589
13f8b97a
PB
590 /* When the buffer is empty, return the last event. Relative
591 movements will all be zero. */
42292d4e 592 index = (hs->n ? hs->head : hs->head - 1);
13f8b97a 593 e = &s->queue[index & QUEUE_MASK];
3b46e624 594
13f8b97a
PB
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;
603 }
604 dz = int_clamp(e->dz, -127, 127);
605 e->dz -= dz;
976f8eef 606
59ae540c 607 b = 0;
13f8b97a 608 if (e->buttons_state & MOUSE_EVENT_LBUTTON)
59ae540c 609 b |= 0x01;
13f8b97a 610 if (e->buttons_state & MOUSE_EVENT_RBUTTON)
59ae540c 611 b |= 0x02;
13f8b97a 612 if (e->buttons_state & MOUSE_EVENT_MBUTTON)
59ae540c 613 b |= 0x04;
3b46e624 614
42292d4e 615 if (hs->n &&
13f8b97a
PB
616 !e->dz &&
617 (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
618 /* that deals with this event */
42292d4e
GH
619 QUEUE_INCR(hs->head);
620 hs->n--;
09b26c5e 621 }
3b46e624 622
09b26c5e
FB
623 /* Appears we have to invert the wheel direction */
624 dz = 0 - dz;
13f8b97a
PB
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;
09b26c5e 637
13f8b97a
PB
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;
652
653 default:
654 abort();
655 }
09b26c5e
FB
656
657 return l;
658}
659
13f8b97a 660static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
47b2d338 661{
13f8b97a 662 USBKeyboardState *s = &hs->kbd;
47b2d338
AZ
663 if (len < 2)
664 return 0;
665
42292d4e 666 usb_keyboard_process_keycode(hs);
5fae51a9 667
47b2d338
AZ
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);
674
675 return MIN(8, len);
676}
677
678static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
679{
680 if (len > 0) {
bd87813e 681 int ledstate = 0;
47b2d338
AZ
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];
bd87813e
GH
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);
47b2d338
AZ
695 }
696 return 0;
697}
698
059809e4 699static void usb_mouse_handle_reset(USBDevice *dev)
59ae540c 700{
47b2d338
AZ
701 USBHIDState *s = (USBHIDState *)dev;
702
5fae51a9 703 memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
42292d4e
GH
704 s->head = 0;
705 s->n = 0;
47b2d338
AZ
706 s->protocol = 1;
707}
708
709static void usb_keyboard_handle_reset(USBDevice *dev)
710{
711 USBHIDState *s = (USBHIDState *)dev;
712
926acf8f 713 qemu_add_kbd_event_handler(usb_keyboard_event, s);
5fae51a9 714 memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
42292d4e
GH
715 s->head = 0;
716 s->n = 0;
5fae51a9
GH
717 memset(s->kbd.key, 0, sizeof (s->kbd.key));
718 s->kbd.keys = 0;
47b2d338 719 s->protocol = 1;
59ae540c
FB
720}
721
68735b6c
KC
722static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
723{
724 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
725}
726
47b2d338 727static int usb_hid_handle_control(USBDevice *dev, int request, int value,
59ae540c
FB
728 int index, int length, uint8_t *data)
729{
47b2d338 730 USBHIDState *s = (USBHIDState *)dev;
0e4e9695 731 int ret;
59ae540c 732
0e4e9695
GH
733 ret = usb_desc_handle_control(dev, request, value, index, length, data);
734 if (ret >= 0) {
735 return ret;
736 }
59ae540c 737
0e4e9695 738 ret = 0;
59ae540c 739 switch(request) {
59ae540c
FB
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:
09b26c5e 751 if (s->kind == USB_MOUSE) {
5fafdf24 752 memcpy(data, qemu_mouse_hid_report_descriptor,
09b26c5e
FB
753 sizeof(qemu_mouse_hid_report_descriptor));
754 ret = sizeof(qemu_mouse_hid_report_descriptor);
755 } else if (s->kind == USB_TABLET) {
5fafdf24 756 memcpy(data, qemu_tablet_hid_report_descriptor,
09b26c5e
FB
757 sizeof(qemu_tablet_hid_report_descriptor));
758 ret = sizeof(qemu_tablet_hid_report_descriptor);
47b2d338 759 } else if (s->kind == USB_KEYBOARD) {
5fafdf24 760 memcpy(data, qemu_keyboard_hid_report_descriptor,
47b2d338
AZ
761 sizeof(qemu_keyboard_hid_report_descriptor));
762 ret = sizeof(qemu_keyboard_hid_report_descriptor);
763 }
764 break;
59ae540c
FB
765 default:
766 goto fail;
767 }
768 break;
769 case GET_REPORT:
13f8b97a
PB
770 if (s->kind == USB_MOUSE || s->kind == USB_TABLET)
771 ret = usb_pointer_poll(s, data, length);
47b2d338 772 else if (s->kind == USB_KEYBOARD)
13f8b97a 773 ret = usb_keyboard_poll(s, data, length);
47b2d338
AZ
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;
59ae540c
FB
796 break;
797 case SET_IDLE:
181a29c5 798 s->idle = (uint8_t) (value >> 8);
74475455 799 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
59ae540c
FB
800 ret = 0;
801 break;
802 default:
803 fail:
804 ret = USB_RET_STALL;
805 break;
806 }
807 return ret;
808}
809
47b2d338 810static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
59ae540c 811{
47b2d338 812 USBHIDState *s = (USBHIDState *)dev;
09b26c5e 813 int ret = 0;
59ae540c 814
4d611c9a 815 switch(p->pid) {
59ae540c 816 case USB_TOKEN_IN:
4d611c9a 817 if (p->devep == 1) {
74475455 818 int64_t curtime = qemu_get_clock_ns(vm_clock);
68735b6c 819 if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
117b3ae6 820 return USB_RET_NAK;
68735b6c 821 usb_hid_set_next_idle(s, curtime);
13f8b97a
PB
822 if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
823 ret = usb_pointer_poll(s, p->data, p->len);
13f8b97a
PB
824 }
825 else if (s->kind == USB_KEYBOARD) {
826 ret = usb_keyboard_poll(s, p->data, p->len);
13f8b97a 827 }
42292d4e 828 s->changed = s->n > 0;
59ae540c
FB
829 } else {
830 goto fail;
831 }
832 break;
833 case USB_TOKEN_OUT:
834 default:
835 fail:
836 ret = USB_RET_STALL;
837 break;
838 }
839 return ret;
840}
841
47b2d338 842static void usb_hid_handle_destroy(USBDevice *dev)
059809e4 843{
47b2d338 844 USBHIDState *s = (USBHIDState *)dev;
059809e4 845
46aaebff
JS
846 switch(s->kind) {
847 case USB_KEYBOARD:
848 qemu_remove_kbd_event_handler();
849 break;
850 default:
47b2d338 851 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
46aaebff 852 }
059809e4
FB
853}
854
806b6024 855static int usb_hid_initfn(USBDevice *dev, int kind)
09b26c5e 856{
806b6024 857 USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
a980a065
GH
858
859 usb_desc_init(dev);
806b6024 860 s->kind = kind;
6fef28ee
AL
861
862 if (s->kind == USB_MOUSE) {
13f8b97a 863 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
6fef28ee
AL
864 0, "QEMU USB Mouse");
865 } else if (s->kind == USB_TABLET) {
13f8b97a 866 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
6fef28ee
AL
867 1, "QEMU USB Tablet");
868 }
13f8b97a 869
117b3ae6
PB
870 /* Force poll routine to be run and grab input the first time. */
871 s->changed = 1;
806b6024 872 return 0;
09b26c5e
FB
873}
874
806b6024 875static int usb_tablet_initfn(USBDevice *dev)
59ae540c 876{
806b6024
GH
877 return usb_hid_initfn(dev, USB_TABLET);
878}
59ae540c 879
806b6024
GH
880static int usb_mouse_initfn(USBDevice *dev)
881{
882 return usb_hid_initfn(dev, USB_MOUSE);
883}
59ae540c 884
806b6024
GH
885static int usb_keyboard_initfn(USBDevice *dev)
886{
887 return usb_hid_initfn(dev, USB_KEYBOARD);
888}
59ae540c 889
47e699dc
AZ
890void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
891{
892 USBHIDState *s = (USBHIDState *)dev;
893
894 s->datain_opaque = opaque;
895 s->datain = datain;
896}
806b6024 897
ee59e6b3
GH
898static int usb_hid_post_load(void *opaque, int version_id)
899{
900 USBHIDState *s = opaque;
901
902 if (s->idle) {
74475455 903 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
ee59e6b3
GH
904 }
905 return 0;
906}
907
908static 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()
918 }
919};
920static 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()
934 }
935};
936
937static 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()
954 }
955};
956
806b6024
GH
957static struct USBDeviceInfo hid_info[] = {
958 {
06384698 959 .product_desc = "QEMU USB Tablet",
556cd098 960 .qdev.name = "usb-tablet",
fa7c70c3 961 .usbdevice_name = "tablet",
806b6024 962 .qdev.size = sizeof(USBHIDState),
ee59e6b3 963 .qdev.vmsd = &vmstate_usb_ptr,
0e4e9695 964 .usb_desc = &desc_tablet,
806b6024
GH
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,
971 },{
06384698 972 .product_desc = "QEMU USB Mouse",
556cd098 973 .qdev.name = "usb-mouse",
fa7c70c3 974 .usbdevice_name = "mouse",
806b6024 975 .qdev.size = sizeof(USBHIDState),
ee59e6b3 976 .qdev.vmsd = &vmstate_usb_ptr,
0e4e9695 977 .usb_desc = &desc_mouse,
806b6024
GH
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,
984 },{
06384698 985 .product_desc = "QEMU USB Keyboard",
556cd098 986 .qdev.name = "usb-kbd",
fa7c70c3 987 .usbdevice_name = "keyboard",
806b6024 988 .qdev.size = sizeof(USBHIDState),
ee59e6b3 989 .qdev.vmsd = &vmstate_usb_kbd,
0e4e9695 990 .usb_desc = &desc_keyboard,
806b6024
GH
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,
997 },{
998 /* end of list */
999 }
1000};
1001
1002static void usb_hid_register_devices(void)
1003{
1004 usb_qdev_register_many(hid_info);
1005}
1006device_init(usb_hid_register_devices)