]> git.proxmox.com Git - qemu.git/blame - hw/usb-hid.c
usb: hid: remote wakeup support.
[qemu.git] / hw / usb-hid.c
CommitLineData
59ae540c
FB
1/*
2 * QEMU USB HID devices
5fafdf24 3 *
59ae540c 4 * Copyright (c) 2005 Fabrice Bellard
47b2d338 5 * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com)
5fafdf24 6 *
59ae540c
FB
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
87ecb68b
PB
25#include "hw.h"
26#include "console.h"
27#include "usb.h"
0e4e9695 28#include "usb-desc.h"
666daa68 29#include "sysemu.h"
59ae540c
FB
30
31/* HID interface requests */
32#define GET_REPORT 0xa101
33#define GET_IDLE 0xa102
34#define GET_PROTOCOL 0xa103
47b2d338 35#define SET_REPORT 0x2109
59ae540c
FB
36#define SET_IDLE 0x210a
37#define SET_PROTOCOL 0x210b
38
47b2d338
AZ
39/* HID descriptor types */
40#define USB_DT_HID 0x21
41#define USB_DT_REPORT 0x22
42#define USB_DT_PHY 0x23
43
44#define USB_MOUSE 1
45#define USB_TABLET 2
46#define USB_KEYBOARD 3
09b26c5e 47
59ae540c 48typedef struct USBMouseState {
59ae540c 49 int dx, dy, dz, buttons_state;
09b26c5e 50 int x, y;
09b26c5e 51 int mouse_grabbed;
455204eb 52 QEMUPutMouseEntry *eh_entry;
59ae540c
FB
53} USBMouseState;
54
47b2d338
AZ
55typedef struct USBKeyboardState {
56 uint16_t modifiers;
57 uint8_t leds;
58 uint8_t key[16];
59 int keys;
60} USBKeyboardState;
61
62typedef struct USBHIDState {
63 USBDevice dev;
64 union {
65 USBMouseState ptr;
66 USBKeyboardState kbd;
67 };
68 int kind;
69 int protocol;
181a29c5 70 uint8_t idle;
68735b6c 71 int64_t next_idle_clock;
117b3ae6 72 int changed;
47e699dc
AZ
73 void *datain_opaque;
74 void (*datain)(void *);
47b2d338
AZ
75} USBHIDState;
76
0e4e9695
GH
77enum {
78 STR_MANUFACTURER = 1,
79 STR_PRODUCT_MOUSE,
80 STR_PRODUCT_TABLET,
81 STR_PRODUCT_KEYBOARD,
82 STR_SERIALNUMBER,
83 STR_CONFIG_MOUSE,
84 STR_CONFIG_TABLET,
85 STR_CONFIG_KEYBOARD,
59ae540c
FB
86};
87
0e4e9695
GH
88static const USBDescStrings desc_strings = {
89 [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
90 [STR_PRODUCT_MOUSE] = "QEMU USB Mouse",
91 [STR_PRODUCT_TABLET] = "QEMU USB Tablet",
92 [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
93 [STR_SERIALNUMBER] = "1",
94 [STR_CONFIG_MOUSE] = "HID Mouse",
95 [STR_CONFIG_TABLET] = "HID Tablet",
96 [STR_CONFIG_KEYBOARD] = "HID Keyboard",
09b26c5e
FB
97};
98
0e4e9695
GH
99static const USBDescIface desc_iface_mouse = {
100 .bInterfaceNumber = 0,
101 .bNumEndpoints = 1,
102 .bInterfaceClass = USB_CLASS_HID,
103 .bInterfaceSubClass = 0x01, /* boot */
104 .bInterfaceProtocol = 0x02,
105 .ndesc = 1,
106 .descs = (USBDescOther[]) {
107 {
108 /* HID descriptor */
109 .data = (uint8_t[]) {
110 0x09, /* u8 bLength */
111 USB_DT_HID, /* u8 bDescriptorType */
112 0x01, 0x00, /* u16 HID_class */
113 0x00, /* u8 country_code */
114 0x01, /* u8 num_descriptors */
115 USB_DT_REPORT, /* u8 type: Report */
116 52, 0, /* u16 len */
117 },
118 },
119 },
120 .eps = (USBDescEndpoint[]) {
121 {
122 .bEndpointAddress = USB_DIR_IN | 0x01,
123 .bmAttributes = USB_ENDPOINT_XFER_INT,
124 .wMaxPacketSize = 4,
125 .bInterval = 0x0a,
126 },
127 },
59ae540c
FB
128};
129
0e4e9695
GH
130static const USBDescIface desc_iface_tablet = {
131 .bInterfaceNumber = 0,
132 .bNumEndpoints = 1,
133 .bInterfaceClass = USB_CLASS_HID,
134 .bInterfaceSubClass = 0x01, /* boot */
135 .bInterfaceProtocol = 0x02,
136 .ndesc = 1,
137 .descs = (USBDescOther[]) {
138 {
139 /* HID descriptor */
140 .data = (uint8_t[]) {
141 0x09, /* u8 bLength */
142 USB_DT_HID, /* u8 bDescriptorType */
143 0x01, 0x00, /* u16 HID_class */
144 0x00, /* u8 country_code */
145 0x01, /* u8 num_descriptors */
146 USB_DT_REPORT, /* u8 type: Report */
147 74, 0, /* u16 len */
148 },
149 },
150 },
151 .eps = (USBDescEndpoint[]) {
152 {
153 .bEndpointAddress = USB_DIR_IN | 0x01,
154 .bmAttributes = USB_ENDPOINT_XFER_INT,
155 .wMaxPacketSize = 8,
156 .bInterval = 0x0a,
157 },
158 },
159};
160
161static const USBDescIface desc_iface_keyboard = {
162 .bInterfaceNumber = 0,
163 .bNumEndpoints = 1,
164 .bInterfaceClass = USB_CLASS_HID,
165 .bInterfaceSubClass = 0x01, /* boot */
166 .bInterfaceProtocol = 0x01, /* keyboard */
167 .ndesc = 1,
168 .descs = (USBDescOther[]) {
169 {
170 /* HID descriptor */
171 .data = (uint8_t[]) {
172 0x09, /* u8 bLength */
173 USB_DT_HID, /* u8 bDescriptorType */
174 0x11, 0x01, /* u16 HID_class */
175 0x00, /* u8 country_code */
176 0x01, /* u8 num_descriptors */
177 USB_DT_REPORT, /* u8 type: Report */
178 0x3f, 0, /* u16 len */
179 },
180 },
181 },
182 .eps = (USBDescEndpoint[]) {
183 {
184 .bEndpointAddress = USB_DIR_IN | 0x01,
185 .bmAttributes = USB_ENDPOINT_XFER_INT,
186 .wMaxPacketSize = 8,
187 .bInterval = 0x0a,
188 },
189 },
190};
191
192static const USBDescDevice desc_device_mouse = {
193 .bcdUSB = 0x0100,
194 .bMaxPacketSize0 = 8,
195 .bNumConfigurations = 1,
196 .confs = (USBDescConfig[]) {
197 {
198 .bNumInterfaces = 1,
199 .bConfigurationValue = 1,
200 .iConfiguration = STR_CONFIG_MOUSE,
201 .bmAttributes = 0xa0,
202 .bMaxPower = 50,
203 .ifs = &desc_iface_mouse,
204 },
205 },
206};
207
208static const USBDescDevice desc_device_tablet = {
209 .bcdUSB = 0x0100,
210 .bMaxPacketSize0 = 8,
211 .bNumConfigurations = 1,
212 .confs = (USBDescConfig[]) {
213 {
214 .bNumInterfaces = 1,
215 .bConfigurationValue = 1,
216 .iConfiguration = STR_CONFIG_TABLET,
217 .bmAttributes = 0xa0,
218 .bMaxPower = 50,
219 .ifs = &desc_iface_tablet,
220 },
221 },
222};
223
224static const USBDescDevice desc_device_keyboard = {
225 .bcdUSB = 0x0100,
226 .bMaxPacketSize0 = 8,
227 .bNumConfigurations = 1,
228 .confs = (USBDescConfig[]) {
229 {
230 .bNumInterfaces = 1,
231 .bConfigurationValue = 1,
232 .iConfiguration = STR_CONFIG_KEYBOARD,
233 .bmAttributes = 0xa0,
234 .bMaxPower = 50,
235 .ifs = &desc_iface_keyboard,
236 },
237 },
238};
239
240static const USBDesc desc_mouse = {
241 .id = {
242 .idVendor = 0x0627,
243 .idProduct = 0x0001,
244 .bcdDevice = 0,
245 .iManufacturer = STR_MANUFACTURER,
246 .iProduct = STR_PRODUCT_MOUSE,
247 .iSerialNumber = STR_SERIALNUMBER,
248 },
249 .full = &desc_device_mouse,
250 .str = desc_strings,
251};
252
253static const USBDesc desc_tablet = {
254 .id = {
255 .idVendor = 0x0627,
256 .idProduct = 0x0001,
257 .bcdDevice = 0,
258 .iManufacturer = STR_MANUFACTURER,
259 .iProduct = STR_PRODUCT_TABLET,
260 .iSerialNumber = STR_SERIALNUMBER,
261 },
262 .full = &desc_device_tablet,
263 .str = desc_strings,
264};
265
266static const USBDesc desc_keyboard = {
267 .id = {
268 .idVendor = 0x0627,
269 .idProduct = 0x0001,
270 .bcdDevice = 0,
271 .iManufacturer = STR_MANUFACTURER,
272 .iProduct = STR_PRODUCT_KEYBOARD,
273 .iSerialNumber = STR_SERIALNUMBER,
274 },
275 .full = &desc_device_keyboard,
276 .str = desc_strings,
47b2d338
AZ
277};
278
59ae540c 279static const uint8_t qemu_mouse_hid_report_descriptor[] = {
976f8eef
AZ
280 0x05, 0x01, /* Usage Page (Generic Desktop) */
281 0x09, 0x02, /* Usage (Mouse) */
282 0xa1, 0x01, /* Collection (Application) */
283 0x09, 0x01, /* Usage (Pointer) */
284 0xa1, 0x00, /* Collection (Physical) */
285 0x05, 0x09, /* Usage Page (Button) */
286 0x19, 0x01, /* Usage Minimum (1) */
287 0x29, 0x03, /* Usage Maximum (3) */
288 0x15, 0x00, /* Logical Minimum (0) */
289 0x25, 0x01, /* Logical Maximum (1) */
290 0x95, 0x03, /* Report Count (3) */
291 0x75, 0x01, /* Report Size (1) */
292 0x81, 0x02, /* Input (Data, Variable, Absolute) */
293 0x95, 0x01, /* Report Count (1) */
294 0x75, 0x05, /* Report Size (5) */
295 0x81, 0x01, /* Input (Constant) */
296 0x05, 0x01, /* Usage Page (Generic Desktop) */
297 0x09, 0x30, /* Usage (X) */
298 0x09, 0x31, /* Usage (Y) */
299 0x09, 0x38, /* Usage (Wheel) */
300 0x15, 0x81, /* Logical Minimum (-0x7f) */
301 0x25, 0x7f, /* Logical Maximum (0x7f) */
302 0x75, 0x08, /* Report Size (8) */
303 0x95, 0x03, /* Report Count (3) */
304 0x81, 0x06, /* Input (Data, Variable, Relative) */
305 0xc0, /* End Collection */
306 0xc0, /* End Collection */
59ae540c
FB
307};
308
09b26c5e 309static const uint8_t qemu_tablet_hid_report_descriptor[] = {
976f8eef
AZ
310 0x05, 0x01, /* Usage Page (Generic Desktop) */
311 0x09, 0x01, /* Usage (Pointer) */
312 0xa1, 0x01, /* Collection (Application) */
313 0x09, 0x01, /* Usage (Pointer) */
314 0xa1, 0x00, /* Collection (Physical) */
315 0x05, 0x09, /* Usage Page (Button) */
316 0x19, 0x01, /* Usage Minimum (1) */
317 0x29, 0x03, /* Usage Maximum (3) */
318 0x15, 0x00, /* Logical Minimum (0) */
319 0x25, 0x01, /* Logical Maximum (1) */
320 0x95, 0x03, /* Report Count (3) */
321 0x75, 0x01, /* Report Size (1) */
322 0x81, 0x02, /* Input (Data, Variable, Absolute) */
323 0x95, 0x01, /* Report Count (1) */
324 0x75, 0x05, /* Report Size (5) */
325 0x81, 0x01, /* Input (Constant) */
326 0x05, 0x01, /* Usage Page (Generic Desktop) */
327 0x09, 0x30, /* Usage (X) */
328 0x09, 0x31, /* Usage (Y) */
329 0x15, 0x00, /* Logical Minimum (0) */
de5c2d0a 330 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
976f8eef 331 0x35, 0x00, /* Physical Minimum (0) */
de5c2d0a 332 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
976f8eef
AZ
333 0x75, 0x10, /* Report Size (16) */
334 0x95, 0x02, /* Report Count (2) */
335 0x81, 0x02, /* Input (Data, Variable, Absolute) */
336 0x05, 0x01, /* Usage Page (Generic Desktop) */
337 0x09, 0x38, /* Usage (Wheel) */
338 0x15, 0x81, /* Logical Minimum (-0x7f) */
339 0x25, 0x7f, /* Logical Maximum (0x7f) */
340 0x35, 0x00, /* Physical Minimum (same as logical) */
341 0x45, 0x00, /* Physical Maximum (same as logical) */
342 0x75, 0x08, /* Report Size (8) */
343 0x95, 0x01, /* Report Count (1) */
344 0x81, 0x06, /* Input (Data, Variable, Relative) */
345 0xc0, /* End Collection */
346 0xc0, /* End Collection */
09b26c5e
FB
347};
348
47b2d338
AZ
349static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
350 0x05, 0x01, /* Usage Page (Generic Desktop) */
351 0x09, 0x06, /* Usage (Keyboard) */
352 0xa1, 0x01, /* Collection (Application) */
353 0x75, 0x01, /* Report Size (1) */
354 0x95, 0x08, /* Report Count (8) */
355 0x05, 0x07, /* Usage Page (Key Codes) */
356 0x19, 0xe0, /* Usage Minimum (224) */
357 0x29, 0xe7, /* Usage Maximum (231) */
358 0x15, 0x00, /* Logical Minimum (0) */
359 0x25, 0x01, /* Logical Maximum (1) */
360 0x81, 0x02, /* Input (Data, Variable, Absolute) */
361 0x95, 0x01, /* Report Count (1) */
362 0x75, 0x08, /* Report Size (8) */
363 0x81, 0x01, /* Input (Constant) */
364 0x95, 0x05, /* Report Count (5) */
365 0x75, 0x01, /* Report Size (1) */
366 0x05, 0x08, /* Usage Page (LEDs) */
367 0x19, 0x01, /* Usage Minimum (1) */
368 0x29, 0x05, /* Usage Maximum (5) */
369 0x91, 0x02, /* Output (Data, Variable, Absolute) */
370 0x95, 0x01, /* Report Count (1) */
371 0x75, 0x03, /* Report Size (3) */
372 0x91, 0x01, /* Output (Constant) */
373 0x95, 0x06, /* Report Count (6) */
374 0x75, 0x08, /* Report Size (8) */
375 0x15, 0x00, /* Logical Minimum (0) */
376 0x25, 0xff, /* Logical Maximum (255) */
377 0x05, 0x07, /* Usage Page (Key Codes) */
378 0x19, 0x00, /* Usage Minimum (0) */
379 0x29, 0xff, /* Usage Maximum (255) */
380 0x81, 0x00, /* Input (Data, Array) */
381 0xc0, /* End Collection */
382};
383
384#define USB_HID_USAGE_ERROR_ROLLOVER 0x01
385#define USB_HID_USAGE_POSTFAIL 0x02
386#define USB_HID_USAGE_ERROR_UNDEFINED 0x03
387
388/* Indices are QEMU keycodes, values are from HID Usage Table. Indices
389 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
390static const uint8_t usb_hid_usage_keys[0x100] = {
391 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
392 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
393 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
394 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
395 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
396 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
397 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
398 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
399 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
400 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
401 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
402 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
403 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
404 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
407
408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
415 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
417 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
418 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424};
425
47e699dc
AZ
426static void usb_hid_changed(USBHIDState *hs)
427{
428 hs->changed = 1;
429
430 if (hs->datain)
431 hs->datain(hs->datain_opaque);
ac57bbb6
GH
432
433 usb_wakeup(&hs->dev);
47e699dc
AZ
434}
435
59ae540c
FB
436static void usb_mouse_event(void *opaque,
437 int dx1, int dy1, int dz1, int buttons_state)
438{
117b3ae6
PB
439 USBHIDState *hs = opaque;
440 USBMouseState *s = &hs->ptr;
59ae540c
FB
441
442 s->dx += dx1;
443 s->dy += dy1;
444 s->dz += dz1;
445 s->buttons_state = buttons_state;
47e699dc
AZ
446
447 usb_hid_changed(hs);
59ae540c
FB
448}
449
09b26c5e
FB
450static void usb_tablet_event(void *opaque,
451 int x, int y, int dz, int buttons_state)
452{
117b3ae6
PB
453 USBHIDState *hs = opaque;
454 USBMouseState *s = &hs->ptr;
09b26c5e
FB
455
456 s->x = x;
457 s->y = y;
458 s->dz += dz;
459 s->buttons_state = buttons_state;
47e699dc
AZ
460
461 usb_hid_changed(hs);
09b26c5e
FB
462}
463
47b2d338
AZ
464static void usb_keyboard_event(void *opaque, int keycode)
465{
117b3ae6
PB
466 USBHIDState *hs = opaque;
467 USBKeyboardState *s = &hs->kbd;
47b2d338
AZ
468 uint8_t hid_code, key;
469 int i;
470
471 key = keycode & 0x7f;
472 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
473 s->modifiers &= ~(1 << 8);
474
475 switch (hid_code) {
476 case 0x00:
477 return;
478
479 case 0xe0:
480 if (s->modifiers & (1 << 9)) {
481 s->modifiers ^= 3 << 8;
482 return;
483 }
484 case 0xe1 ... 0xe7:
485 if (keycode & (1 << 7)) {
486 s->modifiers &= ~(1 << (hid_code & 0x0f));
487 return;
488 }
489 case 0xe8 ... 0xef:
490 s->modifiers |= 1 << (hid_code & 0x0f);
491 return;
492 }
493
494 if (keycode & (1 << 7)) {
495 for (i = s->keys - 1; i >= 0; i --)
496 if (s->key[i] == hid_code) {
497 s->key[i] = s->key[-- s->keys];
498 s->key[s->keys] = 0x00;
47e699dc
AZ
499 usb_hid_changed(hs);
500 break;
47b2d338 501 }
47e699dc
AZ
502 if (i < 0)
503 return;
47b2d338
AZ
504 } else {
505 for (i = s->keys - 1; i >= 0; i --)
506 if (s->key[i] == hid_code)
47e699dc
AZ
507 break;
508 if (i < 0) {
509 if (s->keys < sizeof(s->key))
510 s->key[s->keys ++] = hid_code;
511 } else
512 return;
47b2d338 513 }
47e699dc
AZ
514
515 usb_hid_changed(hs);
47b2d338
AZ
516}
517
59ae540c
FB
518static inline int int_clamp(int val, int vmin, int vmax)
519{
520 if (val < vmin)
521 return vmin;
522 else if (val > vmax)
523 return vmax;
524 else
525 return val;
526}
527
117b3ae6 528static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
59ae540c
FB
529{
530 int dx, dy, dz, b, l;
117b3ae6 531 USBMouseState *s = &hs->ptr;
59ae540c 532
09b26c5e 533 if (!s->mouse_grabbed) {
6fef28ee 534 qemu_activate_mouse_event_handler(s->eh_entry);
09b26c5e
FB
535 s->mouse_grabbed = 1;
536 }
3b46e624 537
976f8eef
AZ
538 dx = int_clamp(s->dx, -127, 127);
539 dy = int_clamp(s->dy, -127, 127);
540 dz = int_clamp(s->dz, -127, 127);
59ae540c
FB
541
542 s->dx -= dx;
543 s->dy -= dy;
544 s->dz -= dz;
3b46e624 545
976f8eef
AZ
546 /* Appears we have to invert the wheel direction */
547 dz = 0 - dz;
548
59ae540c
FB
549 b = 0;
550 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
551 b |= 0x01;
552 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
553 b |= 0x02;
554 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
555 b |= 0x04;
3b46e624 556
c21c583a
AZ
557 l = 0;
558 if (len > l)
559 buf[l ++] = b;
560 if (len > l)
561 buf[l ++] = dx;
562 if (len > l)
563 buf[l ++] = dy;
564 if (len > l)
565 buf[l ++] = dz;
59ae540c
FB
566 return l;
567}
568
117b3ae6 569static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
09b26c5e
FB
570{
571 int dz, b, l;
117b3ae6 572 USBMouseState *s = &hs->ptr;
09b26c5e
FB
573
574 if (!s->mouse_grabbed) {
6fef28ee 575 qemu_activate_mouse_event_handler(s->eh_entry);
09b26c5e
FB
576 s->mouse_grabbed = 1;
577 }
3b46e624 578
976f8eef 579 dz = int_clamp(s->dz, -127, 127);
09b26c5e
FB
580 s->dz -= dz;
581
582 /* Appears we have to invert the wheel direction */
583 dz = 0 - dz;
584 b = 0;
585 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
586 b |= 0x01;
587 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
588 b |= 0x02;
589 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
590 b |= 0x04;
591
592 buf[0] = b;
593 buf[1] = s->x & 0xff;
594 buf[2] = s->x >> 8;
595 buf[3] = s->y & 0xff;
596 buf[4] = s->y >> 8;
597 buf[5] = dz;
598 l = 6;
599
600 return l;
601}
602
47b2d338
AZ
603static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
604{
605 if (len < 2)
606 return 0;
607
608 buf[0] = s->modifiers & 0xff;
609 buf[1] = 0;
610 if (s->keys > 6)
611 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
612 else
613 memcpy(buf + 2, s->key, MIN(8, len) - 2);
614
615 return MIN(8, len);
616}
617
618static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
619{
620 if (len > 0) {
bd87813e 621 int ledstate = 0;
47b2d338
AZ
622 /* 0x01: Num Lock LED
623 * 0x02: Caps Lock LED
624 * 0x04: Scroll Lock LED
625 * 0x08: Compose LED
626 * 0x10: Kana LED */
627 s->leds = buf[0];
bd87813e
GH
628 if (s->leds & 0x04)
629 ledstate |= QEMU_SCROLL_LOCK_LED;
630 if (s->leds & 0x01)
631 ledstate |= QEMU_NUM_LOCK_LED;
632 if (s->leds & 0x02)
633 ledstate |= QEMU_CAPS_LOCK_LED;
634 kbd_put_ledstate(ledstate);
47b2d338
AZ
635 }
636 return 0;
637}
638
059809e4 639static void usb_mouse_handle_reset(USBDevice *dev)
59ae540c 640{
47b2d338
AZ
641 USBHIDState *s = (USBHIDState *)dev;
642
643 s->ptr.dx = 0;
644 s->ptr.dy = 0;
645 s->ptr.dz = 0;
646 s->ptr.x = 0;
647 s->ptr.y = 0;
648 s->ptr.buttons_state = 0;
649 s->protocol = 1;
650}
651
652static void usb_keyboard_handle_reset(USBDevice *dev)
653{
654 USBHIDState *s = (USBHIDState *)dev;
655
926acf8f 656 qemu_add_kbd_event_handler(usb_keyboard_event, s);
47b2d338 657 s->protocol = 1;
59ae540c
FB
658}
659
68735b6c
KC
660static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
661{
662 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
663}
664
47b2d338 665static int usb_hid_handle_control(USBDevice *dev, int request, int value,
59ae540c
FB
666 int index, int length, uint8_t *data)
667{
47b2d338 668 USBHIDState *s = (USBHIDState *)dev;
0e4e9695 669 int ret;
59ae540c 670
0e4e9695
GH
671 ret = usb_desc_handle_control(dev, request, value, index, length, data);
672 if (ret >= 0) {
673 return ret;
674 }
675
676 ret = 0;
59ae540c 677 switch(request) {
59ae540c
FB
678 case DeviceRequest | USB_REQ_GET_INTERFACE:
679 data[0] = 0;
680 ret = 1;
681 break;
682 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
683 ret = 0;
684 break;
685 /* hid specific requests */
686 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
687 switch(value >> 8) {
688 case 0x22:
09b26c5e 689 if (s->kind == USB_MOUSE) {
5fafdf24 690 memcpy(data, qemu_mouse_hid_report_descriptor,
09b26c5e
FB
691 sizeof(qemu_mouse_hid_report_descriptor));
692 ret = sizeof(qemu_mouse_hid_report_descriptor);
693 } else if (s->kind == USB_TABLET) {
5fafdf24 694 memcpy(data, qemu_tablet_hid_report_descriptor,
09b26c5e
FB
695 sizeof(qemu_tablet_hid_report_descriptor));
696 ret = sizeof(qemu_tablet_hid_report_descriptor);
47b2d338 697 } else if (s->kind == USB_KEYBOARD) {
5fafdf24 698 memcpy(data, qemu_keyboard_hid_report_descriptor,
47b2d338
AZ
699 sizeof(qemu_keyboard_hid_report_descriptor));
700 ret = sizeof(qemu_keyboard_hid_report_descriptor);
701 }
702 break;
59ae540c
FB
703 default:
704 goto fail;
705 }
706 break;
707 case GET_REPORT:
09b26c5e 708 if (s->kind == USB_MOUSE)
117b3ae6 709 ret = usb_mouse_poll(s, data, length);
09b26c5e 710 else if (s->kind == USB_TABLET)
117b3ae6 711 ret = usb_tablet_poll(s, data, length);
47b2d338
AZ
712 else if (s->kind == USB_KEYBOARD)
713 ret = usb_keyboard_poll(&s->kbd, data, length);
714 break;
715 case SET_REPORT:
716 if (s->kind == USB_KEYBOARD)
717 ret = usb_keyboard_write(&s->kbd, data, length);
718 else
719 goto fail;
720 break;
721 case GET_PROTOCOL:
722 if (s->kind != USB_KEYBOARD)
723 goto fail;
724 ret = 1;
725 data[0] = s->protocol;
726 break;
727 case SET_PROTOCOL:
728 if (s->kind != USB_KEYBOARD)
729 goto fail;
730 ret = 0;
731 s->protocol = value;
732 break;
733 case GET_IDLE:
734 ret = 1;
735 data[0] = s->idle;
59ae540c
FB
736 break;
737 case SET_IDLE:
181a29c5 738 s->idle = (uint8_t) (value >> 8);
68735b6c 739 usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
59ae540c
FB
740 ret = 0;
741 break;
742 default:
743 fail:
744 ret = USB_RET_STALL;
745 break;
746 }
747 return ret;
748}
749
47b2d338 750static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
59ae540c 751{
47b2d338 752 USBHIDState *s = (USBHIDState *)dev;
09b26c5e 753 int ret = 0;
59ae540c 754
4d611c9a 755 switch(p->pid) {
59ae540c 756 case USB_TOKEN_IN:
4d611c9a 757 if (p->devep == 1) {
68735b6c
KC
758 int64_t curtime = qemu_get_clock(vm_clock);
759 if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
117b3ae6 760 return USB_RET_NAK;
68735b6c 761 usb_hid_set_next_idle(s, curtime);
117b3ae6 762 s->changed = 0;
47b2d338 763 if (s->kind == USB_MOUSE)
117b3ae6 764 ret = usb_mouse_poll(s, p->data, p->len);
47b2d338 765 else if (s->kind == USB_TABLET)
117b3ae6 766 ret = usb_tablet_poll(s, p->data, p->len);
47b2d338
AZ
767 else if (s->kind == USB_KEYBOARD)
768 ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
59ae540c
FB
769 } else {
770 goto fail;
771 }
772 break;
773 case USB_TOKEN_OUT:
774 default:
775 fail:
776 ret = USB_RET_STALL;
777 break;
778 }
779 return ret;
780}
781
47b2d338 782static void usb_hid_handle_destroy(USBDevice *dev)
059809e4 783{
47b2d338 784 USBHIDState *s = (USBHIDState *)dev;
059809e4 785
46aaebff
JS
786 switch(s->kind) {
787 case USB_KEYBOARD:
788 qemu_remove_kbd_event_handler();
789 break;
790 default:
47b2d338 791 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
46aaebff 792 }
059809e4
FB
793}
794
806b6024 795static int usb_hid_initfn(USBDevice *dev, int kind)
09b26c5e 796{
806b6024 797 USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
a980a065
GH
798
799 usb_desc_init(dev);
806b6024 800 s->kind = kind;
6fef28ee
AL
801
802 if (s->kind == USB_MOUSE) {
803 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
804 0, "QEMU USB Mouse");
805 } else if (s->kind == USB_TABLET) {
806 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
807 1, "QEMU USB Tablet");
808 }
809
117b3ae6
PB
810 /* Force poll routine to be run and grab input the first time. */
811 s->changed = 1;
806b6024 812 return 0;
09b26c5e
FB
813}
814
806b6024 815static int usb_tablet_initfn(USBDevice *dev)
59ae540c 816{
806b6024
GH
817 return usb_hid_initfn(dev, USB_TABLET);
818}
59ae540c 819
806b6024
GH
820static int usb_mouse_initfn(USBDevice *dev)
821{
822 return usb_hid_initfn(dev, USB_MOUSE);
823}
59ae540c 824
806b6024
GH
825static int usb_keyboard_initfn(USBDevice *dev)
826{
827 return usb_hid_initfn(dev, USB_KEYBOARD);
828}
59ae540c 829
47e699dc
AZ
830void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
831{
832 USBHIDState *s = (USBHIDState *)dev;
833
834 s->datain_opaque = opaque;
835 s->datain = datain;
836}
806b6024
GH
837
838static struct USBDeviceInfo hid_info[] = {
839 {
06384698 840 .product_desc = "QEMU USB Tablet",
556cd098 841 .qdev.name = "usb-tablet",
fa7c70c3 842 .usbdevice_name = "tablet",
806b6024 843 .qdev.size = sizeof(USBHIDState),
0e4e9695 844 .usb_desc = &desc_tablet,
806b6024
GH
845 .init = usb_tablet_initfn,
846 .handle_packet = usb_generic_handle_packet,
847 .handle_reset = usb_mouse_handle_reset,
848 .handle_control = usb_hid_handle_control,
849 .handle_data = usb_hid_handle_data,
850 .handle_destroy = usb_hid_handle_destroy,
851 },{
06384698 852 .product_desc = "QEMU USB Mouse",
556cd098 853 .qdev.name = "usb-mouse",
fa7c70c3 854 .usbdevice_name = "mouse",
806b6024 855 .qdev.size = sizeof(USBHIDState),
0e4e9695 856 .usb_desc = &desc_mouse,
806b6024
GH
857 .init = usb_mouse_initfn,
858 .handle_packet = usb_generic_handle_packet,
859 .handle_reset = usb_mouse_handle_reset,
860 .handle_control = usb_hid_handle_control,
861 .handle_data = usb_hid_handle_data,
862 .handle_destroy = usb_hid_handle_destroy,
863 },{
06384698 864 .product_desc = "QEMU USB Keyboard",
556cd098 865 .qdev.name = "usb-kbd",
fa7c70c3 866 .usbdevice_name = "keyboard",
806b6024 867 .qdev.size = sizeof(USBHIDState),
0e4e9695 868 .usb_desc = &desc_keyboard,
806b6024
GH
869 .init = usb_keyboard_initfn,
870 .handle_packet = usb_generic_handle_packet,
871 .handle_reset = usb_keyboard_handle_reset,
872 .handle_control = usb_hid_handle_control,
873 .handle_data = usb_hid_handle_data,
874 .handle_destroy = usb_hid_handle_destroy,
875 },{
876 /* end of list */
877 }
878};
879
880static void usb_hid_register_devices(void)
881{
882 usb_qdev_register_many(hid_info);
883}
884device_init(usb_hid_register_devices)