Revert "usb-linux: remove unreachable default in switch statement"
[qemu.git] / hw / usb-hid.c
blob2e4e64729cabd98971609401839959e206f8608c
1 /*
2 * QEMU USB HID devices
4 * Copyright (c) 2005 Fabrice Bellard
5 * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com)
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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.
25 #include "hw.h"
26 #include "console.h"
27 #include "usb.h"
29 /* HID interface requests */
30 #define GET_REPORT 0xa101
31 #define GET_IDLE 0xa102
32 #define GET_PROTOCOL 0xa103
33 #define SET_REPORT 0x2109
34 #define SET_IDLE 0x210a
35 #define SET_PROTOCOL 0x210b
37 /* HID descriptor types */
38 #define USB_DT_HID 0x21
39 #define USB_DT_REPORT 0x22
40 #define USB_DT_PHY 0x23
42 #define USB_MOUSE 1
43 #define USB_TABLET 2
44 #define USB_KEYBOARD 3
46 typedef struct USBMouseState {
47 int dx, dy, dz, buttons_state;
48 int x, y;
49 int mouse_grabbed;
50 QEMUPutMouseEntry *eh_entry;
51 } USBMouseState;
53 typedef struct USBKeyboardState {
54 uint16_t modifiers;
55 uint8_t leds;
56 uint8_t key[16];
57 int keys;
58 } USBKeyboardState;
60 typedef struct USBHIDState {
61 USBDevice dev;
62 union {
63 USBMouseState ptr;
64 USBKeyboardState kbd;
66 int kind;
67 int protocol;
68 uint8_t idle;
69 int64_t next_idle_clock;
70 int changed;
71 void *datain_opaque;
72 void (*datain)(void *);
73 } USBHIDState;
75 /* mostly the same values as the Bochs USB Mouse device */
76 static const uint8_t qemu_mouse_dev_descriptor[] = {
77 0x12, /* u8 bLength; */
78 0x01, /* u8 bDescriptorType; Device */
79 0x00, 0x01, /* u16 bcdUSB; v1.0 */
81 0x00, /* u8 bDeviceClass; */
82 0x00, /* u8 bDeviceSubClass; */
83 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
84 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
86 0x27, 0x06, /* u16 idVendor; */
87 0x01, 0x00, /* u16 idProduct; */
88 0x00, 0x00, /* u16 bcdDevice */
90 0x03, /* u8 iManufacturer; */
91 0x02, /* u8 iProduct; */
92 0x01, /* u8 iSerialNumber; */
93 0x01 /* u8 bNumConfigurations; */
96 static const uint8_t qemu_mouse_config_descriptor[] = {
97 /* one configuration */
98 0x09, /* u8 bLength; */
99 0x02, /* u8 bDescriptorType; Configuration */
100 0x22, 0x00, /* u16 wTotalLength; */
101 0x01, /* u8 bNumInterfaces; (1) */
102 0x01, /* u8 bConfigurationValue; */
103 0x04, /* u8 iConfiguration; */
104 0xe0, /* u8 bmAttributes;
105 Bit 7: must be set,
106 6: Self-powered,
107 5: Remote wakeup,
108 4..0: resvd */
109 50, /* u8 MaxPower; */
111 /* USB 1.1:
112 * USB 2.0, single TT organization (mandatory):
113 * one interface, protocol 0
115 * USB 2.0, multiple TT organization (optional):
116 * two interfaces, protocols 1 (like single TT)
117 * and 2 (multiple TT mode) ... config is
118 * sometimes settable
119 * NOT IMPLEMENTED
122 /* one interface */
123 0x09, /* u8 if_bLength; */
124 0x04, /* u8 if_bDescriptorType; Interface */
125 0x00, /* u8 if_bInterfaceNumber; */
126 0x00, /* u8 if_bAlternateSetting; */
127 0x01, /* u8 if_bNumEndpoints; */
128 0x03, /* u8 if_bInterfaceClass; */
129 0x01, /* u8 if_bInterfaceSubClass; */
130 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
131 0x07, /* u8 if_iInterface; */
133 /* HID descriptor */
134 0x09, /* u8 bLength; */
135 0x21, /* u8 bDescriptorType; */
136 0x01, 0x00, /* u16 HID_class */
137 0x00, /* u8 country_code */
138 0x01, /* u8 num_descriptors */
139 0x22, /* u8 type; Report */
140 52, 0, /* u16 len */
142 /* one endpoint (status change endpoint) */
143 0x07, /* u8 ep_bLength; */
144 0x05, /* u8 ep_bDescriptorType; Endpoint */
145 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
146 0x03, /* u8 ep_bmAttributes; Interrupt */
147 0x04, 0x00, /* u16 ep_wMaxPacketSize; */
148 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
151 static const uint8_t qemu_tablet_config_descriptor[] = {
152 /* one configuration */
153 0x09, /* u8 bLength; */
154 0x02, /* u8 bDescriptorType; Configuration */
155 0x22, 0x00, /* u16 wTotalLength; */
156 0x01, /* u8 bNumInterfaces; (1) */
157 0x01, /* u8 bConfigurationValue; */
158 0x05, /* u8 iConfiguration; */
159 0xa0, /* u8 bmAttributes;
160 Bit 7: must be set,
161 6: Self-powered,
162 5: Remote wakeup,
163 4..0: resvd */
164 50, /* u8 MaxPower; */
166 /* USB 1.1:
167 * USB 2.0, single TT organization (mandatory):
168 * one interface, protocol 0
170 * USB 2.0, multiple TT organization (optional):
171 * two interfaces, protocols 1 (like single TT)
172 * and 2 (multiple TT mode) ... config is
173 * sometimes settable
174 * NOT IMPLEMENTED
177 /* one interface */
178 0x09, /* u8 if_bLength; */
179 0x04, /* u8 if_bDescriptorType; Interface */
180 0x00, /* u8 if_bInterfaceNumber; */
181 0x00, /* u8 if_bAlternateSetting; */
182 0x01, /* u8 if_bNumEndpoints; */
183 0x03, /* u8 if_bInterfaceClass; */
184 0x01, /* u8 if_bInterfaceSubClass; */
185 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
186 0x07, /* u8 if_iInterface; */
188 /* HID descriptor */
189 0x09, /* u8 bLength; */
190 0x21, /* u8 bDescriptorType; */
191 0x01, 0x00, /* u16 HID_class */
192 0x00, /* u8 country_code */
193 0x01, /* u8 num_descriptors */
194 0x22, /* u8 type; Report */
195 74, 0, /* u16 len */
197 /* one endpoint (status change endpoint) */
198 0x07, /* u8 ep_bLength; */
199 0x05, /* u8 ep_bDescriptorType; Endpoint */
200 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
201 0x03, /* u8 ep_bmAttributes; Interrupt */
202 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
203 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
206 static const uint8_t qemu_keyboard_config_descriptor[] = {
207 /* one configuration */
208 0x09, /* u8 bLength; */
209 USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */
210 0x22, 0x00, /* u16 wTotalLength; */
211 0x01, /* u8 bNumInterfaces; (1) */
212 0x01, /* u8 bConfigurationValue; */
213 0x06, /* u8 iConfiguration; */
214 0xa0, /* u8 bmAttributes;
215 Bit 7: must be set,
216 6: Self-powered,
217 5: Remote wakeup,
218 4..0: resvd */
219 0x32, /* u8 MaxPower; */
221 /* USB 1.1:
222 * USB 2.0, single TT organization (mandatory):
223 * one interface, protocol 0
225 * USB 2.0, multiple TT organization (optional):
226 * two interfaces, protocols 1 (like single TT)
227 * and 2 (multiple TT mode) ... config is
228 * sometimes settable
229 * NOT IMPLEMENTED
232 /* one interface */
233 0x09, /* u8 if_bLength; */
234 USB_DT_INTERFACE, /* u8 if_bDescriptorType; Interface */
235 0x00, /* u8 if_bInterfaceNumber; */
236 0x00, /* u8 if_bAlternateSetting; */
237 0x01, /* u8 if_bNumEndpoints; */
238 0x03, /* u8 if_bInterfaceClass; HID */
239 0x01, /* u8 if_bInterfaceSubClass; Boot */
240 0x01, /* u8 if_bInterfaceProtocol; Keyboard */
241 0x07, /* u8 if_iInterface; */
243 /* HID descriptor */
244 0x09, /* u8 bLength; */
245 USB_DT_HID, /* u8 bDescriptorType; */
246 0x11, 0x01, /* u16 HID_class */
247 0x00, /* u8 country_code */
248 0x01, /* u8 num_descriptors */
249 USB_DT_REPORT, /* u8 type; Report */
250 0x3f, 0x00, /* u16 len */
252 /* one endpoint (status change endpoint) */
253 0x07, /* u8 ep_bLength; */
254 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; Endpoint */
255 USB_DIR_IN | 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
256 0x03, /* u8 ep_bmAttributes; Interrupt */
257 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
258 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
261 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
262 0x05, 0x01, /* Usage Page (Generic Desktop) */
263 0x09, 0x02, /* Usage (Mouse) */
264 0xa1, 0x01, /* Collection (Application) */
265 0x09, 0x01, /* Usage (Pointer) */
266 0xa1, 0x00, /* Collection (Physical) */
267 0x05, 0x09, /* Usage Page (Button) */
268 0x19, 0x01, /* Usage Minimum (1) */
269 0x29, 0x03, /* Usage Maximum (3) */
270 0x15, 0x00, /* Logical Minimum (0) */
271 0x25, 0x01, /* Logical Maximum (1) */
272 0x95, 0x03, /* Report Count (3) */
273 0x75, 0x01, /* Report Size (1) */
274 0x81, 0x02, /* Input (Data, Variable, Absolute) */
275 0x95, 0x01, /* Report Count (1) */
276 0x75, 0x05, /* Report Size (5) */
277 0x81, 0x01, /* Input (Constant) */
278 0x05, 0x01, /* Usage Page (Generic Desktop) */
279 0x09, 0x30, /* Usage (X) */
280 0x09, 0x31, /* Usage (Y) */
281 0x09, 0x38, /* Usage (Wheel) */
282 0x15, 0x81, /* Logical Minimum (-0x7f) */
283 0x25, 0x7f, /* Logical Maximum (0x7f) */
284 0x75, 0x08, /* Report Size (8) */
285 0x95, 0x03, /* Report Count (3) */
286 0x81, 0x06, /* Input (Data, Variable, Relative) */
287 0xc0, /* End Collection */
288 0xc0, /* End Collection */
291 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
292 0x05, 0x01, /* Usage Page (Generic Desktop) */
293 0x09, 0x01, /* Usage (Pointer) */
294 0xa1, 0x01, /* Collection (Application) */
295 0x09, 0x01, /* Usage (Pointer) */
296 0xa1, 0x00, /* Collection (Physical) */
297 0x05, 0x09, /* Usage Page (Button) */
298 0x19, 0x01, /* Usage Minimum (1) */
299 0x29, 0x03, /* Usage Maximum (3) */
300 0x15, 0x00, /* Logical Minimum (0) */
301 0x25, 0x01, /* Logical Maximum (1) */
302 0x95, 0x03, /* Report Count (3) */
303 0x75, 0x01, /* Report Size (1) */
304 0x81, 0x02, /* Input (Data, Variable, Absolute) */
305 0x95, 0x01, /* Report Count (1) */
306 0x75, 0x05, /* Report Size (5) */
307 0x81, 0x01, /* Input (Constant) */
308 0x05, 0x01, /* Usage Page (Generic Desktop) */
309 0x09, 0x30, /* Usage (X) */
310 0x09, 0x31, /* Usage (Y) */
311 0x15, 0x00, /* Logical Minimum (0) */
312 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
313 0x35, 0x00, /* Physical Minimum (0) */
314 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
315 0x75, 0x10, /* Report Size (16) */
316 0x95, 0x02, /* Report Count (2) */
317 0x81, 0x02, /* Input (Data, Variable, Absolute) */
318 0x05, 0x01, /* Usage Page (Generic Desktop) */
319 0x09, 0x38, /* Usage (Wheel) */
320 0x15, 0x81, /* Logical Minimum (-0x7f) */
321 0x25, 0x7f, /* Logical Maximum (0x7f) */
322 0x35, 0x00, /* Physical Minimum (same as logical) */
323 0x45, 0x00, /* Physical Maximum (same as logical) */
324 0x75, 0x08, /* Report Size (8) */
325 0x95, 0x01, /* Report Count (1) */
326 0x81, 0x06, /* Input (Data, Variable, Relative) */
327 0xc0, /* End Collection */
328 0xc0, /* End Collection */
331 static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
332 0x05, 0x01, /* Usage Page (Generic Desktop) */
333 0x09, 0x06, /* Usage (Keyboard) */
334 0xa1, 0x01, /* Collection (Application) */
335 0x75, 0x01, /* Report Size (1) */
336 0x95, 0x08, /* Report Count (8) */
337 0x05, 0x07, /* Usage Page (Key Codes) */
338 0x19, 0xe0, /* Usage Minimum (224) */
339 0x29, 0xe7, /* Usage Maximum (231) */
340 0x15, 0x00, /* Logical Minimum (0) */
341 0x25, 0x01, /* Logical Maximum (1) */
342 0x81, 0x02, /* Input (Data, Variable, Absolute) */
343 0x95, 0x01, /* Report Count (1) */
344 0x75, 0x08, /* Report Size (8) */
345 0x81, 0x01, /* Input (Constant) */
346 0x95, 0x05, /* Report Count (5) */
347 0x75, 0x01, /* Report Size (1) */
348 0x05, 0x08, /* Usage Page (LEDs) */
349 0x19, 0x01, /* Usage Minimum (1) */
350 0x29, 0x05, /* Usage Maximum (5) */
351 0x91, 0x02, /* Output (Data, Variable, Absolute) */
352 0x95, 0x01, /* Report Count (1) */
353 0x75, 0x03, /* Report Size (3) */
354 0x91, 0x01, /* Output (Constant) */
355 0x95, 0x06, /* Report Count (6) */
356 0x75, 0x08, /* Report Size (8) */
357 0x15, 0x00, /* Logical Minimum (0) */
358 0x25, 0xff, /* Logical Maximum (255) */
359 0x05, 0x07, /* Usage Page (Key Codes) */
360 0x19, 0x00, /* Usage Minimum (0) */
361 0x29, 0xff, /* Usage Maximum (255) */
362 0x81, 0x00, /* Input (Data, Array) */
363 0xc0, /* End Collection */
366 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
367 #define USB_HID_USAGE_POSTFAIL 0x02
368 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
370 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
371 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
372 static const uint8_t usb_hid_usage_keys[0x100] = {
373 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
374 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
375 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
376 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
377 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
378 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
379 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
380 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
381 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
382 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
383 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
384 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
385 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
386 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
397 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
399 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
400 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
408 static void usb_hid_changed(USBHIDState *hs)
410 hs->changed = 1;
412 if (hs->datain)
413 hs->datain(hs->datain_opaque);
416 static void usb_mouse_event(void *opaque,
417 int dx1, int dy1, int dz1, int buttons_state)
419 USBHIDState *hs = opaque;
420 USBMouseState *s = &hs->ptr;
422 s->dx += dx1;
423 s->dy += dy1;
424 s->dz += dz1;
425 s->buttons_state = buttons_state;
427 usb_hid_changed(hs);
430 static void usb_tablet_event(void *opaque,
431 int x, int y, int dz, int buttons_state)
433 USBHIDState *hs = opaque;
434 USBMouseState *s = &hs->ptr;
436 s->x = x;
437 s->y = y;
438 s->dz += dz;
439 s->buttons_state = buttons_state;
441 usb_hid_changed(hs);
444 static void usb_keyboard_event(void *opaque, int keycode)
446 USBHIDState *hs = opaque;
447 USBKeyboardState *s = &hs->kbd;
448 uint8_t hid_code, key;
449 int i;
451 key = keycode & 0x7f;
452 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
453 s->modifiers &= ~(1 << 8);
455 switch (hid_code) {
456 case 0x00:
457 return;
459 case 0xe0:
460 if (s->modifiers & (1 << 9)) {
461 s->modifiers ^= 3 << 8;
462 return;
464 case 0xe1 ... 0xe7:
465 if (keycode & (1 << 7)) {
466 s->modifiers &= ~(1 << (hid_code & 0x0f));
467 return;
469 case 0xe8 ... 0xef:
470 s->modifiers |= 1 << (hid_code & 0x0f);
471 return;
474 if (keycode & (1 << 7)) {
475 for (i = s->keys - 1; i >= 0; i --)
476 if (s->key[i] == hid_code) {
477 s->key[i] = s->key[-- s->keys];
478 s->key[s->keys] = 0x00;
479 usb_hid_changed(hs);
480 break;
482 if (i < 0)
483 return;
484 } else {
485 for (i = s->keys - 1; i >= 0; i --)
486 if (s->key[i] == hid_code)
487 break;
488 if (i < 0) {
489 if (s->keys < sizeof(s->key))
490 s->key[s->keys ++] = hid_code;
491 } else
492 return;
495 usb_hid_changed(hs);
498 static inline int int_clamp(int val, int vmin, int vmax)
500 if (val < vmin)
501 return vmin;
502 else if (val > vmax)
503 return vmax;
504 else
505 return val;
508 static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
510 int dx, dy, dz, b, l;
511 USBMouseState *s = &hs->ptr;
513 if (!s->mouse_grabbed) {
514 s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, hs,
515 0, "QEMU USB Mouse");
516 s->mouse_grabbed = 1;
519 dx = int_clamp(s->dx, -127, 127);
520 dy = int_clamp(s->dy, -127, 127);
521 dz = int_clamp(s->dz, -127, 127);
523 s->dx -= dx;
524 s->dy -= dy;
525 s->dz -= dz;
527 /* Appears we have to invert the wheel direction */
528 dz = 0 - dz;
530 b = 0;
531 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
532 b |= 0x01;
533 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
534 b |= 0x02;
535 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
536 b |= 0x04;
538 l = 0;
539 if (len > l)
540 buf[l ++] = b;
541 if (len > l)
542 buf[l ++] = dx;
543 if (len > l)
544 buf[l ++] = dy;
545 if (len > l)
546 buf[l ++] = dz;
547 return l;
550 static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
552 int dz, b, l;
553 USBMouseState *s = &hs->ptr;
555 if (!s->mouse_grabbed) {
556 s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs,
557 1, "QEMU USB Tablet");
558 s->mouse_grabbed = 1;
561 dz = int_clamp(s->dz, -127, 127);
562 s->dz -= dz;
564 /* Appears we have to invert the wheel direction */
565 dz = 0 - dz;
566 b = 0;
567 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
568 b |= 0x01;
569 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
570 b |= 0x02;
571 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
572 b |= 0x04;
574 buf[0] = b;
575 buf[1] = s->x & 0xff;
576 buf[2] = s->x >> 8;
577 buf[3] = s->y & 0xff;
578 buf[4] = s->y >> 8;
579 buf[5] = dz;
580 l = 6;
582 return l;
585 static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
587 if (len < 2)
588 return 0;
590 buf[0] = s->modifiers & 0xff;
591 buf[1] = 0;
592 if (s->keys > 6)
593 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
594 else
595 memcpy(buf + 2, s->key, MIN(8, len) - 2);
597 return MIN(8, len);
600 static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
602 if (len > 0) {
603 int ledstate = 0;
604 /* 0x01: Num Lock LED
605 * 0x02: Caps Lock LED
606 * 0x04: Scroll Lock LED
607 * 0x08: Compose LED
608 * 0x10: Kana LED */
609 s->leds = buf[0];
610 if (s->leds & 0x04)
611 ledstate |= QEMU_SCROLL_LOCK_LED;
612 if (s->leds & 0x01)
613 ledstate |= QEMU_NUM_LOCK_LED;
614 if (s->leds & 0x02)
615 ledstate |= QEMU_CAPS_LOCK_LED;
616 kbd_put_ledstate(ledstate);
618 return 0;
621 static void usb_mouse_handle_reset(USBDevice *dev)
623 USBHIDState *s = (USBHIDState *)dev;
625 s->ptr.dx = 0;
626 s->ptr.dy = 0;
627 s->ptr.dz = 0;
628 s->ptr.x = 0;
629 s->ptr.y = 0;
630 s->ptr.buttons_state = 0;
631 s->protocol = 1;
634 static void usb_keyboard_handle_reset(USBDevice *dev)
636 USBHIDState *s = (USBHIDState *)dev;
638 qemu_add_kbd_event_handler(usb_keyboard_event, s);
639 s->protocol = 1;
642 static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
644 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
647 static int usb_hid_handle_control(USBDevice *dev, int request, int value,
648 int index, int length, uint8_t *data)
650 USBHIDState *s = (USBHIDState *)dev;
651 int ret = 0;
653 switch(request) {
654 case DeviceRequest | USB_REQ_GET_STATUS:
655 data[0] = (1 << USB_DEVICE_SELF_POWERED) |
656 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
657 data[1] = 0x00;
658 ret = 2;
659 break;
660 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
661 if (value == USB_DEVICE_REMOTE_WAKEUP) {
662 dev->remote_wakeup = 0;
663 } else {
664 goto fail;
666 ret = 0;
667 break;
668 case DeviceOutRequest | USB_REQ_SET_FEATURE:
669 if (value == USB_DEVICE_REMOTE_WAKEUP) {
670 dev->remote_wakeup = 1;
671 } else {
672 goto fail;
674 ret = 0;
675 break;
676 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
677 dev->addr = value;
678 ret = 0;
679 break;
680 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
681 switch(value >> 8) {
682 case USB_DT_DEVICE:
683 memcpy(data, qemu_mouse_dev_descriptor,
684 sizeof(qemu_mouse_dev_descriptor));
685 ret = sizeof(qemu_mouse_dev_descriptor);
686 break;
687 case USB_DT_CONFIG:
688 if (s->kind == USB_MOUSE) {
689 memcpy(data, qemu_mouse_config_descriptor,
690 sizeof(qemu_mouse_config_descriptor));
691 ret = sizeof(qemu_mouse_config_descriptor);
692 } else if (s->kind == USB_TABLET) {
693 memcpy(data, qemu_tablet_config_descriptor,
694 sizeof(qemu_tablet_config_descriptor));
695 ret = sizeof(qemu_tablet_config_descriptor);
696 } else if (s->kind == USB_KEYBOARD) {
697 memcpy(data, qemu_keyboard_config_descriptor,
698 sizeof(qemu_keyboard_config_descriptor));
699 ret = sizeof(qemu_keyboard_config_descriptor);
701 break;
702 case USB_DT_STRING:
703 switch(value & 0xff) {
704 case 0:
705 /* language ids */
706 data[0] = 4;
707 data[1] = 3;
708 data[2] = 0x09;
709 data[3] = 0x04;
710 ret = 4;
711 break;
712 case 1:
713 /* serial number */
714 ret = set_usb_string(data, "1");
715 break;
716 case 2:
717 /* product description */
718 ret = set_usb_string(data, s->dev.product_desc);
719 break;
720 case 3:
721 /* vendor description */
722 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
723 break;
724 case 4:
725 ret = set_usb_string(data, "HID Mouse");
726 break;
727 case 5:
728 ret = set_usb_string(data, "HID Tablet");
729 break;
730 case 6:
731 ret = set_usb_string(data, "HID Keyboard");
732 break;
733 case 7:
734 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
735 break;
736 default:
737 goto fail;
739 break;
740 default:
741 goto fail;
743 break;
744 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
745 data[0] = 1;
746 ret = 1;
747 break;
748 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
749 ret = 0;
750 break;
751 case DeviceRequest | USB_REQ_GET_INTERFACE:
752 data[0] = 0;
753 ret = 1;
754 break;
755 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
756 ret = 0;
757 break;
758 /* hid specific requests */
759 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
760 switch(value >> 8) {
761 case 0x22:
762 if (s->kind == USB_MOUSE) {
763 memcpy(data, qemu_mouse_hid_report_descriptor,
764 sizeof(qemu_mouse_hid_report_descriptor));
765 ret = sizeof(qemu_mouse_hid_report_descriptor);
766 } else if (s->kind == USB_TABLET) {
767 memcpy(data, qemu_tablet_hid_report_descriptor,
768 sizeof(qemu_tablet_hid_report_descriptor));
769 ret = sizeof(qemu_tablet_hid_report_descriptor);
770 } else if (s->kind == USB_KEYBOARD) {
771 memcpy(data, qemu_keyboard_hid_report_descriptor,
772 sizeof(qemu_keyboard_hid_report_descriptor));
773 ret = sizeof(qemu_keyboard_hid_report_descriptor);
775 break;
776 default:
777 goto fail;
779 break;
780 case GET_REPORT:
781 if (s->kind == USB_MOUSE)
782 ret = usb_mouse_poll(s, data, length);
783 else if (s->kind == USB_TABLET)
784 ret = usb_tablet_poll(s, data, length);
785 else if (s->kind == USB_KEYBOARD)
786 ret = usb_keyboard_poll(&s->kbd, data, length);
787 break;
788 case SET_REPORT:
789 if (s->kind == USB_KEYBOARD)
790 ret = usb_keyboard_write(&s->kbd, data, length);
791 else
792 goto fail;
793 break;
794 case GET_PROTOCOL:
795 if (s->kind != USB_KEYBOARD)
796 goto fail;
797 ret = 1;
798 data[0] = s->protocol;
799 break;
800 case SET_PROTOCOL:
801 if (s->kind != USB_KEYBOARD)
802 goto fail;
803 ret = 0;
804 s->protocol = value;
805 break;
806 case GET_IDLE:
807 ret = 1;
808 data[0] = s->idle;
809 break;
810 case SET_IDLE:
811 s->idle = (uint8_t) (value >> 8);
812 usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
813 ret = 0;
814 break;
815 default:
816 fail:
817 ret = USB_RET_STALL;
818 break;
820 return ret;
823 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
825 USBHIDState *s = (USBHIDState *)dev;
826 int ret = 0;
828 switch(p->pid) {
829 case USB_TOKEN_IN:
830 if (p->devep == 1) {
831 int64_t curtime = qemu_get_clock(vm_clock);
832 if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
833 return USB_RET_NAK;
834 usb_hid_set_next_idle(s, curtime);
835 s->changed = 0;
836 if (s->kind == USB_MOUSE)
837 ret = usb_mouse_poll(s, p->data, p->len);
838 else if (s->kind == USB_TABLET)
839 ret = usb_tablet_poll(s, p->data, p->len);
840 else if (s->kind == USB_KEYBOARD)
841 ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
842 } else {
843 goto fail;
845 break;
846 case USB_TOKEN_OUT:
847 default:
848 fail:
849 ret = USB_RET_STALL;
850 break;
852 return ret;
855 static void usb_hid_handle_destroy(USBDevice *dev)
857 USBHIDState *s = (USBHIDState *)dev;
859 if (s->kind != USB_KEYBOARD)
860 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
861 /* TODO: else */
864 static int usb_hid_initfn(USBDevice *dev, int kind)
866 USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
867 s->dev.speed = USB_SPEED_FULL;
868 s->kind = kind;
869 /* Force poll routine to be run and grab input the first time. */
870 s->changed = 1;
871 return 0;
874 static int usb_tablet_initfn(USBDevice *dev)
876 return usb_hid_initfn(dev, USB_TABLET);
879 static int usb_mouse_initfn(USBDevice *dev)
881 return usb_hid_initfn(dev, USB_MOUSE);
884 static int usb_keyboard_initfn(USBDevice *dev)
886 return usb_hid_initfn(dev, USB_KEYBOARD);
889 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
891 USBHIDState *s = (USBHIDState *)dev;
893 s->datain_opaque = opaque;
894 s->datain = datain;
897 static struct USBDeviceInfo hid_info[] = {
899 .product_desc = "QEMU USB Tablet",
900 .qdev.name = "usb-tablet",
901 .usbdevice_name = "tablet",
902 .qdev.size = sizeof(USBHIDState),
903 .init = usb_tablet_initfn,
904 .handle_packet = usb_generic_handle_packet,
905 .handle_reset = usb_mouse_handle_reset,
906 .handle_control = usb_hid_handle_control,
907 .handle_data = usb_hid_handle_data,
908 .handle_destroy = usb_hid_handle_destroy,
910 .product_desc = "QEMU USB Mouse",
911 .qdev.name = "usb-mouse",
912 .usbdevice_name = "mouse",
913 .qdev.size = sizeof(USBHIDState),
914 .init = usb_mouse_initfn,
915 .handle_packet = usb_generic_handle_packet,
916 .handle_reset = usb_mouse_handle_reset,
917 .handle_control = usb_hid_handle_control,
918 .handle_data = usb_hid_handle_data,
919 .handle_destroy = usb_hid_handle_destroy,
921 .product_desc = "QEMU USB Keyboard",
922 .qdev.name = "usb-kbd",
923 .usbdevice_name = "keyboard",
924 .qdev.size = sizeof(USBHIDState),
925 .init = usb_keyboard_initfn,
926 .handle_packet = usb_generic_handle_packet,
927 .handle_reset = usb_keyboard_handle_reset,
928 .handle_control = usb_hid_handle_control,
929 .handle_data = usb_hid_handle_data,
930 .handle_destroy = usb_hid_handle_destroy,
932 /* end of list */
936 static void usb_hid_register_devices(void)
938 usb_qdev_register_many(hid_info);
940 device_init(usb_hid_register_devices)