MINI2440: General update
[qemu/mini2440.git] / hw / usb-hid.c
blobc850a9194749f632d2863627f611728122edb168
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 int changed;
70 void *datain_opaque;
71 void (*datain)(void *);
72 } USBHIDState;
74 /* mostly the same values as the Bochs USB Mouse device */
75 static const uint8_t qemu_mouse_dev_descriptor[] = {
76 0x12, /* u8 bLength; */
77 0x01, /* u8 bDescriptorType; Device */
78 0x00, 0x01, /* u16 bcdUSB; v1.0 */
80 0x00, /* u8 bDeviceClass; */
81 0x00, /* u8 bDeviceSubClass; */
82 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
83 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
85 0x27, 0x06, /* u16 idVendor; */
86 0x01, 0x00, /* u16 idProduct; */
87 0x00, 0x00, /* u16 bcdDevice */
89 0x03, /* u8 iManufacturer; */
90 0x02, /* u8 iProduct; */
91 0x01, /* u8 iSerialNumber; */
92 0x01 /* u8 bNumConfigurations; */
95 static const uint8_t qemu_mouse_config_descriptor[] = {
96 /* one configuration */
97 0x09, /* u8 bLength; */
98 0x02, /* u8 bDescriptorType; Configuration */
99 0x22, 0x00, /* u16 wTotalLength; */
100 0x01, /* u8 bNumInterfaces; (1) */
101 0x01, /* u8 bConfigurationValue; */
102 0x04, /* u8 iConfiguration; */
103 0xa0, /* u8 bmAttributes;
104 Bit 7: must be set,
105 6: Self-powered,
106 5: Remote wakeup,
107 4..0: resvd */
108 50, /* u8 MaxPower; */
110 /* USB 1.1:
111 * USB 2.0, single TT organization (mandatory):
112 * one interface, protocol 0
114 * USB 2.0, multiple TT organization (optional):
115 * two interfaces, protocols 1 (like single TT)
116 * and 2 (multiple TT mode) ... config is
117 * sometimes settable
118 * NOT IMPLEMENTED
121 /* one interface */
122 0x09, /* u8 if_bLength; */
123 0x04, /* u8 if_bDescriptorType; Interface */
124 0x00, /* u8 if_bInterfaceNumber; */
125 0x00, /* u8 if_bAlternateSetting; */
126 0x01, /* u8 if_bNumEndpoints; */
127 0x03, /* u8 if_bInterfaceClass; */
128 0x01, /* u8 if_bInterfaceSubClass; */
129 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
130 0x07, /* u8 if_iInterface; */
132 /* HID descriptor */
133 0x09, /* u8 bLength; */
134 0x21, /* u8 bDescriptorType; */
135 0x01, 0x00, /* u16 HID_class */
136 0x00, /* u8 country_code */
137 0x01, /* u8 num_descriptors */
138 0x22, /* u8 type; Report */
139 52, 0, /* u16 len */
141 /* one endpoint (status change endpoint) */
142 0x07, /* u8 ep_bLength; */
143 0x05, /* u8 ep_bDescriptorType; Endpoint */
144 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
145 0x03, /* u8 ep_bmAttributes; Interrupt */
146 0x04, 0x00, /* u16 ep_wMaxPacketSize; */
147 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
150 static const uint8_t qemu_tablet_config_descriptor[] = {
151 /* one configuration */
152 0x09, /* u8 bLength; */
153 0x02, /* u8 bDescriptorType; Configuration */
154 0x22, 0x00, /* u16 wTotalLength; */
155 0x01, /* u8 bNumInterfaces; (1) */
156 0x01, /* u8 bConfigurationValue; */
157 0x05, /* u8 iConfiguration; */
158 0xa0, /* u8 bmAttributes;
159 Bit 7: must be set,
160 6: Self-powered,
161 5: Remote wakeup,
162 4..0: resvd */
163 50, /* u8 MaxPower; */
165 /* USB 1.1:
166 * USB 2.0, single TT organization (mandatory):
167 * one interface, protocol 0
169 * USB 2.0, multiple TT organization (optional):
170 * two interfaces, protocols 1 (like single TT)
171 * and 2 (multiple TT mode) ... config is
172 * sometimes settable
173 * NOT IMPLEMENTED
176 /* one interface */
177 0x09, /* u8 if_bLength; */
178 0x04, /* u8 if_bDescriptorType; Interface */
179 0x00, /* u8 if_bInterfaceNumber; */
180 0x00, /* u8 if_bAlternateSetting; */
181 0x01, /* u8 if_bNumEndpoints; */
182 0x03, /* u8 if_bInterfaceClass; */
183 0x01, /* u8 if_bInterfaceSubClass; */
184 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
185 0x07, /* u8 if_iInterface; */
187 /* HID descriptor */
188 0x09, /* u8 bLength; */
189 0x21, /* u8 bDescriptorType; */
190 0x01, 0x00, /* u16 HID_class */
191 0x00, /* u8 country_code */
192 0x01, /* u8 num_descriptors */
193 0x22, /* u8 type; Report */
194 74, 0, /* u16 len */
196 /* one endpoint (status change endpoint) */
197 0x07, /* u8 ep_bLength; */
198 0x05, /* u8 ep_bDescriptorType; Endpoint */
199 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
200 0x03, /* u8 ep_bmAttributes; Interrupt */
201 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
202 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
205 static const uint8_t qemu_keyboard_config_descriptor[] = {
206 /* one configuration */
207 0x09, /* u8 bLength; */
208 USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */
209 0x22, 0x00, /* u16 wTotalLength; */
210 0x01, /* u8 bNumInterfaces; (1) */
211 0x01, /* u8 bConfigurationValue; */
212 0x06, /* u8 iConfiguration; */
213 0xa0, /* u8 bmAttributes;
214 Bit 7: must be set,
215 6: Self-powered,
216 5: Remote wakeup,
217 4..0: resvd */
218 0x32, /* u8 MaxPower; */
220 /* USB 1.1:
221 * USB 2.0, single TT organization (mandatory):
222 * one interface, protocol 0
224 * USB 2.0, multiple TT organization (optional):
225 * two interfaces, protocols 1 (like single TT)
226 * and 2 (multiple TT mode) ... config is
227 * sometimes settable
228 * NOT IMPLEMENTED
231 /* one interface */
232 0x09, /* u8 if_bLength; */
233 USB_DT_INTERFACE, /* u8 if_bDescriptorType; Interface */
234 0x00, /* u8 if_bInterfaceNumber; */
235 0x00, /* u8 if_bAlternateSetting; */
236 0x01, /* u8 if_bNumEndpoints; */
237 0x03, /* u8 if_bInterfaceClass; HID */
238 0x01, /* u8 if_bInterfaceSubClass; Boot */
239 0x01, /* u8 if_bInterfaceProtocol; Keyboard */
240 0x07, /* u8 if_iInterface; */
242 /* HID descriptor */
243 0x09, /* u8 bLength; */
244 USB_DT_HID, /* u8 bDescriptorType; */
245 0x11, 0x01, /* u16 HID_class */
246 0x00, /* u8 country_code */
247 0x01, /* u8 num_descriptors */
248 USB_DT_REPORT, /* u8 type; Report */
249 0x3f, 0x00, /* u16 len */
251 /* one endpoint (status change endpoint) */
252 0x07, /* u8 ep_bLength; */
253 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; Endpoint */
254 USB_DIR_IN | 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
255 0x03, /* u8 ep_bmAttributes; Interrupt */
256 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
257 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
260 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
261 0x05, 0x01, /* Usage Page (Generic Desktop) */
262 0x09, 0x02, /* Usage (Mouse) */
263 0xa1, 0x01, /* Collection (Application) */
264 0x09, 0x01, /* Usage (Pointer) */
265 0xa1, 0x00, /* Collection (Physical) */
266 0x05, 0x09, /* Usage Page (Button) */
267 0x19, 0x01, /* Usage Minimum (1) */
268 0x29, 0x03, /* Usage Maximum (3) */
269 0x15, 0x00, /* Logical Minimum (0) */
270 0x25, 0x01, /* Logical Maximum (1) */
271 0x95, 0x03, /* Report Count (3) */
272 0x75, 0x01, /* Report Size (1) */
273 0x81, 0x02, /* Input (Data, Variable, Absolute) */
274 0x95, 0x01, /* Report Count (1) */
275 0x75, 0x05, /* Report Size (5) */
276 0x81, 0x01, /* Input (Constant) */
277 0x05, 0x01, /* Usage Page (Generic Desktop) */
278 0x09, 0x30, /* Usage (X) */
279 0x09, 0x31, /* Usage (Y) */
280 0x09, 0x38, /* Usage (Wheel) */
281 0x15, 0x81, /* Logical Minimum (-0x7f) */
282 0x25, 0x7f, /* Logical Maximum (0x7f) */
283 0x75, 0x08, /* Report Size (8) */
284 0x95, 0x03, /* Report Count (3) */
285 0x81, 0x06, /* Input (Data, Variable, Relative) */
286 0xc0, /* End Collection */
287 0xc0, /* End Collection */
290 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
291 0x05, 0x01, /* Usage Page (Generic Desktop) */
292 0x09, 0x01, /* Usage (Pointer) */
293 0xa1, 0x01, /* Collection (Application) */
294 0x09, 0x01, /* Usage (Pointer) */
295 0xa1, 0x00, /* Collection (Physical) */
296 0x05, 0x09, /* Usage Page (Button) */
297 0x19, 0x01, /* Usage Minimum (1) */
298 0x29, 0x03, /* Usage Maximum (3) */
299 0x15, 0x00, /* Logical Minimum (0) */
300 0x25, 0x01, /* Logical Maximum (1) */
301 0x95, 0x03, /* Report Count (3) */
302 0x75, 0x01, /* Report Size (1) */
303 0x81, 0x02, /* Input (Data, Variable, Absolute) */
304 0x95, 0x01, /* Report Count (1) */
305 0x75, 0x05, /* Report Size (5) */
306 0x81, 0x01, /* Input (Constant) */
307 0x05, 0x01, /* Usage Page (Generic Desktop) */
308 0x09, 0x30, /* Usage (X) */
309 0x09, 0x31, /* Usage (Y) */
310 0x15, 0x00, /* Logical Minimum (0) */
311 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
312 0x35, 0x00, /* Physical Minimum (0) */
313 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
314 0x75, 0x10, /* Report Size (16) */
315 0x95, 0x02, /* Report Count (2) */
316 0x81, 0x02, /* Input (Data, Variable, Absolute) */
317 0x05, 0x01, /* Usage Page (Generic Desktop) */
318 0x09, 0x38, /* Usage (Wheel) */
319 0x15, 0x81, /* Logical Minimum (-0x7f) */
320 0x25, 0x7f, /* Logical Maximum (0x7f) */
321 0x35, 0x00, /* Physical Minimum (same as logical) */
322 0x45, 0x00, /* Physical Maximum (same as logical) */
323 0x75, 0x08, /* Report Size (8) */
324 0x95, 0x01, /* Report Count (1) */
325 0x81, 0x06, /* Input (Data, Variable, Relative) */
326 0xc0, /* End Collection */
327 0xc0, /* End Collection */
330 static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
331 0x05, 0x01, /* Usage Page (Generic Desktop) */
332 0x09, 0x06, /* Usage (Keyboard) */
333 0xa1, 0x01, /* Collection (Application) */
334 0x75, 0x01, /* Report Size (1) */
335 0x95, 0x08, /* Report Count (8) */
336 0x05, 0x07, /* Usage Page (Key Codes) */
337 0x19, 0xe0, /* Usage Minimum (224) */
338 0x29, 0xe7, /* Usage Maximum (231) */
339 0x15, 0x00, /* Logical Minimum (0) */
340 0x25, 0x01, /* Logical Maximum (1) */
341 0x81, 0x02, /* Input (Data, Variable, Absolute) */
342 0x95, 0x01, /* Report Count (1) */
343 0x75, 0x08, /* Report Size (8) */
344 0x81, 0x01, /* Input (Constant) */
345 0x95, 0x05, /* Report Count (5) */
346 0x75, 0x01, /* Report Size (1) */
347 0x05, 0x08, /* Usage Page (LEDs) */
348 0x19, 0x01, /* Usage Minimum (1) */
349 0x29, 0x05, /* Usage Maximum (5) */
350 0x91, 0x02, /* Output (Data, Variable, Absolute) */
351 0x95, 0x01, /* Report Count (1) */
352 0x75, 0x03, /* Report Size (3) */
353 0x91, 0x01, /* Output (Constant) */
354 0x95, 0x06, /* Report Count (6) */
355 0x75, 0x08, /* Report Size (8) */
356 0x15, 0x00, /* Logical Minimum (0) */
357 0x25, 0xff, /* Logical Maximum (255) */
358 0x05, 0x07, /* Usage Page (Key Codes) */
359 0x19, 0x00, /* Usage Minimum (0) */
360 0x29, 0xff, /* Usage Maximum (255) */
361 0x81, 0x00, /* Input (Data, Array) */
362 0xc0, /* End Collection */
365 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
366 #define USB_HID_USAGE_POSTFAIL 0x02
367 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
369 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
370 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
371 static const uint8_t usb_hid_usage_keys[0x100] = {
372 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
373 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
374 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
375 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
376 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
377 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
378 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
379 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
380 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
381 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
382 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
383 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
384 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
390 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
396 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
398 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
399 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
400 0x00, 0x00, 0x00, 0x00, 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,
407 static void usb_hid_changed(USBHIDState *hs)
409 hs->changed = 1;
411 if (hs->datain)
412 hs->datain(hs->datain_opaque);
415 static void usb_mouse_event(void *opaque,
416 int dx1, int dy1, int dz1, int buttons_state)
418 USBHIDState *hs = opaque;
419 USBMouseState *s = &hs->ptr;
421 s->dx += dx1;
422 s->dy += dy1;
423 s->dz += dz1;
424 s->buttons_state = buttons_state;
426 usb_hid_changed(hs);
429 static void usb_tablet_event(void *opaque,
430 int x, int y, int dz, int buttons_state)
432 USBHIDState *hs = opaque;
433 USBMouseState *s = &hs->ptr;
435 s->x = x;
436 s->y = y;
437 s->dz += dz;
438 s->buttons_state = buttons_state;
440 usb_hid_changed(hs);
443 static void usb_keyboard_event(void *opaque, int keycode)
445 USBHIDState *hs = opaque;
446 USBKeyboardState *s = &hs->kbd;
447 uint8_t hid_code, key;
448 int i;
450 key = keycode & 0x7f;
451 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
452 s->modifiers &= ~(1 << 8);
454 switch (hid_code) {
455 case 0x00:
456 return;
458 case 0xe0:
459 if (s->modifiers & (1 << 9)) {
460 s->modifiers ^= 3 << 8;
461 return;
463 case 0xe1 ... 0xe7:
464 if (keycode & (1 << 7)) {
465 s->modifiers &= ~(1 << (hid_code & 0x0f));
466 return;
468 case 0xe8 ... 0xef:
469 s->modifiers |= 1 << (hid_code & 0x0f);
470 return;
473 if (keycode & (1 << 7)) {
474 for (i = s->keys - 1; i >= 0; i --)
475 if (s->key[i] == hid_code) {
476 s->key[i] = s->key[-- s->keys];
477 s->key[s->keys] = 0x00;
478 usb_hid_changed(hs);
479 break;
481 if (i < 0)
482 return;
483 } else {
484 for (i = s->keys - 1; i >= 0; i --)
485 if (s->key[i] == hid_code)
486 break;
487 if (i < 0) {
488 if (s->keys < sizeof(s->key))
489 s->key[s->keys ++] = hid_code;
490 } else
491 return;
494 usb_hid_changed(hs);
497 static inline int int_clamp(int val, int vmin, int vmax)
499 if (val < vmin)
500 return vmin;
501 else if (val > vmax)
502 return vmax;
503 else
504 return val;
507 static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
509 int dx, dy, dz, b, l;
510 USBMouseState *s = &hs->ptr;
512 if (!s->mouse_grabbed) {
513 s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, hs,
514 0, "QEMU USB Mouse");
515 s->mouse_grabbed = 1;
518 dx = int_clamp(s->dx, -127, 127);
519 dy = int_clamp(s->dy, -127, 127);
520 dz = int_clamp(s->dz, -127, 127);
522 s->dx -= dx;
523 s->dy -= dy;
524 s->dz -= dz;
526 /* Appears we have to invert the wheel direction */
527 dz = 0 - dz;
529 b = 0;
530 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
531 b |= 0x01;
532 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
533 b |= 0x02;
534 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
535 b |= 0x04;
537 l = 0;
538 if (len > l)
539 buf[l ++] = b;
540 if (len > l)
541 buf[l ++] = dx;
542 if (len > l)
543 buf[l ++] = dy;
544 if (len > l)
545 buf[l ++] = dz;
546 return l;
549 static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
551 int dz, b, l;
552 USBMouseState *s = &hs->ptr;
554 if (!s->mouse_grabbed) {
555 s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs,
556 1, "QEMU USB Tablet");
557 s->mouse_grabbed = 1;
560 dz = int_clamp(s->dz, -127, 127);
561 s->dz -= dz;
563 /* Appears we have to invert the wheel direction */
564 dz = 0 - dz;
565 b = 0;
566 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
567 b |= 0x01;
568 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
569 b |= 0x02;
570 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
571 b |= 0x04;
573 buf[0] = b;
574 buf[1] = s->x & 0xff;
575 buf[2] = s->x >> 8;
576 buf[3] = s->y & 0xff;
577 buf[4] = s->y >> 8;
578 buf[5] = dz;
579 l = 6;
581 return l;
584 static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
586 if (len < 2)
587 return 0;
589 buf[0] = s->modifiers & 0xff;
590 buf[1] = 0;
591 if (s->keys > 6)
592 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
593 else
594 memcpy(buf + 2, s->key, MIN(8, len) - 2);
596 return MIN(8, len);
599 static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
601 if (len > 0) {
602 /* 0x01: Num Lock LED
603 * 0x02: Caps Lock LED
604 * 0x04: Scroll Lock LED
605 * 0x08: Compose LED
606 * 0x10: Kana LED */
607 s->leds = buf[0];
609 return 0;
612 static void usb_mouse_handle_reset(USBDevice *dev)
614 USBHIDState *s = (USBHIDState *)dev;
616 s->ptr.dx = 0;
617 s->ptr.dy = 0;
618 s->ptr.dz = 0;
619 s->ptr.x = 0;
620 s->ptr.y = 0;
621 s->ptr.buttons_state = 0;
622 s->protocol = 1;
625 static void usb_keyboard_handle_reset(USBDevice *dev)
627 USBHIDState *s = (USBHIDState *)dev;
629 qemu_add_kbd_event_handler(usb_keyboard_event, s);
630 s->protocol = 1;
633 static int usb_hid_handle_control(USBDevice *dev, int request, int value,
634 int index, int length, uint8_t *data)
636 USBHIDState *s = (USBHIDState *)dev;
637 int ret = 0;
639 switch(request) {
640 case DeviceRequest | USB_REQ_GET_STATUS:
641 data[0] = (1 << USB_DEVICE_SELF_POWERED) |
642 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
643 data[1] = 0x00;
644 ret = 2;
645 break;
646 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
647 if (value == USB_DEVICE_REMOTE_WAKEUP) {
648 dev->remote_wakeup = 0;
649 } else {
650 goto fail;
652 ret = 0;
653 break;
654 case DeviceOutRequest | USB_REQ_SET_FEATURE:
655 if (value == USB_DEVICE_REMOTE_WAKEUP) {
656 dev->remote_wakeup = 1;
657 } else {
658 goto fail;
660 ret = 0;
661 break;
662 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
663 dev->addr = value;
664 ret = 0;
665 break;
666 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
667 switch(value >> 8) {
668 case USB_DT_DEVICE:
669 memcpy(data, qemu_mouse_dev_descriptor,
670 sizeof(qemu_mouse_dev_descriptor));
671 ret = sizeof(qemu_mouse_dev_descriptor);
672 break;
673 case USB_DT_CONFIG:
674 if (s->kind == USB_MOUSE) {
675 memcpy(data, qemu_mouse_config_descriptor,
676 sizeof(qemu_mouse_config_descriptor));
677 ret = sizeof(qemu_mouse_config_descriptor);
678 } else if (s->kind == USB_TABLET) {
679 memcpy(data, qemu_tablet_config_descriptor,
680 sizeof(qemu_tablet_config_descriptor));
681 ret = sizeof(qemu_tablet_config_descriptor);
682 } else if (s->kind == USB_KEYBOARD) {
683 memcpy(data, qemu_keyboard_config_descriptor,
684 sizeof(qemu_keyboard_config_descriptor));
685 ret = sizeof(qemu_keyboard_config_descriptor);
687 break;
688 case USB_DT_STRING:
689 switch(value & 0xff) {
690 case 0:
691 /* language ids */
692 data[0] = 4;
693 data[1] = 3;
694 data[2] = 0x09;
695 data[3] = 0x04;
696 ret = 4;
697 break;
698 case 1:
699 /* serial number */
700 ret = set_usb_string(data, "1");
701 break;
702 case 2:
703 /* product description */
704 ret = set_usb_string(data, s->dev.devname);
705 break;
706 case 3:
707 /* vendor description */
708 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
709 break;
710 case 4:
711 ret = set_usb_string(data, "HID Mouse");
712 break;
713 case 5:
714 ret = set_usb_string(data, "HID Tablet");
715 break;
716 case 6:
717 ret = set_usb_string(data, "HID Keyboard");
718 break;
719 case 7:
720 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
721 break;
722 default:
723 goto fail;
725 break;
726 default:
727 goto fail;
729 break;
730 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
731 data[0] = 1;
732 ret = 1;
733 break;
734 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
735 ret = 0;
736 break;
737 case DeviceRequest | USB_REQ_GET_INTERFACE:
738 data[0] = 0;
739 ret = 1;
740 break;
741 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
742 ret = 0;
743 break;
744 /* hid specific requests */
745 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
746 switch(value >> 8) {
747 case 0x22:
748 if (s->kind == USB_MOUSE) {
749 memcpy(data, qemu_mouse_hid_report_descriptor,
750 sizeof(qemu_mouse_hid_report_descriptor));
751 ret = sizeof(qemu_mouse_hid_report_descriptor);
752 } else if (s->kind == USB_TABLET) {
753 memcpy(data, qemu_tablet_hid_report_descriptor,
754 sizeof(qemu_tablet_hid_report_descriptor));
755 ret = sizeof(qemu_tablet_hid_report_descriptor);
756 } else if (s->kind == USB_KEYBOARD) {
757 memcpy(data, qemu_keyboard_hid_report_descriptor,
758 sizeof(qemu_keyboard_hid_report_descriptor));
759 ret = sizeof(qemu_keyboard_hid_report_descriptor);
761 break;
762 default:
763 goto fail;
765 break;
766 case GET_REPORT:
767 if (s->kind == USB_MOUSE)
768 ret = usb_mouse_poll(s, data, length);
769 else if (s->kind == USB_TABLET)
770 ret = usb_tablet_poll(s, data, length);
771 else if (s->kind == USB_KEYBOARD)
772 ret = usb_keyboard_poll(&s->kbd, data, length);
773 break;
774 case SET_REPORT:
775 if (s->kind == USB_KEYBOARD)
776 ret = usb_keyboard_write(&s->kbd, data, length);
777 else
778 goto fail;
779 break;
780 case GET_PROTOCOL:
781 if (s->kind != USB_KEYBOARD)
782 goto fail;
783 ret = 1;
784 data[0] = s->protocol;
785 break;
786 case SET_PROTOCOL:
787 if (s->kind != USB_KEYBOARD)
788 goto fail;
789 ret = 0;
790 s->protocol = value;
791 break;
792 case GET_IDLE:
793 ret = 1;
794 data[0] = s->idle;
795 break;
796 case SET_IDLE:
797 s->idle = (uint8_t) (value >> 8);
798 ret = 0;
799 break;
800 default:
801 fail:
802 ret = USB_RET_STALL;
803 break;
805 return ret;
808 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
810 USBHIDState *s = (USBHIDState *)dev;
811 int ret = 0;
813 switch(p->pid) {
814 case USB_TOKEN_IN:
815 if (p->devep == 1) {
816 /* TODO: Implement finite idle delays. */
817 if (!(s->changed || s->idle))
818 return USB_RET_NAK;
819 s->changed = 0;
820 if (s->kind == USB_MOUSE)
821 ret = usb_mouse_poll(s, p->data, p->len);
822 else if (s->kind == USB_TABLET)
823 ret = usb_tablet_poll(s, p->data, p->len);
824 else if (s->kind == USB_KEYBOARD)
825 ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
826 } else {
827 goto fail;
829 break;
830 case USB_TOKEN_OUT:
831 default:
832 fail:
833 ret = USB_RET_STALL;
834 break;
836 return ret;
839 static void usb_hid_handle_destroy(USBDevice *dev)
841 USBHIDState *s = (USBHIDState *)dev;
843 if (s->kind != USB_KEYBOARD)
844 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
845 /* TODO: else */
846 qemu_free(s);
849 USBDevice *usb_tablet_init(void)
851 USBHIDState *s;
853 s = qemu_mallocz(sizeof(USBHIDState));
854 s->dev.speed = USB_SPEED_FULL;
855 s->dev.handle_packet = usb_generic_handle_packet;
857 s->dev.handle_reset = usb_mouse_handle_reset;
858 s->dev.handle_control = usb_hid_handle_control;
859 s->dev.handle_data = usb_hid_handle_data;
860 s->dev.handle_destroy = usb_hid_handle_destroy;
861 s->kind = USB_TABLET;
862 /* Force poll routine to be run and grab input the first time. */
863 s->changed = 1;
865 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
867 return (USBDevice *)s;
870 USBDevice *usb_mouse_init(void)
872 USBHIDState *s;
874 s = qemu_mallocz(sizeof(USBHIDState));
875 s->dev.speed = USB_SPEED_FULL;
876 s->dev.handle_packet = usb_generic_handle_packet;
878 s->dev.handle_reset = usb_mouse_handle_reset;
879 s->dev.handle_control = usb_hid_handle_control;
880 s->dev.handle_data = usb_hid_handle_data;
881 s->dev.handle_destroy = usb_hid_handle_destroy;
882 s->kind = USB_MOUSE;
883 /* Force poll routine to be run and grab input the first time. */
884 s->changed = 1;
886 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
888 return (USBDevice *)s;
891 USBDevice *usb_keyboard_init(void)
893 USBHIDState *s;
895 s = qemu_mallocz(sizeof(USBHIDState));
896 s->dev.speed = USB_SPEED_FULL;
897 s->dev.handle_packet = usb_generic_handle_packet;
899 s->dev.handle_reset = usb_keyboard_handle_reset;
900 s->dev.handle_control = usb_hid_handle_control;
901 s->dev.handle_data = usb_hid_handle_data;
902 s->dev.handle_destroy = usb_hid_handle_destroy;
903 s->kind = USB_KEYBOARD;
905 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");
907 return (USBDevice *) s;
910 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
912 USBHIDState *s = (USBHIDState *)dev;
914 s->datain_opaque = opaque;
915 s->datain = datain;