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