]> git.proxmox.com Git - qemu.git/blame - hw/usb-hid.c
Merge remote-tracking branch 'qmp/for-anthony' into staging
[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"
d8dfad9c 29#include "qemu-timer.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,
0e4e9695
GH
145 .bInterfaceProtocol = 0x02,
146 .ndesc = 1,
147 .descs = (USBDescOther[]) {
148 {
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 */
158 },
159 },
160 },
161 .eps = (USBDescEndpoint[]) {
162 {
163 .bEndpointAddress = USB_DIR_IN | 0x01,
164 .bmAttributes = USB_ENDPOINT_XFER_INT,
165 .wMaxPacketSize = 8,
166 .bInterval = 0x0a,
167 },
168 },
169};
170
171static 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[]) {
179 {
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 */
189 },
190 },
191 },
192 .eps = (USBDescEndpoint[]) {
193 {
194 .bEndpointAddress = USB_DIR_IN | 0x01,
195 .bmAttributes = USB_ENDPOINT_XFER_INT,
196 .wMaxPacketSize = 8,
197 .bInterval = 0x0a,
198 },
199 },
200};
201
202static const USBDescDevice desc_device_mouse = {
203 .bcdUSB = 0x0100,
204 .bMaxPacketSize0 = 8,
205 .bNumConfigurations = 1,
206 .confs = (USBDescConfig[]) {
207 {
208 .bNumInterfaces = 1,
209 .bConfigurationValue = 1,
210 .iConfiguration = STR_CONFIG_MOUSE,
211 .bmAttributes = 0xa0,
212 .bMaxPower = 50,
add75088 213 .nif = 1,
0e4e9695
GH
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,
add75088 230 .nif = 1,
0e4e9695
GH
231 .ifs = &desc_iface_tablet,
232 },
233 },
234};
235
236static const USBDescDevice desc_device_keyboard = {
237 .bcdUSB = 0x0100,
238 .bMaxPacketSize0 = 8,
239 .bNumConfigurations = 1,
240 .confs = (USBDescConfig[]) {
241 {
242 .bNumInterfaces = 1,
243 .bConfigurationValue = 1,
244 .iConfiguration = STR_CONFIG_KEYBOARD,
245 .bmAttributes = 0xa0,
246 .bMaxPower = 50,
add75088 247 .nif = 1,
0e4e9695
GH
248 .ifs = &desc_iface_keyboard,
249 },
250 },
251};
252
253static 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,
261 },
262 .full = &desc_device_mouse,
263 .str = desc_strings,
264};
265
266static 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,
274 },
275 .full = &desc_device_tablet,
276 .str = desc_strings,
277};
278
279static 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,
287 },
288 .full = &desc_device_keyboard,
289 .str = desc_strings,
47b2d338
AZ
290};
291
59ae540c 292static const uint8_t qemu_mouse_hid_report_descriptor[] = {
976f8eef
AZ
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 */
59ae540c
FB
320};
321
09b26c5e 322static const uint8_t qemu_tablet_hid_report_descriptor[] = {
976f8eef
AZ
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) */
de5c2d0a 343 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
976f8eef 344 0x35, 0x00, /* Physical Minimum (0) */
de5c2d0a 345 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
976f8eef
AZ
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 */
09b26c5e
FB
360};
361
47b2d338
AZ
362static 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 */
395};
396
397#define USB_HID_USAGE_ERROR_ROLLOVER 0x01
398#define USB_HID_USAGE_POSTFAIL 0x02
399#define USB_HID_USAGE_ERROR_UNDEFINED 0x03
400
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. */
403static 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,
420
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,
a8fb7ff3 432 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
47b2d338
AZ
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,
437};
438
47e699dc
AZ
439static void usb_hid_changed(USBHIDState *hs)
440{
441 hs->changed = 1;
442
443 if (hs->datain)
444 hs->datain(hs->datain_opaque);
ac57bbb6
GH
445
446 usb_wakeup(&hs->dev);
47e699dc
AZ
447}
448
13f8b97a
PB
449static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
450 e->xdx = e->ydy = e->dz = 0;
451 e->buttons_state = buttons;
452}
47e699dc 453
13f8b97a
PB
454static 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 }
463 e->dz += z1;
59ae540c
FB
464}
465
13f8b97a
PB
466static void usb_pointer_event(void *opaque,
467 int x1, int y1, int z1, int buttons_state)
09b26c5e 468{
117b3ae6
PB
469 USBHIDState *hs = opaque;
470 USBMouseState *s = &hs->ptr;
42292d4e 471 unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
13f8b97a
PB
472 unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
473
474 /* We combine events where feasible to keep the queue small. We shouldn't
475 * combine anything with the first event of a particular button state, as
476 * that would change the location of the button state change. When the
477 * queue is empty, a second event is needed because we don't know if
478 * the first event changed the button state. */
42292d4e 479 if (hs->n == QUEUE_LENGTH) {
13f8b97a
PB
480 /* Queue full. Discard old button state, combine motion normally. */
481 s->queue[use_slot].buttons_state = buttons_state;
42292d4e 482 } else if (hs->n < 2 ||
13f8b97a
PB
483 s->queue[use_slot].buttons_state != buttons_state ||
484 s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
485 /* Cannot or should not combine, so add an empty item to the queue. */
486 QUEUE_INCR(use_slot);
42292d4e 487 hs->n++;
13f8b97a
PB
488 usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
489 }
490 usb_pointer_event_combine(&s->queue[use_slot],
491 hs->kind == USB_MOUSE,
492 x1, y1, z1);
47e699dc 493 usb_hid_changed(hs);
09b26c5e
FB
494}
495
47b2d338
AZ
496static void usb_keyboard_event(void *opaque, int keycode)
497{
117b3ae6
PB
498 USBHIDState *hs = opaque;
499 USBKeyboardState *s = &hs->kbd;
5fae51a9
GH
500 int slot;
501
42292d4e 502 if (hs->n == QUEUE_LENGTH) {
5fae51a9
GH
503 fprintf(stderr, "usb-kbd: warning: key event queue full\n");
504 return;
505 }
42292d4e 506 slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
5fae51a9
GH
507 s->keycodes[slot] = keycode;
508 usb_hid_changed(hs);
509}
510
42292d4e 511static void usb_keyboard_process_keycode(USBHIDState *hs)
5fae51a9 512{
42292d4e 513 USBKeyboardState *s = &hs->kbd;
47b2d338 514 uint8_t hid_code, key;
5fae51a9
GH
515 int i, keycode, slot;
516
42292d4e 517 if (hs->n == 0) {
5fae51a9
GH
518 return;
519 }
42292d4e 520 slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
5fae51a9 521 keycode = s->keycodes[slot];
47b2d338
AZ
522
523 key = keycode & 0x7f;
524 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
525 s->modifiers &= ~(1 << 8);
526
527 switch (hid_code) {
528 case 0x00:
529 return;
530
531 case 0xe0:
532 if (s->modifiers & (1 << 9)) {
533 s->modifiers ^= 3 << 8;
534 return;
535 }
536 case 0xe1 ... 0xe7:
537 if (keycode & (1 << 7)) {
538 s->modifiers &= ~(1 << (hid_code & 0x0f));
539 return;
540 }
541 case 0xe8 ... 0xef:
542 s->modifiers |= 1 << (hid_code & 0x0f);
543 return;
544 }
545
546 if (keycode & (1 << 7)) {
547 for (i = s->keys - 1; i >= 0; i --)
548 if (s->key[i] == hid_code) {
549 s->key[i] = s->key[-- s->keys];
550 s->key[s->keys] = 0x00;
47e699dc 551 break;
47b2d338 552 }
47e699dc
AZ
553 if (i < 0)
554 return;
47b2d338
AZ
555 } else {
556 for (i = s->keys - 1; i >= 0; i --)
557 if (s->key[i] == hid_code)
47e699dc
AZ
558 break;
559 if (i < 0) {
560 if (s->keys < sizeof(s->key))
561 s->key[s->keys ++] = hid_code;
562 } else
563 return;
47b2d338
AZ
564 }
565}
566
59ae540c
FB
567static inline int int_clamp(int val, int vmin, int vmax)
568{
569 if (val < vmin)
570 return vmin;
571 else if (val > vmax)
572 return vmax;
573 else
574 return val;
575}
576
13f8b97a 577static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
59ae540c
FB
578{
579 int dx, dy, dz, b, l;
13f8b97a 580 int index;
117b3ae6 581 USBMouseState *s = &hs->ptr;
13f8b97a 582 USBPointerEvent *e;
59ae540c 583
09b26c5e 584 if (!s->mouse_grabbed) {
6fef28ee 585 qemu_activate_mouse_event_handler(s->eh_entry);
13f8b97a 586 s->mouse_grabbed = 1;
09b26c5e 587 }
3b46e624 588
13f8b97a
PB
589 /* When the buffer is empty, return the last event. Relative
590 movements will all be zero. */
42292d4e 591 index = (hs->n ? hs->head : hs->head - 1);
13f8b97a 592 e = &s->queue[index & QUEUE_MASK];
3b46e624 593
13f8b97a
PB
594 if (hs->kind == USB_MOUSE) {
595 dx = int_clamp(e->xdx, -127, 127);
596 dy = int_clamp(e->ydy, -127, 127);
597 e->xdx -= dx;
598 e->ydy -= dy;
599 } else {
600 dx = e->xdx;
601 dy = e->ydy;
602 }
603 dz = int_clamp(e->dz, -127, 127);
604 e->dz -= dz;
976f8eef 605
59ae540c 606 b = 0;
13f8b97a 607 if (e->buttons_state & MOUSE_EVENT_LBUTTON)
59ae540c 608 b |= 0x01;
13f8b97a 609 if (e->buttons_state & MOUSE_EVENT_RBUTTON)
59ae540c 610 b |= 0x02;
13f8b97a 611 if (e->buttons_state & MOUSE_EVENT_MBUTTON)
59ae540c 612 b |= 0x04;
3b46e624 613
42292d4e 614 if (hs->n &&
13f8b97a
PB
615 !e->dz &&
616 (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
617 /* that deals with this event */
42292d4e
GH
618 QUEUE_INCR(hs->head);
619 hs->n--;
09b26c5e 620 }
3b46e624 621
09b26c5e
FB
622 /* Appears we have to invert the wheel direction */
623 dz = 0 - dz;
13f8b97a
PB
624 l = 0;
625 switch (hs->kind) {
626 case USB_MOUSE:
627 if (len > l)
628 buf[l++] = b;
629 if (len > l)
630 buf[l++] = dx;
631 if (len > l)
632 buf[l++] = dy;
633 if (len > l)
634 buf[l++] = dz;
635 break;
09b26c5e 636
13f8b97a
PB
637 case USB_TABLET:
638 if (len > l)
639 buf[l++] = b;
640 if (len > l)
641 buf[l++] = dx & 0xff;
642 if (len > l)
643 buf[l++] = dx >> 8;
644 if (len > l)
645 buf[l++] = dy & 0xff;
646 if (len > l)
647 buf[l++] = dy >> 8;
648 if (len > l)
649 buf[l++] = dz;
650 break;
651
652 default:
653 abort();
654 }
09b26c5e
FB
655
656 return l;
657}
658
13f8b97a 659static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
47b2d338 660{
13f8b97a 661 USBKeyboardState *s = &hs->kbd;
47b2d338
AZ
662 if (len < 2)
663 return 0;
664
42292d4e 665 usb_keyboard_process_keycode(hs);
5fae51a9 666
47b2d338
AZ
667 buf[0] = s->modifiers & 0xff;
668 buf[1] = 0;
669 if (s->keys > 6)
670 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
671 else
672 memcpy(buf + 2, s->key, MIN(8, len) - 2);
673
674 return MIN(8, len);
675}
676
677static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
678{
679 if (len > 0) {
bd87813e 680 int ledstate = 0;
47b2d338
AZ
681 /* 0x01: Num Lock LED
682 * 0x02: Caps Lock LED
683 * 0x04: Scroll Lock LED
684 * 0x08: Compose LED
685 * 0x10: Kana LED */
686 s->leds = buf[0];
bd87813e
GH
687 if (s->leds & 0x04)
688 ledstate |= QEMU_SCROLL_LOCK_LED;
689 if (s->leds & 0x01)
690 ledstate |= QEMU_NUM_LOCK_LED;
691 if (s->leds & 0x02)
692 ledstate |= QEMU_CAPS_LOCK_LED;
693 kbd_put_ledstate(ledstate);
47b2d338
AZ
694 }
695 return 0;
696}
697
059809e4 698static void usb_mouse_handle_reset(USBDevice *dev)
59ae540c 699{
47b2d338
AZ
700 USBHIDState *s = (USBHIDState *)dev;
701
5fae51a9 702 memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
42292d4e
GH
703 s->head = 0;
704 s->n = 0;
47b2d338
AZ
705 s->protocol = 1;
706}
707
708static void usb_keyboard_handle_reset(USBDevice *dev)
709{
710 USBHIDState *s = (USBHIDState *)dev;
711
926acf8f 712 qemu_add_kbd_event_handler(usb_keyboard_event, s);
5fae51a9 713 memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
42292d4e
GH
714 s->head = 0;
715 s->n = 0;
5fae51a9
GH
716 memset(s->kbd.key, 0, sizeof (s->kbd.key));
717 s->kbd.keys = 0;
47b2d338 718 s->protocol = 1;
59ae540c
FB
719}
720
68735b6c
KC
721static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
722{
723 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
724}
725
007fd62f
HG
726static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
727 int request, int value, int index, int length, uint8_t *data)
59ae540c 728{
47b2d338 729 USBHIDState *s = (USBHIDState *)dev;
0e4e9695 730 int ret;
59ae540c 731
007fd62f 732 ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
0e4e9695
GH
733 if (ret >= 0) {
734 return ret;
735 }
59ae540c 736
0e4e9695 737 ret = 0;
59ae540c 738 switch(request) {
59ae540c
FB
739 case DeviceRequest | USB_REQ_GET_INTERFACE:
740 data[0] = 0;
741 ret = 1;
742 break;
743 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
744 ret = 0;
745 break;
746 /* hid specific requests */
747 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
748 switch(value >> 8) {
749 case 0x22:
09b26c5e 750 if (s->kind == USB_MOUSE) {
5fafdf24 751 memcpy(data, qemu_mouse_hid_report_descriptor,
09b26c5e
FB
752 sizeof(qemu_mouse_hid_report_descriptor));
753 ret = sizeof(qemu_mouse_hid_report_descriptor);
754 } else if (s->kind == USB_TABLET) {
5fafdf24 755 memcpy(data, qemu_tablet_hid_report_descriptor,
09b26c5e
FB
756 sizeof(qemu_tablet_hid_report_descriptor));
757 ret = sizeof(qemu_tablet_hid_report_descriptor);
47b2d338 758 } else if (s->kind == USB_KEYBOARD) {
5fafdf24 759 memcpy(data, qemu_keyboard_hid_report_descriptor,
47b2d338
AZ
760 sizeof(qemu_keyboard_hid_report_descriptor));
761 ret = sizeof(qemu_keyboard_hid_report_descriptor);
762 }
763 break;
59ae540c
FB
764 default:
765 goto fail;
766 }
767 break;
768 case GET_REPORT:
e7e73892 769 if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
13f8b97a 770 ret = usb_pointer_poll(s, data, length);
e7e73892 771 } else if (s->kind == USB_KEYBOARD) {
13f8b97a 772 ret = usb_keyboard_poll(s, data, length);
e7e73892
GH
773 }
774 s->changed = s->n > 0;
47b2d338
AZ
775 break;
776 case SET_REPORT:
777 if (s->kind == USB_KEYBOARD)
778 ret = usb_keyboard_write(&s->kbd, data, length);
779 else
780 goto fail;
781 break;
782 case GET_PROTOCOL:
46115ac4 783 if (s->kind != USB_KEYBOARD && s->kind != USB_MOUSE)
47b2d338
AZ
784 goto fail;
785 ret = 1;
786 data[0] = s->protocol;
787 break;
788 case SET_PROTOCOL:
46115ac4 789 if (s->kind != USB_KEYBOARD && s->kind != USB_MOUSE)
47b2d338
AZ
790 goto fail;
791 ret = 0;
792 s->protocol = value;
793 break;
794 case GET_IDLE:
795 ret = 1;
796 data[0] = s->idle;
59ae540c
FB
797 break;
798 case SET_IDLE:
181a29c5 799 s->idle = (uint8_t) (value >> 8);
74475455 800 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
59ae540c
FB
801 ret = 0;
802 break;
803 default:
804 fail:
805 ret = USB_RET_STALL;
806 break;
807 }
808 return ret;
809}
810
47b2d338 811static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
59ae540c 812{
47b2d338 813 USBHIDState *s = (USBHIDState *)dev;
09b26c5e 814 int ret = 0;
59ae540c 815
4d611c9a 816 switch(p->pid) {
59ae540c 817 case USB_TOKEN_IN:
4d611c9a 818 if (p->devep == 1) {
74475455 819 int64_t curtime = qemu_get_clock_ns(vm_clock);
68735b6c 820 if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
117b3ae6 821 return USB_RET_NAK;
68735b6c 822 usb_hid_set_next_idle(s, curtime);
13f8b97a
PB
823 if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
824 ret = usb_pointer_poll(s, p->data, p->len);
13f8b97a
PB
825 }
826 else if (s->kind == USB_KEYBOARD) {
827 ret = usb_keyboard_poll(s, p->data, p->len);
13f8b97a 828 }
42292d4e 829 s->changed = s->n > 0;
59ae540c
FB
830 } else {
831 goto fail;
832 }
833 break;
834 case USB_TOKEN_OUT:
835 default:
836 fail:
837 ret = USB_RET_STALL;
838 break;
839 }
840 return ret;
841}
842
47b2d338 843static void usb_hid_handle_destroy(USBDevice *dev)
059809e4 844{
47b2d338 845 USBHIDState *s = (USBHIDState *)dev;
059809e4 846
46aaebff
JS
847 switch(s->kind) {
848 case USB_KEYBOARD:
849 qemu_remove_kbd_event_handler();
850 break;
851 default:
47b2d338 852 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
46aaebff 853 }
059809e4
FB
854}
855
806b6024 856static int usb_hid_initfn(USBDevice *dev, int kind)
09b26c5e 857{
806b6024 858 USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
a980a065
GH
859
860 usb_desc_init(dev);
806b6024 861 s->kind = kind;
6fef28ee
AL
862
863 if (s->kind == USB_MOUSE) {
13f8b97a 864 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
6fef28ee
AL
865 0, "QEMU USB Mouse");
866 } else if (s->kind == USB_TABLET) {
13f8b97a 867 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
6fef28ee
AL
868 1, "QEMU USB Tablet");
869 }
13f8b97a 870
117b3ae6
PB
871 /* Force poll routine to be run and grab input the first time. */
872 s->changed = 1;
806b6024 873 return 0;
09b26c5e
FB
874}
875
806b6024 876static int usb_tablet_initfn(USBDevice *dev)
59ae540c 877{
806b6024
GH
878 return usb_hid_initfn(dev, USB_TABLET);
879}
59ae540c 880
806b6024
GH
881static int usb_mouse_initfn(USBDevice *dev)
882{
883 return usb_hid_initfn(dev, USB_MOUSE);
884}
59ae540c 885
806b6024
GH
886static int usb_keyboard_initfn(USBDevice *dev)
887{
888 return usb_hid_initfn(dev, USB_KEYBOARD);
889}
59ae540c 890
47e699dc
AZ
891void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
892{
893 USBHIDState *s = (USBHIDState *)dev;
894
895 s->datain_opaque = opaque;
896 s->datain = datain;
897}
806b6024 898
ee59e6b3
GH
899static int usb_hid_post_load(void *opaque, int version_id)
900{
901 USBHIDState *s = opaque;
902
903 if (s->idle) {
74475455 904 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
ee59e6b3
GH
905 }
906 return 0;
907}
908
909static const VMStateDescription vmstate_usb_ptr_queue = {
910 .name = "usb-ptr-queue",
911 .version_id = 1,
912 .minimum_version_id = 1,
913 .fields = (VMStateField []) {
914 VMSTATE_INT32(xdx, USBPointerEvent),
915 VMSTATE_INT32(ydy, USBPointerEvent),
916 VMSTATE_INT32(dz, USBPointerEvent),
917 VMSTATE_INT32(buttons_state, USBPointerEvent),
918 VMSTATE_END_OF_LIST()
919 }
920};
921static const VMStateDescription vmstate_usb_ptr = {
922 .name = "usb-ptr",
923 .version_id = 1,
924 .minimum_version_id = 1,
925 .post_load = usb_hid_post_load,
926 .fields = (VMStateField []) {
927 VMSTATE_USB_DEVICE(dev, USBHIDState),
928 VMSTATE_STRUCT_ARRAY(ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
929 vmstate_usb_ptr_queue, USBPointerEvent),
930 VMSTATE_UINT32(head, USBHIDState),
931 VMSTATE_UINT32(n, USBHIDState),
932 VMSTATE_INT32(protocol, USBHIDState),
933 VMSTATE_UINT8(idle, USBHIDState),
934 VMSTATE_END_OF_LIST()
935 }
936};
937
938static const VMStateDescription vmstate_usb_kbd = {
939 .name = "usb-kbd",
940 .version_id = 1,
941 .minimum_version_id = 1,
942 .post_load = usb_hid_post_load,
943 .fields = (VMStateField []) {
944 VMSTATE_USB_DEVICE(dev, USBHIDState),
945 VMSTATE_UINT32_ARRAY(kbd.keycodes, USBHIDState, QUEUE_LENGTH),
946 VMSTATE_UINT32(head, USBHIDState),
947 VMSTATE_UINT32(n, USBHIDState),
948 VMSTATE_UINT16(kbd.modifiers, USBHIDState),
949 VMSTATE_UINT8(kbd.leds, USBHIDState),
950 VMSTATE_UINT8_ARRAY(kbd.key, USBHIDState, 16),
951 VMSTATE_INT32(kbd.keys, USBHIDState),
952 VMSTATE_INT32(protocol, USBHIDState),
953 VMSTATE_UINT8(idle, USBHIDState),
954 VMSTATE_END_OF_LIST()
955 }
956};
957
806b6024
GH
958static struct USBDeviceInfo hid_info[] = {
959 {
06384698 960 .product_desc = "QEMU USB Tablet",
556cd098 961 .qdev.name = "usb-tablet",
fa7c70c3 962 .usbdevice_name = "tablet",
806b6024 963 .qdev.size = sizeof(USBHIDState),
ee59e6b3 964 .qdev.vmsd = &vmstate_usb_ptr,
0e4e9695 965 .usb_desc = &desc_tablet,
806b6024
GH
966 .init = usb_tablet_initfn,
967 .handle_packet = usb_generic_handle_packet,
968 .handle_reset = usb_mouse_handle_reset,
969 .handle_control = usb_hid_handle_control,
970 .handle_data = usb_hid_handle_data,
971 .handle_destroy = usb_hid_handle_destroy,
972 },{
06384698 973 .product_desc = "QEMU USB Mouse",
556cd098 974 .qdev.name = "usb-mouse",
fa7c70c3 975 .usbdevice_name = "mouse",
806b6024 976 .qdev.size = sizeof(USBHIDState),
ee59e6b3 977 .qdev.vmsd = &vmstate_usb_ptr,
0e4e9695 978 .usb_desc = &desc_mouse,
806b6024
GH
979 .init = usb_mouse_initfn,
980 .handle_packet = usb_generic_handle_packet,
981 .handle_reset = usb_mouse_handle_reset,
982 .handle_control = usb_hid_handle_control,
983 .handle_data = usb_hid_handle_data,
984 .handle_destroy = usb_hid_handle_destroy,
985 },{
06384698 986 .product_desc = "QEMU USB Keyboard",
556cd098 987 .qdev.name = "usb-kbd",
fa7c70c3 988 .usbdevice_name = "keyboard",
806b6024 989 .qdev.size = sizeof(USBHIDState),
ee59e6b3 990 .qdev.vmsd = &vmstate_usb_kbd,
0e4e9695 991 .usb_desc = &desc_keyboard,
806b6024
GH
992 .init = usb_keyboard_initfn,
993 .handle_packet = usb_generic_handle_packet,
994 .handle_reset = usb_keyboard_handle_reset,
995 .handle_control = usb_hid_handle_control,
996 .handle_data = usb_hid_handle_data,
997 .handle_destroy = usb_hid_handle_destroy,
998 },{
999 /* end of list */
1000 }
1001};
1002
1003static void usb_hid_register_devices(void)
1004{
1005 usb_qdev_register_many(hid_info);
1006}
1007device_init(usb_hid_register_devices)