]> git.proxmox.com Git - qemu.git/blame - hw/usb-hid.c
usb-hid: add hid_has_events()
[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
0d878eec
GH
44#define HID_MOUSE 1
45#define HID_TABLET 2
46#define HID_KEYBOARD 3
09b26c5e 47
0d878eec 48typedef struct HIDPointerEvent {
13f8b97a
PB
49 int32_t xdx, ydy; /* relative iff it's a mouse, otherwise absolute */
50 int32_t dz, buttons_state;
0d878eec 51} HIDPointerEvent;
13f8b97a
PB
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
8bde6805
GH
57typedef struct HIDState HIDState;
58typedef void (*HIDEventFunc)(HIDState *s);
59
0d878eec
GH
60typedef struct HIDMouseState {
61 HIDPointerEvent queue[QUEUE_LENGTH];
09b26c5e 62 int mouse_grabbed;
455204eb 63 QEMUPutMouseEntry *eh_entry;
0d878eec 64} HIDMouseState;
59ae540c 65
0d878eec 66typedef struct HIDKeyboardState {
5fae51a9 67 uint32_t keycodes[QUEUE_LENGTH];
47b2d338
AZ
68 uint16_t modifiers;
69 uint8_t leds;
70 uint8_t key[16];
ee59e6b3 71 int32_t keys;
0d878eec 72} HIDKeyboardState;
47b2d338 73
8bde6805 74struct HIDState {
47b2d338 75 union {
0d878eec
GH
76 HIDMouseState ptr;
77 HIDKeyboardState kbd;
47b2d338 78 };
42292d4e
GH
79 uint32_t head; /* index into circular queue */
80 uint32_t n;
47b2d338 81 int kind;
8bde6805
GH
82 HIDEventFunc event;
83};
0d878eec
GH
84
85typedef struct USBHIDState {
86 USBDevice dev;
87 HIDState hid;
ee59e6b3 88 int32_t protocol;
181a29c5 89 uint8_t idle;
68735b6c 90 int64_t next_idle_clock;
47e699dc
AZ
91 void *datain_opaque;
92 void (*datain)(void *);
47b2d338
AZ
93} USBHIDState;
94
0e4e9695
GH
95enum {
96 STR_MANUFACTURER = 1,
97 STR_PRODUCT_MOUSE,
98 STR_PRODUCT_TABLET,
99 STR_PRODUCT_KEYBOARD,
100 STR_SERIALNUMBER,
101 STR_CONFIG_MOUSE,
102 STR_CONFIG_TABLET,
103 STR_CONFIG_KEYBOARD,
59ae540c
FB
104};
105
0e4e9695
GH
106static const USBDescStrings desc_strings = {
107 [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
108 [STR_PRODUCT_MOUSE] = "QEMU USB Mouse",
109 [STR_PRODUCT_TABLET] = "QEMU USB Tablet",
110 [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
7b074a22 111 [STR_SERIALNUMBER] = "42", /* == remote wakeup works */
0e4e9695
GH
112 [STR_CONFIG_MOUSE] = "HID Mouse",
113 [STR_CONFIG_TABLET] = "HID Tablet",
114 [STR_CONFIG_KEYBOARD] = "HID Keyboard",
09b26c5e
FB
115};
116
0e4e9695
GH
117static const USBDescIface desc_iface_mouse = {
118 .bInterfaceNumber = 0,
119 .bNumEndpoints = 1,
120 .bInterfaceClass = USB_CLASS_HID,
121 .bInterfaceSubClass = 0x01, /* boot */
122 .bInterfaceProtocol = 0x02,
123 .ndesc = 1,
124 .descs = (USBDescOther[]) {
125 {
126 /* HID descriptor */
127 .data = (uint8_t[]) {
128 0x09, /* u8 bLength */
129 USB_DT_HID, /* u8 bDescriptorType */
130 0x01, 0x00, /* u16 HID_class */
131 0x00, /* u8 country_code */
132 0x01, /* u8 num_descriptors */
133 USB_DT_REPORT, /* u8 type: Report */
134 52, 0, /* u16 len */
135 },
136 },
137 },
138 .eps = (USBDescEndpoint[]) {
139 {
140 .bEndpointAddress = USB_DIR_IN | 0x01,
141 .bmAttributes = USB_ENDPOINT_XFER_INT,
142 .wMaxPacketSize = 4,
143 .bInterval = 0x0a,
144 },
145 },
59ae540c
FB
146};
147
0e4e9695
GH
148static const USBDescIface desc_iface_tablet = {
149 .bInterfaceNumber = 0,
150 .bNumEndpoints = 1,
151 .bInterfaceClass = USB_CLASS_HID,
0e4e9695
GH
152 .bInterfaceProtocol = 0x02,
153 .ndesc = 1,
154 .descs = (USBDescOther[]) {
155 {
156 /* HID descriptor */
157 .data = (uint8_t[]) {
158 0x09, /* u8 bLength */
159 USB_DT_HID, /* u8 bDescriptorType */
160 0x01, 0x00, /* u16 HID_class */
161 0x00, /* u8 country_code */
162 0x01, /* u8 num_descriptors */
163 USB_DT_REPORT, /* u8 type: Report */
164 74, 0, /* u16 len */
165 },
166 },
167 },
168 .eps = (USBDescEndpoint[]) {
169 {
170 .bEndpointAddress = USB_DIR_IN | 0x01,
171 .bmAttributes = USB_ENDPOINT_XFER_INT,
172 .wMaxPacketSize = 8,
173 .bInterval = 0x0a,
174 },
175 },
176};
177
178static const USBDescIface desc_iface_keyboard = {
179 .bInterfaceNumber = 0,
180 .bNumEndpoints = 1,
181 .bInterfaceClass = USB_CLASS_HID,
182 .bInterfaceSubClass = 0x01, /* boot */
183 .bInterfaceProtocol = 0x01, /* keyboard */
184 .ndesc = 1,
185 .descs = (USBDescOther[]) {
186 {
187 /* HID descriptor */
188 .data = (uint8_t[]) {
189 0x09, /* u8 bLength */
190 USB_DT_HID, /* u8 bDescriptorType */
191 0x11, 0x01, /* u16 HID_class */
192 0x00, /* u8 country_code */
193 0x01, /* u8 num_descriptors */
194 USB_DT_REPORT, /* u8 type: Report */
195 0x3f, 0, /* u16 len */
196 },
197 },
198 },
199 .eps = (USBDescEndpoint[]) {
200 {
201 .bEndpointAddress = USB_DIR_IN | 0x01,
202 .bmAttributes = USB_ENDPOINT_XFER_INT,
203 .wMaxPacketSize = 8,
204 .bInterval = 0x0a,
205 },
206 },
207};
208
209static const USBDescDevice desc_device_mouse = {
210 .bcdUSB = 0x0100,
211 .bMaxPacketSize0 = 8,
212 .bNumConfigurations = 1,
213 .confs = (USBDescConfig[]) {
214 {
215 .bNumInterfaces = 1,
216 .bConfigurationValue = 1,
217 .iConfiguration = STR_CONFIG_MOUSE,
218 .bmAttributes = 0xa0,
219 .bMaxPower = 50,
add75088 220 .nif = 1,
0e4e9695
GH
221 .ifs = &desc_iface_mouse,
222 },
223 },
224};
225
226static const USBDescDevice desc_device_tablet = {
227 .bcdUSB = 0x0100,
228 .bMaxPacketSize0 = 8,
229 .bNumConfigurations = 1,
230 .confs = (USBDescConfig[]) {
231 {
232 .bNumInterfaces = 1,
233 .bConfigurationValue = 1,
234 .iConfiguration = STR_CONFIG_TABLET,
235 .bmAttributes = 0xa0,
236 .bMaxPower = 50,
add75088 237 .nif = 1,
0e4e9695
GH
238 .ifs = &desc_iface_tablet,
239 },
240 },
241};
242
243static const USBDescDevice desc_device_keyboard = {
244 .bcdUSB = 0x0100,
245 .bMaxPacketSize0 = 8,
246 .bNumConfigurations = 1,
247 .confs = (USBDescConfig[]) {
248 {
249 .bNumInterfaces = 1,
250 .bConfigurationValue = 1,
251 .iConfiguration = STR_CONFIG_KEYBOARD,
252 .bmAttributes = 0xa0,
253 .bMaxPower = 50,
add75088 254 .nif = 1,
0e4e9695
GH
255 .ifs = &desc_iface_keyboard,
256 },
257 },
258};
259
260static const USBDesc desc_mouse = {
261 .id = {
262 .idVendor = 0x0627,
263 .idProduct = 0x0001,
264 .bcdDevice = 0,
265 .iManufacturer = STR_MANUFACTURER,
266 .iProduct = STR_PRODUCT_MOUSE,
267 .iSerialNumber = STR_SERIALNUMBER,
268 },
269 .full = &desc_device_mouse,
270 .str = desc_strings,
271};
272
273static const USBDesc desc_tablet = {
274 .id = {
275 .idVendor = 0x0627,
276 .idProduct = 0x0001,
277 .bcdDevice = 0,
278 .iManufacturer = STR_MANUFACTURER,
279 .iProduct = STR_PRODUCT_TABLET,
280 .iSerialNumber = STR_SERIALNUMBER,
281 },
282 .full = &desc_device_tablet,
283 .str = desc_strings,
284};
285
286static const USBDesc desc_keyboard = {
287 .id = {
288 .idVendor = 0x0627,
289 .idProduct = 0x0001,
290 .bcdDevice = 0,
291 .iManufacturer = STR_MANUFACTURER,
292 .iProduct = STR_PRODUCT_KEYBOARD,
293 .iSerialNumber = STR_SERIALNUMBER,
294 },
295 .full = &desc_device_keyboard,
296 .str = desc_strings,
47b2d338
AZ
297};
298
59ae540c 299static const uint8_t qemu_mouse_hid_report_descriptor[] = {
976f8eef
AZ
300 0x05, 0x01, /* Usage Page (Generic Desktop) */
301 0x09, 0x02, /* Usage (Mouse) */
302 0xa1, 0x01, /* Collection (Application) */
303 0x09, 0x01, /* Usage (Pointer) */
304 0xa1, 0x00, /* Collection (Physical) */
305 0x05, 0x09, /* Usage Page (Button) */
306 0x19, 0x01, /* Usage Minimum (1) */
307 0x29, 0x03, /* Usage Maximum (3) */
308 0x15, 0x00, /* Logical Minimum (0) */
309 0x25, 0x01, /* Logical Maximum (1) */
310 0x95, 0x03, /* Report Count (3) */
311 0x75, 0x01, /* Report Size (1) */
312 0x81, 0x02, /* Input (Data, Variable, Absolute) */
313 0x95, 0x01, /* Report Count (1) */
314 0x75, 0x05, /* Report Size (5) */
315 0x81, 0x01, /* Input (Constant) */
316 0x05, 0x01, /* Usage Page (Generic Desktop) */
317 0x09, 0x30, /* Usage (X) */
318 0x09, 0x31, /* Usage (Y) */
319 0x09, 0x38, /* Usage (Wheel) */
320 0x15, 0x81, /* Logical Minimum (-0x7f) */
321 0x25, 0x7f, /* Logical Maximum (0x7f) */
322 0x75, 0x08, /* Report Size (8) */
323 0x95, 0x03, /* Report Count (3) */
324 0x81, 0x06, /* Input (Data, Variable, Relative) */
325 0xc0, /* End Collection */
326 0xc0, /* End Collection */
59ae540c
FB
327};
328
09b26c5e 329static const uint8_t qemu_tablet_hid_report_descriptor[] = {
976f8eef
AZ
330 0x05, 0x01, /* Usage Page (Generic Desktop) */
331 0x09, 0x01, /* Usage (Pointer) */
332 0xa1, 0x01, /* Collection (Application) */
333 0x09, 0x01, /* Usage (Pointer) */
334 0xa1, 0x00, /* Collection (Physical) */
335 0x05, 0x09, /* Usage Page (Button) */
336 0x19, 0x01, /* Usage Minimum (1) */
337 0x29, 0x03, /* Usage Maximum (3) */
338 0x15, 0x00, /* Logical Minimum (0) */
339 0x25, 0x01, /* Logical Maximum (1) */
340 0x95, 0x03, /* Report Count (3) */
341 0x75, 0x01, /* Report Size (1) */
342 0x81, 0x02, /* Input (Data, Variable, Absolute) */
343 0x95, 0x01, /* Report Count (1) */
344 0x75, 0x05, /* Report Size (5) */
345 0x81, 0x01, /* Input (Constant) */
346 0x05, 0x01, /* Usage Page (Generic Desktop) */
347 0x09, 0x30, /* Usage (X) */
348 0x09, 0x31, /* Usage (Y) */
349 0x15, 0x00, /* Logical Minimum (0) */
de5c2d0a 350 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
976f8eef 351 0x35, 0x00, /* Physical Minimum (0) */
de5c2d0a 352 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
976f8eef
AZ
353 0x75, 0x10, /* Report Size (16) */
354 0x95, 0x02, /* Report Count (2) */
355 0x81, 0x02, /* Input (Data, Variable, Absolute) */
356 0x05, 0x01, /* Usage Page (Generic Desktop) */
357 0x09, 0x38, /* Usage (Wheel) */
358 0x15, 0x81, /* Logical Minimum (-0x7f) */
359 0x25, 0x7f, /* Logical Maximum (0x7f) */
360 0x35, 0x00, /* Physical Minimum (same as logical) */
361 0x45, 0x00, /* Physical Maximum (same as logical) */
362 0x75, 0x08, /* Report Size (8) */
363 0x95, 0x01, /* Report Count (1) */
364 0x81, 0x06, /* Input (Data, Variable, Relative) */
365 0xc0, /* End Collection */
366 0xc0, /* End Collection */
09b26c5e
FB
367};
368
47b2d338
AZ
369static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
370 0x05, 0x01, /* Usage Page (Generic Desktop) */
371 0x09, 0x06, /* Usage (Keyboard) */
372 0xa1, 0x01, /* Collection (Application) */
373 0x75, 0x01, /* Report Size (1) */
374 0x95, 0x08, /* Report Count (8) */
375 0x05, 0x07, /* Usage Page (Key Codes) */
376 0x19, 0xe0, /* Usage Minimum (224) */
377 0x29, 0xe7, /* Usage Maximum (231) */
378 0x15, 0x00, /* Logical Minimum (0) */
379 0x25, 0x01, /* Logical Maximum (1) */
380 0x81, 0x02, /* Input (Data, Variable, Absolute) */
381 0x95, 0x01, /* Report Count (1) */
382 0x75, 0x08, /* Report Size (8) */
383 0x81, 0x01, /* Input (Constant) */
384 0x95, 0x05, /* Report Count (5) */
385 0x75, 0x01, /* Report Size (1) */
386 0x05, 0x08, /* Usage Page (LEDs) */
387 0x19, 0x01, /* Usage Minimum (1) */
388 0x29, 0x05, /* Usage Maximum (5) */
389 0x91, 0x02, /* Output (Data, Variable, Absolute) */
390 0x95, 0x01, /* Report Count (1) */
391 0x75, 0x03, /* Report Size (3) */
392 0x91, 0x01, /* Output (Constant) */
393 0x95, 0x06, /* Report Count (6) */
394 0x75, 0x08, /* Report Size (8) */
395 0x15, 0x00, /* Logical Minimum (0) */
396 0x25, 0xff, /* Logical Maximum (255) */
397 0x05, 0x07, /* Usage Page (Key Codes) */
398 0x19, 0x00, /* Usage Minimum (0) */
399 0x29, 0xff, /* Usage Maximum (255) */
400 0x81, 0x00, /* Input (Data, Array) */
401 0xc0, /* End Collection */
402};
403
404#define USB_HID_USAGE_ERROR_ROLLOVER 0x01
405#define USB_HID_USAGE_POSTFAIL 0x02
406#define USB_HID_USAGE_ERROR_UNDEFINED 0x03
407
408/* Indices are QEMU keycodes, values are from HID Usage Table. Indices
409 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
410static const uint8_t usb_hid_usage_keys[0x100] = {
411 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
412 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
413 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
414 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
415 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
416 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
417 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
418 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
419 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
420 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
421 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
422 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
423 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
425 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
427
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 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, 0x54, 0x00, 0x46,
435 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
437 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
438 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
a8fb7ff3 439 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
47b2d338
AZ
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444};
445
38931fa8
GH
446static bool hid_has_events(HIDState *hs)
447{
448 return hs->n > 0;
449}
450
8bde6805 451static void usb_hid_changed(HIDState *hs)
47e699dc 452{
8bde6805 453 USBHIDState *us = container_of(hs, USBHIDState, hid);
47e699dc 454
8bde6805
GH
455 if (us->datain) {
456 us->datain(us->datain_opaque);
457 }
ac57bbb6 458
8bde6805 459 usb_wakeup(&us->dev);
47e699dc
AZ
460}
461
0d878eec
GH
462static void hid_pointer_event_clear(HIDPointerEvent *e, int buttons)
463{
13f8b97a
PB
464 e->xdx = e->ydy = e->dz = 0;
465 e->buttons_state = buttons;
466}
47e699dc 467
0d878eec 468static void hid_pointer_event_combine(HIDPointerEvent *e, int xyrel,
13f8b97a
PB
469 int x1, int y1, int z1) {
470 if (xyrel) {
471 e->xdx += x1;
472 e->ydy += y1;
473 } else {
474 e->xdx = x1;
475 e->ydy = y1;
8534b8ba
JK
476 /* Windows drivers do not like the 0/0 position and ignore such
477 * events. */
478 if (!(x1 | y1)) {
479 x1 = 1;
480 }
13f8b97a
PB
481 }
482 e->dz += z1;
59ae540c
FB
483}
484
8bde6805 485static void hid_pointer_event(void *opaque,
13f8b97a 486 int x1, int y1, int z1, int buttons_state)
09b26c5e 487{
8bde6805 488 HIDState *hs = opaque;
42292d4e 489 unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
13f8b97a
PB
490 unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
491
492 /* We combine events where feasible to keep the queue small. We shouldn't
493 * combine anything with the first event of a particular button state, as
494 * that would change the location of the button state change. When the
495 * queue is empty, a second event is needed because we don't know if
496 * the first event changed the button state. */
42292d4e 497 if (hs->n == QUEUE_LENGTH) {
13f8b97a 498 /* Queue full. Discard old button state, combine motion normally. */
0d878eec 499 hs->ptr.queue[use_slot].buttons_state = buttons_state;
42292d4e 500 } else if (hs->n < 2 ||
0d878eec
GH
501 hs->ptr.queue[use_slot].buttons_state != buttons_state ||
502 hs->ptr.queue[previous_slot].buttons_state !=
503 hs->ptr.queue[use_slot].buttons_state) {
13f8b97a
PB
504 /* Cannot or should not combine, so add an empty item to the queue. */
505 QUEUE_INCR(use_slot);
42292d4e 506 hs->n++;
0d878eec 507 hid_pointer_event_clear(&hs->ptr.queue[use_slot], buttons_state);
13f8b97a 508 }
0d878eec
GH
509 hid_pointer_event_combine(&hs->ptr.queue[use_slot],
510 hs->kind == HID_MOUSE,
13f8b97a 511 x1, y1, z1);
8bde6805 512 hs->event(hs);
09b26c5e
FB
513}
514
8bde6805 515static void hid_keyboard_event(void *opaque, int keycode)
47b2d338 516{
8bde6805 517 HIDState *hs = opaque;
5fae51a9
GH
518 int slot;
519
42292d4e 520 if (hs->n == QUEUE_LENGTH) {
5fae51a9
GH
521 fprintf(stderr, "usb-kbd: warning: key event queue full\n");
522 return;
523 }
42292d4e 524 slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
0d878eec 525 hs->kbd.keycodes[slot] = keycode;
8bde6805 526 hs->event(hs);
5fae51a9
GH
527}
528
0d878eec 529static void hid_keyboard_process_keycode(HIDState *hs)
5fae51a9 530{
47b2d338 531 uint8_t hid_code, key;
5fae51a9
GH
532 int i, keycode, slot;
533
42292d4e 534 if (hs->n == 0) {
5fae51a9
GH
535 return;
536 }
42292d4e 537 slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
0d878eec 538 keycode = hs->kbd.keycodes[slot];
47b2d338
AZ
539
540 key = keycode & 0x7f;
0d878eec
GH
541 hid_code = usb_hid_usage_keys[key | ((hs->kbd.modifiers >> 1) & (1 << 7))];
542 hs->kbd.modifiers &= ~(1 << 8);
47b2d338
AZ
543
544 switch (hid_code) {
545 case 0x00:
546 return;
547
548 case 0xe0:
0d878eec
GH
549 if (hs->kbd.modifiers & (1 << 9)) {
550 hs->kbd.modifiers ^= 3 << 8;
47b2d338
AZ
551 return;
552 }
553 case 0xe1 ... 0xe7:
554 if (keycode & (1 << 7)) {
0d878eec 555 hs->kbd.modifiers &= ~(1 << (hid_code & 0x0f));
47b2d338
AZ
556 return;
557 }
558 case 0xe8 ... 0xef:
0d878eec 559 hs->kbd.modifiers |= 1 << (hid_code & 0x0f);
47b2d338
AZ
560 return;
561 }
562
563 if (keycode & (1 << 7)) {
0d878eec
GH
564 for (i = hs->kbd.keys - 1; i >= 0; i--) {
565 if (hs->kbd.key[i] == hid_code) {
566 hs->kbd.key[i] = hs->kbd.key[-- hs->kbd.keys];
567 hs->kbd.key[hs->kbd.keys] = 0x00;
47e699dc 568 break;
47b2d338 569 }
0d878eec
GH
570 }
571 if (i < 0) {
47e699dc 572 return;
0d878eec 573 }
47b2d338 574 } else {
0d878eec
GH
575 for (i = hs->kbd.keys - 1; i >= 0; i--) {
576 if (hs->kbd.key[i] == hid_code) {
47e699dc 577 break;
0d878eec
GH
578 }
579 }
47e699dc 580 if (i < 0) {
0d878eec
GH
581 if (hs->kbd.keys < sizeof(hs->kbd.key)) {
582 hs->kbd.key[hs->kbd.keys++] = hid_code;
583 }
584 } else {
47e699dc 585 return;
0d878eec 586 }
47b2d338
AZ
587 }
588}
589
59ae540c
FB
590static inline int int_clamp(int val, int vmin, int vmax)
591{
592 if (val < vmin)
593 return vmin;
594 else if (val > vmax)
595 return vmax;
596 else
597 return val;
598}
599
0d878eec 600static int hid_pointer_poll(HIDState *hs, uint8_t *buf, int len)
59ae540c
FB
601{
602 int dx, dy, dz, b, l;
13f8b97a 603 int index;
0d878eec 604 HIDPointerEvent *e;
59ae540c 605
0d878eec
GH
606 if (!hs->ptr.mouse_grabbed) {
607 qemu_activate_mouse_event_handler(hs->ptr.eh_entry);
608 hs->ptr.mouse_grabbed = 1;
09b26c5e 609 }
3b46e624 610
13f8b97a
PB
611 /* When the buffer is empty, return the last event. Relative
612 movements will all be zero. */
42292d4e 613 index = (hs->n ? hs->head : hs->head - 1);
0d878eec 614 e = &hs->ptr.queue[index & QUEUE_MASK];
3b46e624 615
0d878eec 616 if (hs->kind == HID_MOUSE) {
13f8b97a
PB
617 dx = int_clamp(e->xdx, -127, 127);
618 dy = int_clamp(e->ydy, -127, 127);
619 e->xdx -= dx;
620 e->ydy -= dy;
621 } else {
622 dx = e->xdx;
623 dy = e->ydy;
624 }
625 dz = int_clamp(e->dz, -127, 127);
626 e->dz -= dz;
976f8eef 627
59ae540c 628 b = 0;
13f8b97a 629 if (e->buttons_state & MOUSE_EVENT_LBUTTON)
59ae540c 630 b |= 0x01;
13f8b97a 631 if (e->buttons_state & MOUSE_EVENT_RBUTTON)
59ae540c 632 b |= 0x02;
13f8b97a 633 if (e->buttons_state & MOUSE_EVENT_MBUTTON)
59ae540c 634 b |= 0x04;
3b46e624 635
42292d4e 636 if (hs->n &&
13f8b97a 637 !e->dz &&
0d878eec 638 (hs->kind == HID_TABLET || (!e->xdx && !e->ydy))) {
13f8b97a 639 /* that deals with this event */
42292d4e
GH
640 QUEUE_INCR(hs->head);
641 hs->n--;
09b26c5e 642 }
3b46e624 643
09b26c5e
FB
644 /* Appears we have to invert the wheel direction */
645 dz = 0 - dz;
13f8b97a
PB
646 l = 0;
647 switch (hs->kind) {
0d878eec 648 case HID_MOUSE:
13f8b97a
PB
649 if (len > l)
650 buf[l++] = b;
651 if (len > l)
652 buf[l++] = dx;
653 if (len > l)
654 buf[l++] = dy;
655 if (len > l)
656 buf[l++] = dz;
657 break;
09b26c5e 658
0d878eec 659 case HID_TABLET:
13f8b97a
PB
660 if (len > l)
661 buf[l++] = b;
662 if (len > l)
663 buf[l++] = dx & 0xff;
664 if (len > l)
665 buf[l++] = dx >> 8;
666 if (len > l)
667 buf[l++] = dy & 0xff;
668 if (len > l)
669 buf[l++] = dy >> 8;
670 if (len > l)
671 buf[l++] = dz;
672 break;
673
674 default:
675 abort();
676 }
09b26c5e
FB
677
678 return l;
679}
680
0d878eec 681static int hid_keyboard_poll(HIDState *hs, uint8_t *buf, int len)
47b2d338
AZ
682{
683 if (len < 2)
684 return 0;
685
0d878eec 686 hid_keyboard_process_keycode(hs);
5fae51a9 687
0d878eec 688 buf[0] = hs->kbd.modifiers & 0xff;
47b2d338 689 buf[1] = 0;
0d878eec 690 if (hs->kbd.keys > 6) {
47b2d338 691 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
0d878eec
GH
692 } else {
693 memcpy(buf + 2, hs->kbd.key, MIN(8, len) - 2);
694 }
47b2d338
AZ
695
696 return MIN(8, len);
697}
698
0d878eec 699static int hid_keyboard_write(HIDState *hs, uint8_t *buf, int len)
47b2d338
AZ
700{
701 if (len > 0) {
bd87813e 702 int ledstate = 0;
47b2d338
AZ
703 /* 0x01: Num Lock LED
704 * 0x02: Caps Lock LED
705 * 0x04: Scroll Lock LED
706 * 0x08: Compose LED
707 * 0x10: Kana LED */
0d878eec
GH
708 hs->kbd.leds = buf[0];
709 if (hs->kbd.leds & 0x04) {
bd87813e 710 ledstate |= QEMU_SCROLL_LOCK_LED;
0d878eec
GH
711 }
712 if (hs->kbd.leds & 0x01) {
bd87813e 713 ledstate |= QEMU_NUM_LOCK_LED;
0d878eec
GH
714 }
715 if (hs->kbd.leds & 0x02) {
bd87813e 716 ledstate |= QEMU_CAPS_LOCK_LED;
0d878eec 717 }
bd87813e 718 kbd_put_ledstate(ledstate);
47b2d338
AZ
719 }
720 return 0;
721}
722
8bde6805 723static void hid_handle_reset(HIDState *hs)
59ae540c 724{
8bde6805
GH
725 switch (hs->kind) {
726 case HID_KEYBOARD:
727 qemu_add_kbd_event_handler(hid_keyboard_event, hs);
728 memset(hs->kbd.keycodes, 0, sizeof(hs->kbd.keycodes));
729 memset(hs->kbd.key, 0, sizeof(hs->kbd.key));
730 hs->kbd.keys = 0;
731 break;
732 case HID_MOUSE:
733 case HID_TABLET:
734 memset(hs->ptr.queue, 0, sizeof(hs->ptr.queue));
735 break;
736 }
737 hs->head = 0;
738 hs->n = 0;
47b2d338
AZ
739}
740
8bde6805 741static void usb_hid_handle_reset(USBDevice *dev)
47b2d338 742{
0d878eec
GH
743 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
744
8bde6805 745 hid_handle_reset(&us->hid);
0d878eec 746 us->protocol = 1;
38931fa8 747 us->idle = 0;
59ae540c
FB
748}
749
68735b6c
KC
750static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
751{
752 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
753}
754
007fd62f
HG
755static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
756 int request, int value, int index, int length, uint8_t *data)
59ae540c 757{
0d878eec
GH
758 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
759 HIDState *hs = &us->hid;
0e4e9695 760 int ret;
59ae540c 761
007fd62f 762 ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
0e4e9695
GH
763 if (ret >= 0) {
764 return ret;
765 }
59ae540c 766
0e4e9695 767 ret = 0;
0d878eec 768 switch (request) {
59ae540c
FB
769 case DeviceRequest | USB_REQ_GET_INTERFACE:
770 data[0] = 0;
771 ret = 1;
772 break;
773 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
774 ret = 0;
775 break;
776 /* hid specific requests */
777 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
0d878eec 778 switch (value >> 8) {
59ae540c 779 case 0x22:
0d878eec 780 if (hs->kind == HID_MOUSE) {
5fafdf24 781 memcpy(data, qemu_mouse_hid_report_descriptor,
09b26c5e
FB
782 sizeof(qemu_mouse_hid_report_descriptor));
783 ret = sizeof(qemu_mouse_hid_report_descriptor);
0d878eec
GH
784 } else if (hs->kind == HID_TABLET) {
785 memcpy(data, qemu_tablet_hid_report_descriptor,
09b26c5e
FB
786 sizeof(qemu_tablet_hid_report_descriptor));
787 ret = sizeof(qemu_tablet_hid_report_descriptor);
0d878eec 788 } else if (hs->kind == HID_KEYBOARD) {
5fafdf24 789 memcpy(data, qemu_keyboard_hid_report_descriptor,
47b2d338
AZ
790 sizeof(qemu_keyboard_hid_report_descriptor));
791 ret = sizeof(qemu_keyboard_hid_report_descriptor);
792 }
793 break;
59ae540c
FB
794 default:
795 goto fail;
796 }
797 break;
798 case GET_REPORT:
0d878eec
GH
799 if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
800 ret = hid_pointer_poll(hs, data, length);
801 } else if (hs->kind == HID_KEYBOARD) {
802 ret = hid_keyboard_poll(hs, data, length);
e7e73892 803 }
47b2d338
AZ
804 break;
805 case SET_REPORT:
0d878eec
GH
806 if (hs->kind == HID_KEYBOARD) {
807 ret = hid_keyboard_write(hs, data, length);
808 } else {
47b2d338 809 goto fail;
0d878eec 810 }
47b2d338
AZ
811 break;
812 case GET_PROTOCOL:
0d878eec 813 if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
47b2d338 814 goto fail;
0d878eec 815 }
47b2d338 816 ret = 1;
0d878eec 817 data[0] = us->protocol;
47b2d338
AZ
818 break;
819 case SET_PROTOCOL:
0d878eec 820 if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
47b2d338 821 goto fail;
0d878eec 822 }
47b2d338 823 ret = 0;
0d878eec 824 us->protocol = value;
47b2d338
AZ
825 break;
826 case GET_IDLE:
827 ret = 1;
0d878eec 828 data[0] = us->idle;
59ae540c
FB
829 break;
830 case SET_IDLE:
0d878eec
GH
831 us->idle = (uint8_t) (value >> 8);
832 usb_hid_set_next_idle(us, qemu_get_clock_ns(vm_clock));
59ae540c
FB
833 ret = 0;
834 break;
835 default:
836 fail:
837 ret = USB_RET_STALL;
838 break;
839 }
840 return ret;
841}
842
47b2d338 843static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
59ae540c 844{
0d878eec
GH
845 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
846 HIDState *hs = &us->hid;
4f4321c1 847 uint8_t buf[p->iov.size];
09b26c5e 848 int ret = 0;
59ae540c 849
0d878eec 850 switch (p->pid) {
59ae540c 851 case USB_TOKEN_IN:
4d611c9a 852 if (p->devep == 1) {
74475455 853 int64_t curtime = qemu_get_clock_ns(vm_clock);
38931fa8 854 if (!hid_has_events(hs) &&
0d878eec 855 (!us->idle || us->next_idle_clock - curtime > 0)) {
117b3ae6 856 return USB_RET_NAK;
13f8b97a 857 }
0d878eec
GH
858 usb_hid_set_next_idle(us, curtime);
859 if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
860 ret = hid_pointer_poll(hs, buf, p->iov.size);
861 } else if (hs->kind == HID_KEYBOARD) {
862 ret = hid_keyboard_poll(hs, buf, p->iov.size);
13f8b97a 863 }
4f4321c1 864 usb_packet_copy(p, buf, ret);
59ae540c
FB
865 } else {
866 goto fail;
867 }
868 break;
869 case USB_TOKEN_OUT:
870 default:
871 fail:
872 ret = USB_RET_STALL;
873 break;
874 }
875 return ret;
876}
877
8bde6805 878static void hid_free(HIDState *hs)
059809e4 879{
8bde6805 880 switch (hs->kind) {
0d878eec 881 case HID_KEYBOARD:
46aaebff
JS
882 qemu_remove_kbd_event_handler();
883 break;
8bde6805
GH
884 case HID_MOUSE:
885 case HID_TABLET:
886 qemu_remove_mouse_event_handler(hs->ptr.eh_entry);
887 break;
46aaebff 888 }
059809e4
FB
889}
890
8bde6805 891static void usb_hid_handle_destroy(USBDevice *dev)
09b26c5e 892{
0d878eec 893 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
a980a065 894
8bde6805
GH
895 hid_free(&us->hid);
896}
897
898static void hid_init(HIDState *hs, int kind, HIDEventFunc event)
899{
0d878eec 900 hs->kind = kind;
8bde6805 901 hs->event = event;
0d878eec
GH
902
903 if (hs->kind == HID_MOUSE) {
8bde6805 904 hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
0d878eec
GH
905 0, "QEMU HID Mouse");
906 } else if (hs->kind == HID_TABLET) {
8bde6805 907 hs->ptr.eh_entry = qemu_add_mouse_event_handler(hid_pointer_event, hs,
0d878eec 908 1, "QEMU HID Tablet");
6fef28ee 909 }
8bde6805
GH
910}
911
912static int usb_hid_initfn(USBDevice *dev, int kind)
913{
914 USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
915
916 usb_desc_init(dev);
917 hid_init(&us->hid, kind, usb_hid_changed);
806b6024 918 return 0;
09b26c5e
FB
919}
920
806b6024 921static int usb_tablet_initfn(USBDevice *dev)
59ae540c 922{
0d878eec 923 return usb_hid_initfn(dev, HID_TABLET);
806b6024 924}
59ae540c 925
806b6024
GH
926static int usb_mouse_initfn(USBDevice *dev)
927{
0d878eec 928 return usb_hid_initfn(dev, HID_MOUSE);
806b6024 929}
59ae540c 930
806b6024
GH
931static int usb_keyboard_initfn(USBDevice *dev)
932{
0d878eec 933 return usb_hid_initfn(dev, HID_KEYBOARD);
806b6024 934}
59ae540c 935
47e699dc
AZ
936void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
937{
938 USBHIDState *s = (USBHIDState *)dev;
939
940 s->datain_opaque = opaque;
941 s->datain = datain;
942}
806b6024 943
ee59e6b3
GH
944static int usb_hid_post_load(void *opaque, int version_id)
945{
946 USBHIDState *s = opaque;
947
948 if (s->idle) {
74475455 949 usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
ee59e6b3
GH
950 }
951 return 0;
952}
953
954static const VMStateDescription vmstate_usb_ptr_queue = {
955 .name = "usb-ptr-queue",
956 .version_id = 1,
957 .minimum_version_id = 1,
958 .fields = (VMStateField []) {
0d878eec
GH
959 VMSTATE_INT32(xdx, HIDPointerEvent),
960 VMSTATE_INT32(ydy, HIDPointerEvent),
961 VMSTATE_INT32(dz, HIDPointerEvent),
962 VMSTATE_INT32(buttons_state, HIDPointerEvent),
ee59e6b3
GH
963 VMSTATE_END_OF_LIST()
964 }
965};
966static const VMStateDescription vmstate_usb_ptr = {
967 .name = "usb-ptr",
968 .version_id = 1,
969 .minimum_version_id = 1,
970 .post_load = usb_hid_post_load,
971 .fields = (VMStateField []) {
972 VMSTATE_USB_DEVICE(dev, USBHIDState),
0d878eec
GH
973 VMSTATE_STRUCT_ARRAY(hid.ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
974 vmstate_usb_ptr_queue, HIDPointerEvent),
975 VMSTATE_UINT32(hid.head, USBHIDState),
976 VMSTATE_UINT32(hid.n, USBHIDState),
ee59e6b3
GH
977 VMSTATE_INT32(protocol, USBHIDState),
978 VMSTATE_UINT8(idle, USBHIDState),
979 VMSTATE_END_OF_LIST()
980 }
981};
982
983static const VMStateDescription vmstate_usb_kbd = {
984 .name = "usb-kbd",
985 .version_id = 1,
986 .minimum_version_id = 1,
987 .post_load = usb_hid_post_load,
988 .fields = (VMStateField []) {
989 VMSTATE_USB_DEVICE(dev, USBHIDState),
0d878eec
GH
990 VMSTATE_UINT32_ARRAY(hid.kbd.keycodes, USBHIDState, QUEUE_LENGTH),
991 VMSTATE_UINT32(hid.head, USBHIDState),
992 VMSTATE_UINT32(hid.n, USBHIDState),
993 VMSTATE_UINT16(hid.kbd.modifiers, USBHIDState),
994 VMSTATE_UINT8(hid.kbd.leds, USBHIDState),
995 VMSTATE_UINT8_ARRAY(hid.kbd.key, USBHIDState, 16),
996 VMSTATE_INT32(hid.kbd.keys, USBHIDState),
ee59e6b3
GH
997 VMSTATE_INT32(protocol, USBHIDState),
998 VMSTATE_UINT8(idle, USBHIDState),
999 VMSTATE_END_OF_LIST()
1000 }
1001};
1002
806b6024
GH
1003static struct USBDeviceInfo hid_info[] = {
1004 {
06384698 1005 .product_desc = "QEMU USB Tablet",
556cd098 1006 .qdev.name = "usb-tablet",
fa7c70c3 1007 .usbdevice_name = "tablet",
806b6024 1008 .qdev.size = sizeof(USBHIDState),
ee59e6b3 1009 .qdev.vmsd = &vmstate_usb_ptr,
0e4e9695 1010 .usb_desc = &desc_tablet,
806b6024
GH
1011 .init = usb_tablet_initfn,
1012 .handle_packet = usb_generic_handle_packet,
8bde6805 1013 .handle_reset = usb_hid_handle_reset,
806b6024
GH
1014 .handle_control = usb_hid_handle_control,
1015 .handle_data = usb_hid_handle_data,
1016 .handle_destroy = usb_hid_handle_destroy,
1017 },{
06384698 1018 .product_desc = "QEMU USB Mouse",
556cd098 1019 .qdev.name = "usb-mouse",
fa7c70c3 1020 .usbdevice_name = "mouse",
806b6024 1021 .qdev.size = sizeof(USBHIDState),
ee59e6b3 1022 .qdev.vmsd = &vmstate_usb_ptr,
0e4e9695 1023 .usb_desc = &desc_mouse,
806b6024
GH
1024 .init = usb_mouse_initfn,
1025 .handle_packet = usb_generic_handle_packet,
8bde6805 1026 .handle_reset = usb_hid_handle_reset,
806b6024
GH
1027 .handle_control = usb_hid_handle_control,
1028 .handle_data = usb_hid_handle_data,
1029 .handle_destroy = usb_hid_handle_destroy,
1030 },{
06384698 1031 .product_desc = "QEMU USB Keyboard",
556cd098 1032 .qdev.name = "usb-kbd",
fa7c70c3 1033 .usbdevice_name = "keyboard",
806b6024 1034 .qdev.size = sizeof(USBHIDState),
ee59e6b3 1035 .qdev.vmsd = &vmstate_usb_kbd,
0e4e9695 1036 .usb_desc = &desc_keyboard,
806b6024
GH
1037 .init = usb_keyboard_initfn,
1038 .handle_packet = usb_generic_handle_packet,
8bde6805 1039 .handle_reset = usb_hid_handle_reset,
806b6024
GH
1040 .handle_control = usb_hid_handle_control,
1041 .handle_data = usb_hid_handle_data,
1042 .handle_destroy = usb_hid_handle_destroy,
1043 },{
1044 /* end of list */
1045 }
1046};
1047
1048static void usb_hid_register_devices(void)
1049{
1050 usb_qdev_register_many(hid_info);
1051}
1052device_init(usb_hid_register_devices)