Fix typo in comment, by Andreas Faerber.
[qemu/dscho.git] / hw / usb-hid.c
blob43fc47e9cb5a26deca628618083e2c6a859c74d7
1 /*
2 * QEMU USB HID devices
3 *
4 * Copyright (c) 2005 Fabrice Bellard
5 * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com)
6 *
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 "vl.h"
27 /* HID interface requests */
28 #define GET_REPORT 0xa101
29 #define GET_IDLE 0xa102
30 #define GET_PROTOCOL 0xa103
31 #define SET_REPORT 0x2109
32 #define SET_IDLE 0x210a
33 #define SET_PROTOCOL 0x210b
35 /* HID descriptor types */
36 #define USB_DT_HID 0x21
37 #define USB_DT_REPORT 0x22
38 #define USB_DT_PHY 0x23
40 #define USB_MOUSE 1
41 #define USB_TABLET 2
42 #define USB_KEYBOARD 3
44 typedef struct USBMouseState {
45 int dx, dy, dz, buttons_state;
46 int x, y;
47 int mouse_grabbed;
48 QEMUPutMouseEntry *eh_entry;
49 } USBMouseState;
51 typedef struct USBKeyboardState {
52 uint16_t modifiers;
53 uint8_t leds;
54 uint8_t key[16];
55 int keys;
56 } USBKeyboardState;
58 typedef struct USBHIDState {
59 USBDevice dev;
60 union {
61 USBMouseState ptr;
62 USBKeyboardState kbd;
64 int kind;
65 int protocol;
66 int idle;
67 } USBHIDState;
69 /* mostly the same values as the Bochs USB Mouse device */
70 static const uint8_t qemu_mouse_dev_descriptor[] = {
71 0x12, /* u8 bLength; */
72 0x01, /* u8 bDescriptorType; Device */
73 0x00, 0x01, /* u16 bcdUSB; v1.0 */
75 0x00, /* u8 bDeviceClass; */
76 0x00, /* u8 bDeviceSubClass; */
77 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
78 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
80 0x27, 0x06, /* u16 idVendor; */
81 0x01, 0x00, /* u16 idProduct; */
82 0x00, 0x00, /* u16 bcdDevice */
84 0x03, /* u8 iManufacturer; */
85 0x02, /* u8 iProduct; */
86 0x01, /* u8 iSerialNumber; */
87 0x01 /* u8 bNumConfigurations; */
90 static const uint8_t qemu_mouse_config_descriptor[] = {
91 /* one configuration */
92 0x09, /* u8 bLength; */
93 0x02, /* u8 bDescriptorType; Configuration */
94 0x22, 0x00, /* u16 wTotalLength; */
95 0x01, /* u8 bNumInterfaces; (1) */
96 0x01, /* u8 bConfigurationValue; */
97 0x04, /* u8 iConfiguration; */
98 0xa0, /* u8 bmAttributes;
99 Bit 7: must be set,
100 6: Self-powered,
101 5: Remote wakeup,
102 4..0: resvd */
103 50, /* u8 MaxPower; */
105 /* USB 1.1:
106 * USB 2.0, single TT organization (mandatory):
107 * one interface, protocol 0
109 * USB 2.0, multiple TT organization (optional):
110 * two interfaces, protocols 1 (like single TT)
111 * and 2 (multiple TT mode) ... config is
112 * sometimes settable
113 * NOT IMPLEMENTED
116 /* one interface */
117 0x09, /* u8 if_bLength; */
118 0x04, /* u8 if_bDescriptorType; Interface */
119 0x00, /* u8 if_bInterfaceNumber; */
120 0x00, /* u8 if_bAlternateSetting; */
121 0x01, /* u8 if_bNumEndpoints; */
122 0x03, /* u8 if_bInterfaceClass; */
123 0x01, /* u8 if_bInterfaceSubClass; */
124 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
125 0x07, /* u8 if_iInterface; */
127 /* HID descriptor */
128 0x09, /* u8 bLength; */
129 0x21, /* u8 bDescriptorType; */
130 0x01, 0x00, /* u16 HID_class */
131 0x00, /* u8 country_code */
132 0x01, /* u8 num_descriptors */
133 0x22, /* u8 type; Report */
134 50, 0, /* u16 len */
136 /* one endpoint (status change endpoint) */
137 0x07, /* u8 ep_bLength; */
138 0x05, /* u8 ep_bDescriptorType; Endpoint */
139 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
140 0x03, /* u8 ep_bmAttributes; Interrupt */
141 0x03, 0x00, /* u16 ep_wMaxPacketSize; */
142 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
145 static const uint8_t qemu_tablet_config_descriptor[] = {
146 /* one configuration */
147 0x09, /* u8 bLength; */
148 0x02, /* u8 bDescriptorType; Configuration */
149 0x22, 0x00, /* u16 wTotalLength; */
150 0x01, /* u8 bNumInterfaces; (1) */
151 0x01, /* u8 bConfigurationValue; */
152 0x05, /* u8 iConfiguration; */
153 0xa0, /* u8 bmAttributes;
154 Bit 7: must be set,
155 6: Self-powered,
156 5: Remote wakeup,
157 4..0: resvd */
158 50, /* u8 MaxPower; */
160 /* USB 1.1:
161 * USB 2.0, single TT organization (mandatory):
162 * one interface, protocol 0
164 * USB 2.0, multiple TT organization (optional):
165 * two interfaces, protocols 1 (like single TT)
166 * and 2 (multiple TT mode) ... config is
167 * sometimes settable
168 * NOT IMPLEMENTED
171 /* one interface */
172 0x09, /* u8 if_bLength; */
173 0x04, /* u8 if_bDescriptorType; Interface */
174 0x00, /* u8 if_bInterfaceNumber; */
175 0x00, /* u8 if_bAlternateSetting; */
176 0x01, /* u8 if_bNumEndpoints; */
177 0x03, /* u8 if_bInterfaceClass; */
178 0x01, /* u8 if_bInterfaceSubClass; */
179 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
180 0x07, /* u8 if_iInterface; */
182 /* HID descriptor */
183 0x09, /* u8 bLength; */
184 0x21, /* u8 bDescriptorType; */
185 0x01, 0x00, /* u16 HID_class */
186 0x00, /* u8 country_code */
187 0x01, /* u8 num_descriptors */
188 0x22, /* u8 type; Report */
189 74, 0, /* u16 len */
191 /* one endpoint (status change endpoint) */
192 0x07, /* u8 ep_bLength; */
193 0x05, /* u8 ep_bDescriptorType; Endpoint */
194 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
195 0x03, /* u8 ep_bmAttributes; Interrupt */
196 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
197 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
200 static const uint8_t qemu_keyboard_config_descriptor[] = {
201 /* one configuration */
202 0x09, /* u8 bLength; */
203 USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */
204 0x22, 0x00, /* u16 wTotalLength; */
205 0x01, /* u8 bNumInterfaces; (1) */
206 0x01, /* u8 bConfigurationValue; */
207 0x06, /* u8 iConfiguration; */
208 0xa0, /* u8 bmAttributes;
209 Bit 7: must be set,
210 6: Self-powered,
211 5: Remote wakeup,
212 4..0: resvd */
213 0x32, /* u8 MaxPower; */
215 /* USB 1.1:
216 * USB 2.0, single TT organization (mandatory):
217 * one interface, protocol 0
219 * USB 2.0, multiple TT organization (optional):
220 * two interfaces, protocols 1 (like single TT)
221 * and 2 (multiple TT mode) ... config is
222 * sometimes settable
223 * NOT IMPLEMENTED
226 /* one interface */
227 0x09, /* u8 if_bLength; */
228 USB_DT_INTERFACE, /* u8 if_bDescriptorType; Interface */
229 0x00, /* u8 if_bInterfaceNumber; */
230 0x00, /* u8 if_bAlternateSetting; */
231 0x01, /* u8 if_bNumEndpoints; */
232 0x03, /* u8 if_bInterfaceClass; HID */
233 0x01, /* u8 if_bInterfaceSubClass; Boot */
234 0x01, /* u8 if_bInterfaceProtocol; Keyboard */
235 0x07, /* u8 if_iInterface; */
237 /* HID descriptor */
238 0x09, /* u8 bLength; */
239 USB_DT_HID, /* u8 bDescriptorType; */
240 0x11, 0x01, /* u16 HID_class */
241 0x00, /* u8 country_code */
242 0x01, /* u8 num_descriptors */
243 USB_DT_REPORT, /* u8 type; Report */
244 0x3f, 0x00, /* u16 len */
246 /* one endpoint (status change endpoint) */
247 0x07, /* u8 ep_bLength; */
248 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; Endpoint */
249 USB_DIR_IN | 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
250 0x03, /* u8 ep_bmAttributes; Interrupt */
251 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
252 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
255 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
256 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01,
257 0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
258 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
259 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
260 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81,
261 0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
262 0xC0, 0xC0,
265 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
266 0x05, 0x01, /* Usage Page Generic Desktop */
267 0x09, 0x01, /* Usage Mouse */
268 0xA1, 0x01, /* Collection Application */
269 0x09, 0x01, /* Usage Pointer */
270 0xA1, 0x00, /* Collection Physical */
271 0x05, 0x09, /* Usage Page Button */
272 0x19, 0x01, /* Usage Minimum Button 1 */
273 0x29, 0x03, /* Usage Maximum Button 3 */
274 0x15, 0x00, /* Logical Minimum 0 */
275 0x25, 0x01, /* Logical Maximum 1 */
276 0x95, 0x03, /* Report Count 3 */
277 0x75, 0x01, /* Report Size 1 */
278 0x81, 0x02, /* Input (Data, Var, Abs) */
279 0x95, 0x01, /* Report Count 1 */
280 0x75, 0x05, /* Report Size 5 */
281 0x81, 0x01, /* Input (Cnst, Var, Abs) */
282 0x05, 0x01, /* Usage Page Generic Desktop */
283 0x09, 0x30, /* Usage X */
284 0x09, 0x31, /* Usage Y */
285 0x15, 0x00, /* Logical Minimum 0 */
286 0x26, 0xFF, 0x7F, /* Logical Maximum 0x7fff */
287 0x35, 0x00, /* Physical Minimum 0 */
288 0x46, 0xFE, 0x7F, /* Physical Maximum 0x7fff */
289 0x75, 0x10, /* Report Size 16 */
290 0x95, 0x02, /* Report Count 2 */
291 0x81, 0x02, /* Input (Data, Var, Abs) */
292 0x05, 0x01, /* Usage Page Generic Desktop */
293 0x09, 0x38, /* Usage Wheel */
294 0x15, 0x81, /* Logical Minimum -127 */
295 0x25, 0x7F, /* Logical Maximum 127 */
296 0x35, 0x00, /* Physical Minimum 0 (same as logical) */
297 0x45, 0x00, /* Physical Maximum 0 (same as logical) */
298 0x75, 0x08, /* Report Size 8 */
299 0x95, 0x01, /* Report Count 1 */
300 0x81, 0x02, /* Input (Data, Var, Rel) */
301 0xC0, /* End Collection */
302 0xC0, /* End Collection */
305 static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
306 0x05, 0x01, /* Usage Page (Generic Desktop) */
307 0x09, 0x06, /* Usage (Keyboard) */
308 0xa1, 0x01, /* Collection (Application) */
309 0x75, 0x01, /* Report Size (1) */
310 0x95, 0x08, /* Report Count (8) */
311 0x05, 0x07, /* Usage Page (Key Codes) */
312 0x19, 0xe0, /* Usage Minimum (224) */
313 0x29, 0xe7, /* Usage Maximum (231) */
314 0x15, 0x00, /* Logical Minimum (0) */
315 0x25, 0x01, /* Logical Maximum (1) */
316 0x81, 0x02, /* Input (Data, Variable, Absolute) */
317 0x95, 0x01, /* Report Count (1) */
318 0x75, 0x08, /* Report Size (8) */
319 0x81, 0x01, /* Input (Constant) */
320 0x95, 0x05, /* Report Count (5) */
321 0x75, 0x01, /* Report Size (1) */
322 0x05, 0x08, /* Usage Page (LEDs) */
323 0x19, 0x01, /* Usage Minimum (1) */
324 0x29, 0x05, /* Usage Maximum (5) */
325 0x91, 0x02, /* Output (Data, Variable, Absolute) */
326 0x95, 0x01, /* Report Count (1) */
327 0x75, 0x03, /* Report Size (3) */
328 0x91, 0x01, /* Output (Constant) */
329 0x95, 0x06, /* Report Count (6) */
330 0x75, 0x08, /* Report Size (8) */
331 0x15, 0x00, /* Logical Minimum (0) */
332 0x25, 0xff, /* Logical Maximum (255) */
333 0x05, 0x07, /* Usage Page (Key Codes) */
334 0x19, 0x00, /* Usage Minimum (0) */
335 0x29, 0xff, /* Usage Maximum (255) */
336 0x81, 0x00, /* Input (Data, Array) */
337 0xc0, /* End Collection */
340 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
341 #define USB_HID_USAGE_POSTFAIL 0x02
342 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
344 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
345 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
346 static const uint8_t usb_hid_usage_keys[0x100] = {
347 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
348 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
349 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
350 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
351 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
352 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
353 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
354 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
355 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
356 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
357 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
358 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
359 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
371 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
373 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
374 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 static void usb_mouse_event(void *opaque,
383 int dx1, int dy1, int dz1, int buttons_state)
385 USBMouseState *s = opaque;
387 s->dx += dx1;
388 s->dy += dy1;
389 s->dz += dz1;
390 s->buttons_state = buttons_state;
393 static void usb_tablet_event(void *opaque,
394 int x, int y, int dz, int buttons_state)
396 USBMouseState *s = opaque;
398 s->x = x;
399 s->y = y;
400 s->dz += dz;
401 s->buttons_state = buttons_state;
404 static void usb_keyboard_event(void *opaque, int keycode)
406 USBKeyboardState *s = opaque;
407 uint8_t hid_code, key;
408 int i;
410 key = keycode & 0x7f;
411 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
412 s->modifiers &= ~(1 << 8);
414 switch (hid_code) {
415 case 0x00:
416 return;
418 case 0xe0:
419 if (s->modifiers & (1 << 9)) {
420 s->modifiers ^= 3 << 8;
421 return;
423 case 0xe1 ... 0xe7:
424 if (keycode & (1 << 7)) {
425 s->modifiers &= ~(1 << (hid_code & 0x0f));
426 return;
428 case 0xe8 ... 0xef:
429 s->modifiers |= 1 << (hid_code & 0x0f);
430 return;
433 if (keycode & (1 << 7)) {
434 for (i = s->keys - 1; i >= 0; i --)
435 if (s->key[i] == hid_code) {
436 s->key[i] = s->key[-- s->keys];
437 s->key[s->keys] = 0x00;
438 return;
440 } else {
441 for (i = s->keys - 1; i >= 0; i --)
442 if (s->key[i] == hid_code)
443 return;
444 if (s->keys < sizeof(s->key))
445 s->key[s->keys ++] = hid_code;
449 static inline int int_clamp(int val, int vmin, int vmax)
451 if (val < vmin)
452 return vmin;
453 else if (val > vmax)
454 return vmax;
455 else
456 return val;
459 static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
461 int dx, dy, dz, b, l;
463 if (!s->mouse_grabbed) {
464 s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
465 0, "QEMU USB Mouse");
466 s->mouse_grabbed = 1;
469 dx = int_clamp(s->dx, -128, 127);
470 dy = int_clamp(s->dy, -128, 127);
471 dz = int_clamp(s->dz, -128, 127);
473 s->dx -= dx;
474 s->dy -= dy;
475 s->dz -= dz;
477 b = 0;
478 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
479 b |= 0x01;
480 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
481 b |= 0x02;
482 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
483 b |= 0x04;
485 buf[0] = b;
486 buf[1] = dx;
487 buf[2] = dy;
488 l = 3;
489 if (len >= 4) {
490 buf[3] = dz;
491 l = 4;
493 return l;
496 static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
498 int dz, b, l;
500 if (!s->mouse_grabbed) {
501 s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
502 1, "QEMU USB Tablet");
503 s->mouse_grabbed = 1;
506 dz = int_clamp(s->dz, -128, 127);
507 s->dz -= dz;
509 /* Appears we have to invert the wheel direction */
510 dz = 0 - dz;
511 b = 0;
512 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
513 b |= 0x01;
514 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
515 b |= 0x02;
516 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
517 b |= 0x04;
519 buf[0] = b;
520 buf[1] = s->x & 0xff;
521 buf[2] = s->x >> 8;
522 buf[3] = s->y & 0xff;
523 buf[4] = s->y >> 8;
524 buf[5] = dz;
525 l = 6;
527 return l;
530 static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
532 if (len < 2)
533 return 0;
535 buf[0] = s->modifiers & 0xff;
536 buf[1] = 0;
537 if (s->keys > 6)
538 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
539 else
540 memcpy(buf + 2, s->key, MIN(8, len) - 2);
542 return MIN(8, len);
545 static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
547 if (len > 0) {
548 /* 0x01: Num Lock LED
549 * 0x02: Caps Lock LED
550 * 0x04: Scroll Lock LED
551 * 0x08: Compose LED
552 * 0x10: Kana LED */
553 s->leds = buf[0];
555 return 0;
558 static void usb_mouse_handle_reset(USBDevice *dev)
560 USBHIDState *s = (USBHIDState *)dev;
562 s->ptr.dx = 0;
563 s->ptr.dy = 0;
564 s->ptr.dz = 0;
565 s->ptr.x = 0;
566 s->ptr.y = 0;
567 s->ptr.buttons_state = 0;
568 s->protocol = 1;
571 static void usb_keyboard_handle_reset(USBDevice *dev)
573 USBHIDState *s = (USBHIDState *)dev;
575 qemu_add_kbd_event_handler(usb_keyboard_event, &s->kbd);
576 s->protocol = 1;
579 static int usb_hid_handle_control(USBDevice *dev, int request, int value,
580 int index, int length, uint8_t *data)
582 USBHIDState *s = (USBHIDState *)dev;
583 int ret = 0;
585 switch(request) {
586 case DeviceRequest | USB_REQ_GET_STATUS:
587 data[0] = (1 << USB_DEVICE_SELF_POWERED) |
588 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
589 data[1] = 0x00;
590 ret = 2;
591 break;
592 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
593 if (value == USB_DEVICE_REMOTE_WAKEUP) {
594 dev->remote_wakeup = 0;
595 } else {
596 goto fail;
598 ret = 0;
599 break;
600 case DeviceOutRequest | USB_REQ_SET_FEATURE:
601 if (value == USB_DEVICE_REMOTE_WAKEUP) {
602 dev->remote_wakeup = 1;
603 } else {
604 goto fail;
606 ret = 0;
607 break;
608 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
609 dev->addr = value;
610 ret = 0;
611 break;
612 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
613 switch(value >> 8) {
614 case USB_DT_DEVICE:
615 memcpy(data, qemu_mouse_dev_descriptor,
616 sizeof(qemu_mouse_dev_descriptor));
617 ret = sizeof(qemu_mouse_dev_descriptor);
618 break;
619 case USB_DT_CONFIG:
620 if (s->kind == USB_MOUSE) {
621 memcpy(data, qemu_mouse_config_descriptor,
622 sizeof(qemu_mouse_config_descriptor));
623 ret = sizeof(qemu_mouse_config_descriptor);
624 } else if (s->kind == USB_TABLET) {
625 memcpy(data, qemu_tablet_config_descriptor,
626 sizeof(qemu_tablet_config_descriptor));
627 ret = sizeof(qemu_tablet_config_descriptor);
628 } else if (s->kind == USB_KEYBOARD) {
629 memcpy(data, qemu_keyboard_config_descriptor,
630 sizeof(qemu_keyboard_config_descriptor));
631 ret = sizeof(qemu_keyboard_config_descriptor);
633 break;
634 case USB_DT_STRING:
635 switch(value & 0xff) {
636 case 0:
637 /* language ids */
638 data[0] = 4;
639 data[1] = 3;
640 data[2] = 0x09;
641 data[3] = 0x04;
642 ret = 4;
643 break;
644 case 1:
645 /* serial number */
646 ret = set_usb_string(data, "1");
647 break;
648 case 2:
649 /* product description */
650 ret = set_usb_string(data, s->dev.devname);
651 break;
652 case 3:
653 /* vendor description */
654 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
655 break;
656 case 4:
657 ret = set_usb_string(data, "HID Mouse");
658 break;
659 case 5:
660 ret = set_usb_string(data, "HID Tablet");
661 break;
662 case 6:
663 ret = set_usb_string(data, "HID Keyboard");
664 break;
665 case 7:
666 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
667 break;
668 default:
669 goto fail;
671 break;
672 default:
673 goto fail;
675 break;
676 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
677 data[0] = 1;
678 ret = 1;
679 break;
680 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
681 ret = 0;
682 break;
683 case DeviceRequest | USB_REQ_GET_INTERFACE:
684 data[0] = 0;
685 ret = 1;
686 break;
687 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
688 ret = 0;
689 break;
690 /* hid specific requests */
691 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
692 switch(value >> 8) {
693 case 0x22:
694 if (s->kind == USB_MOUSE) {
695 memcpy(data, qemu_mouse_hid_report_descriptor,
696 sizeof(qemu_mouse_hid_report_descriptor));
697 ret = sizeof(qemu_mouse_hid_report_descriptor);
698 } else if (s->kind == USB_TABLET) {
699 memcpy(data, qemu_tablet_hid_report_descriptor,
700 sizeof(qemu_tablet_hid_report_descriptor));
701 ret = sizeof(qemu_tablet_hid_report_descriptor);
702 } else if (s->kind == USB_KEYBOARD) {
703 memcpy(data, qemu_keyboard_hid_report_descriptor,
704 sizeof(qemu_keyboard_hid_report_descriptor));
705 ret = sizeof(qemu_keyboard_hid_report_descriptor);
707 break;
708 default:
709 goto fail;
711 break;
712 case GET_REPORT:
713 if (s->kind == USB_MOUSE)
714 ret = usb_mouse_poll(&s->ptr, data, length);
715 else if (s->kind == USB_TABLET)
716 ret = usb_tablet_poll(&s->ptr, data, length);
717 else if (s->kind == USB_KEYBOARD)
718 ret = usb_keyboard_poll(&s->kbd, data, length);
719 break;
720 case SET_REPORT:
721 if (s->kind == USB_KEYBOARD)
722 ret = usb_keyboard_write(&s->kbd, data, length);
723 else
724 goto fail;
725 break;
726 case GET_PROTOCOL:
727 if (s->kind != USB_KEYBOARD)
728 goto fail;
729 ret = 1;
730 data[0] = s->protocol;
731 break;
732 case SET_PROTOCOL:
733 if (s->kind != USB_KEYBOARD)
734 goto fail;
735 ret = 0;
736 s->protocol = value;
737 break;
738 case GET_IDLE:
739 ret = 1;
740 data[0] = s->idle;
741 break;
742 case SET_IDLE:
743 s->idle = value;
744 ret = 0;
745 break;
746 default:
747 fail:
748 ret = USB_RET_STALL;
749 break;
751 return ret;
754 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
756 USBHIDState *s = (USBHIDState *)dev;
757 int ret = 0;
759 switch(p->pid) {
760 case USB_TOKEN_IN:
761 if (p->devep == 1) {
762 if (s->kind == USB_MOUSE)
763 ret = usb_mouse_poll(&s->ptr, p->data, p->len);
764 else if (s->kind == USB_TABLET)
765 ret = usb_tablet_poll(&s->ptr, p->data, p->len);
766 else if (s->kind == USB_KEYBOARD)
767 ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
768 } else {
769 goto fail;
771 break;
772 case USB_TOKEN_OUT:
773 default:
774 fail:
775 ret = USB_RET_STALL;
776 break;
778 return ret;
781 static void usb_hid_handle_destroy(USBDevice *dev)
783 USBHIDState *s = (USBHIDState *)dev;
785 if (s->kind != USB_KEYBOARD)
786 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
787 /* TODO: else */
788 qemu_free(s);
791 USBDevice *usb_tablet_init(void)
793 USBHIDState *s;
795 s = qemu_mallocz(sizeof(USBHIDState));
796 if (!s)
797 return NULL;
798 s->dev.speed = USB_SPEED_FULL;
799 s->dev.handle_packet = usb_generic_handle_packet;
801 s->dev.handle_reset = usb_mouse_handle_reset;
802 s->dev.handle_control = usb_hid_handle_control;
803 s->dev.handle_data = usb_hid_handle_data;
804 s->dev.handle_destroy = usb_hid_handle_destroy;
805 s->kind = USB_TABLET;
807 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
809 return (USBDevice *)s;
812 USBDevice *usb_mouse_init(void)
814 USBHIDState *s;
816 s = qemu_mallocz(sizeof(USBHIDState));
817 if (!s)
818 return NULL;
819 s->dev.speed = USB_SPEED_FULL;
820 s->dev.handle_packet = usb_generic_handle_packet;
822 s->dev.handle_reset = usb_mouse_handle_reset;
823 s->dev.handle_control = usb_hid_handle_control;
824 s->dev.handle_data = usb_hid_handle_data;
825 s->dev.handle_destroy = usb_hid_handle_destroy;
826 s->kind = USB_MOUSE;
828 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
830 return (USBDevice *)s;
833 USBDevice *usb_keyboard_init(void)
835 USBHIDState *s;
837 s = qemu_mallocz(sizeof(USBHIDState));
838 if (!s)
839 return NULL;
840 s->dev.speed = USB_SPEED_FULL;
841 s->dev.handle_packet = usb_generic_handle_packet;
843 s->dev.handle_reset = usb_keyboard_handle_reset;
844 s->dev.handle_control = usb_hid_handle_control;
845 s->dev.handle_data = usb_hid_handle_data;
846 s->dev.handle_destroy = usb_hid_handle_destroy;
847 s->kind = USB_KEYBOARD;
849 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");
851 return (USBDevice *) s;