Use external clock in wm8750 slave mode.
[qemu/mini2440/sniper_sniper_test.git] / hw / usb-hid.c
blob068cbbfe9ae5102061a5c55ad0b90307efed8d77
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 int idle;
69 int changed;
70 } USBHIDState;
72 /* mostly the same values as the Bochs USB Mouse device */
73 static const uint8_t qemu_mouse_dev_descriptor[] = {
74 0x12, /* u8 bLength; */
75 0x01, /* u8 bDescriptorType; Device */
76 0x00, 0x01, /* u16 bcdUSB; v1.0 */
78 0x00, /* u8 bDeviceClass; */
79 0x00, /* u8 bDeviceSubClass; */
80 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
81 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
83 0x27, 0x06, /* u16 idVendor; */
84 0x01, 0x00, /* u16 idProduct; */
85 0x00, 0x00, /* u16 bcdDevice */
87 0x03, /* u8 iManufacturer; */
88 0x02, /* u8 iProduct; */
89 0x01, /* u8 iSerialNumber; */
90 0x01 /* u8 bNumConfigurations; */
93 static const uint8_t qemu_mouse_config_descriptor[] = {
94 /* one configuration */
95 0x09, /* u8 bLength; */
96 0x02, /* u8 bDescriptorType; Configuration */
97 0x22, 0x00, /* u16 wTotalLength; */
98 0x01, /* u8 bNumInterfaces; (1) */
99 0x01, /* u8 bConfigurationValue; */
100 0x04, /* u8 iConfiguration; */
101 0xa0, /* u8 bmAttributes;
102 Bit 7: must be set,
103 6: Self-powered,
104 5: Remote wakeup,
105 4..0: resvd */
106 50, /* u8 MaxPower; */
108 /* USB 1.1:
109 * USB 2.0, single TT organization (mandatory):
110 * one interface, protocol 0
112 * USB 2.0, multiple TT organization (optional):
113 * two interfaces, protocols 1 (like single TT)
114 * and 2 (multiple TT mode) ... config is
115 * sometimes settable
116 * NOT IMPLEMENTED
119 /* one interface */
120 0x09, /* u8 if_bLength; */
121 0x04, /* u8 if_bDescriptorType; Interface */
122 0x00, /* u8 if_bInterfaceNumber; */
123 0x00, /* u8 if_bAlternateSetting; */
124 0x01, /* u8 if_bNumEndpoints; */
125 0x03, /* u8 if_bInterfaceClass; */
126 0x01, /* u8 if_bInterfaceSubClass; */
127 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
128 0x07, /* u8 if_iInterface; */
130 /* HID descriptor */
131 0x09, /* u8 bLength; */
132 0x21, /* u8 bDescriptorType; */
133 0x01, 0x00, /* u16 HID_class */
134 0x00, /* u8 country_code */
135 0x01, /* u8 num_descriptors */
136 0x22, /* u8 type; Report */
137 52, 0, /* u16 len */
139 /* one endpoint (status change endpoint) */
140 0x07, /* u8 ep_bLength; */
141 0x05, /* u8 ep_bDescriptorType; Endpoint */
142 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
143 0x03, /* u8 ep_bmAttributes; Interrupt */
144 0x04, 0x00, /* u16 ep_wMaxPacketSize; */
145 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
148 static const uint8_t qemu_tablet_config_descriptor[] = {
149 /* one configuration */
150 0x09, /* u8 bLength; */
151 0x02, /* u8 bDescriptorType; Configuration */
152 0x22, 0x00, /* u16 wTotalLength; */
153 0x01, /* u8 bNumInterfaces; (1) */
154 0x01, /* u8 bConfigurationValue; */
155 0x05, /* u8 iConfiguration; */
156 0xa0, /* u8 bmAttributes;
157 Bit 7: must be set,
158 6: Self-powered,
159 5: Remote wakeup,
160 4..0: resvd */
161 50, /* u8 MaxPower; */
163 /* USB 1.1:
164 * USB 2.0, single TT organization (mandatory):
165 * one interface, protocol 0
167 * USB 2.0, multiple TT organization (optional):
168 * two interfaces, protocols 1 (like single TT)
169 * and 2 (multiple TT mode) ... config is
170 * sometimes settable
171 * NOT IMPLEMENTED
174 /* one interface */
175 0x09, /* u8 if_bLength; */
176 0x04, /* u8 if_bDescriptorType; Interface */
177 0x00, /* u8 if_bInterfaceNumber; */
178 0x00, /* u8 if_bAlternateSetting; */
179 0x01, /* u8 if_bNumEndpoints; */
180 0x03, /* u8 if_bInterfaceClass; */
181 0x01, /* u8 if_bInterfaceSubClass; */
182 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
183 0x07, /* u8 if_iInterface; */
185 /* HID descriptor */
186 0x09, /* u8 bLength; */
187 0x21, /* u8 bDescriptorType; */
188 0x01, 0x00, /* u16 HID_class */
189 0x00, /* u8 country_code */
190 0x01, /* u8 num_descriptors */
191 0x22, /* u8 type; Report */
192 74, 0, /* u16 len */
194 /* one endpoint (status change endpoint) */
195 0x07, /* u8 ep_bLength; */
196 0x05, /* u8 ep_bDescriptorType; Endpoint */
197 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
198 0x03, /* u8 ep_bmAttributes; Interrupt */
199 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
200 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
203 static const uint8_t qemu_keyboard_config_descriptor[] = {
204 /* one configuration */
205 0x09, /* u8 bLength; */
206 USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */
207 0x22, 0x00, /* u16 wTotalLength; */
208 0x01, /* u8 bNumInterfaces; (1) */
209 0x01, /* u8 bConfigurationValue; */
210 0x06, /* u8 iConfiguration; */
211 0xa0, /* u8 bmAttributes;
212 Bit 7: must be set,
213 6: Self-powered,
214 5: Remote wakeup,
215 4..0: resvd */
216 0x32, /* u8 MaxPower; */
218 /* USB 1.1:
219 * USB 2.0, single TT organization (mandatory):
220 * one interface, protocol 0
222 * USB 2.0, multiple TT organization (optional):
223 * two interfaces, protocols 1 (like single TT)
224 * and 2 (multiple TT mode) ... config is
225 * sometimes settable
226 * NOT IMPLEMENTED
229 /* one interface */
230 0x09, /* u8 if_bLength; */
231 USB_DT_INTERFACE, /* u8 if_bDescriptorType; Interface */
232 0x00, /* u8 if_bInterfaceNumber; */
233 0x00, /* u8 if_bAlternateSetting; */
234 0x01, /* u8 if_bNumEndpoints; */
235 0x03, /* u8 if_bInterfaceClass; HID */
236 0x01, /* u8 if_bInterfaceSubClass; Boot */
237 0x01, /* u8 if_bInterfaceProtocol; Keyboard */
238 0x07, /* u8 if_iInterface; */
240 /* HID descriptor */
241 0x09, /* u8 bLength; */
242 USB_DT_HID, /* u8 bDescriptorType; */
243 0x11, 0x01, /* u16 HID_class */
244 0x00, /* u8 country_code */
245 0x01, /* u8 num_descriptors */
246 USB_DT_REPORT, /* u8 type; Report */
247 0x3f, 0x00, /* u16 len */
249 /* one endpoint (status change endpoint) */
250 0x07, /* u8 ep_bLength; */
251 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; Endpoint */
252 USB_DIR_IN | 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
253 0x03, /* u8 ep_bmAttributes; Interrupt */
254 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
255 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
258 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
259 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01,
260 0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
261 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
262 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
263 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38,
264 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95, 0x03,
265 0x81, 0x06, 0xC0, 0xC0,
268 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
269 0x05, 0x01, /* Usage Page Generic Desktop */
270 0x09, 0x01, /* Usage Pointer */
271 0xA1, 0x01, /* Collection Application */
272 0x09, 0x01, /* Usage Pointer */
273 0xA1, 0x00, /* Collection Physical */
274 0x05, 0x09, /* Usage Page Button */
275 0x19, 0x01, /* Usage Minimum Button 1 */
276 0x29, 0x03, /* Usage Maximum Button 3 */
277 0x15, 0x00, /* Logical Minimum 0 */
278 0x25, 0x01, /* Logical Maximum 1 */
279 0x95, 0x03, /* Report Count 3 */
280 0x75, 0x01, /* Report Size 1 */
281 0x81, 0x02, /* Input (Data, Var, Abs) */
282 0x95, 0x01, /* Report Count 1 */
283 0x75, 0x05, /* Report Size 5 */
284 0x81, 0x01, /* Input (Cnst, Array, Abs) */
285 0x05, 0x01, /* Usage Page Generic Desktop */
286 0x09, 0x30, /* Usage X */
287 0x09, 0x31, /* Usage Y */
288 0x15, 0x00, /* Logical Minimum 0 */
289 0x26, 0xFF, 0x7F, /* Logical Maximum 0x7fff */
290 0x35, 0x00, /* Physical Minimum 0 */
291 0x46, 0xFE, 0x7F, /* Physical Maximum 0x7fff */
292 0x75, 0x10, /* Report Size 16 */
293 0x95, 0x02, /* Report Count 2 */
294 0x81, 0x02, /* Input (Data, Var, Abs) */
295 0x05, 0x01, /* Usage Page Generic Desktop */
296 0x09, 0x38, /* Usage Wheel */
297 0x15, 0x81, /* Logical Minimum -127 */
298 0x25, 0x7F, /* Logical Maximum 127 */
299 0x35, 0x00, /* Physical Minimum 0 (same as logical) */
300 0x45, 0x00, /* Physical Maximum 0 (same as logical) */
301 0x75, 0x08, /* Report Size 8 */
302 0x95, 0x01, /* Report Count 1 */
303 0x81, 0x06, /* Input (Data, Var, Rel) */
304 0xC0, /* End Collection */
305 0xC0, /* End Collection */
308 static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
309 0x05, 0x01, /* Usage Page (Generic Desktop) */
310 0x09, 0x06, /* Usage (Keyboard) */
311 0xa1, 0x01, /* Collection (Application) */
312 0x75, 0x01, /* Report Size (1) */
313 0x95, 0x08, /* Report Count (8) */
314 0x05, 0x07, /* Usage Page (Key Codes) */
315 0x19, 0xe0, /* Usage Minimum (224) */
316 0x29, 0xe7, /* Usage Maximum (231) */
317 0x15, 0x00, /* Logical Minimum (0) */
318 0x25, 0x01, /* Logical Maximum (1) */
319 0x81, 0x02, /* Input (Data, Variable, Absolute) */
320 0x95, 0x01, /* Report Count (1) */
321 0x75, 0x08, /* Report Size (8) */
322 0x81, 0x01, /* Input (Constant) */
323 0x95, 0x05, /* Report Count (5) */
324 0x75, 0x01, /* Report Size (1) */
325 0x05, 0x08, /* Usage Page (LEDs) */
326 0x19, 0x01, /* Usage Minimum (1) */
327 0x29, 0x05, /* Usage Maximum (5) */
328 0x91, 0x02, /* Output (Data, Variable, Absolute) */
329 0x95, 0x01, /* Report Count (1) */
330 0x75, 0x03, /* Report Size (3) */
331 0x91, 0x01, /* Output (Constant) */
332 0x95, 0x06, /* Report Count (6) */
333 0x75, 0x08, /* Report Size (8) */
334 0x15, 0x00, /* Logical Minimum (0) */
335 0x25, 0xff, /* Logical Maximum (255) */
336 0x05, 0x07, /* Usage Page (Key Codes) */
337 0x19, 0x00, /* Usage Minimum (0) */
338 0x29, 0xff, /* Usage Maximum (255) */
339 0x81, 0x00, /* Input (Data, Array) */
340 0xc0, /* End Collection */
343 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
344 #define USB_HID_USAGE_POSTFAIL 0x02
345 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
347 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
348 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
349 static const uint8_t usb_hid_usage_keys[0x100] = {
350 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
351 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
352 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
353 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
354 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
355 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
356 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
357 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
358 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
359 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
360 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
361 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
362 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x58, 0xe4, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
374 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
376 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
377 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 static void usb_mouse_event(void *opaque,
386 int dx1, int dy1, int dz1, int buttons_state)
388 USBHIDState *hs = opaque;
389 USBMouseState *s = &hs->ptr;
391 s->dx += dx1;
392 s->dy += dy1;
393 s->dz += dz1;
394 s->buttons_state = buttons_state;
395 hs->changed = 1;
398 static void usb_tablet_event(void *opaque,
399 int x, int y, int dz, int buttons_state)
401 USBHIDState *hs = opaque;
402 USBMouseState *s = &hs->ptr;
404 s->x = x;
405 s->y = y;
406 s->dz += dz;
407 s->buttons_state = buttons_state;
408 hs->changed = 1;
411 static void usb_keyboard_event(void *opaque, int keycode)
413 USBHIDState *hs = opaque;
414 USBKeyboardState *s = &hs->kbd;
415 uint8_t hid_code, key;
416 int i;
418 key = keycode & 0x7f;
419 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
420 s->modifiers &= ~(1 << 8);
422 hs->changed = 1;
424 switch (hid_code) {
425 case 0x00:
426 return;
428 case 0xe0:
429 if (s->modifiers & (1 << 9)) {
430 s->modifiers ^= 3 << 8;
431 return;
433 case 0xe1 ... 0xe7:
434 if (keycode & (1 << 7)) {
435 s->modifiers &= ~(1 << (hid_code & 0x0f));
436 return;
438 case 0xe8 ... 0xef:
439 s->modifiers |= 1 << (hid_code & 0x0f);
440 return;
443 if (keycode & (1 << 7)) {
444 for (i = s->keys - 1; i >= 0; i --)
445 if (s->key[i] == hid_code) {
446 s->key[i] = s->key[-- s->keys];
447 s->key[s->keys] = 0x00;
448 return;
450 } else {
451 for (i = s->keys - 1; i >= 0; i --)
452 if (s->key[i] == hid_code)
453 return;
454 if (s->keys < sizeof(s->key))
455 s->key[s->keys ++] = hid_code;
459 static inline int int_clamp(int val, int vmin, int vmax)
461 if (val < vmin)
462 return vmin;
463 else if (val > vmax)
464 return vmax;
465 else
466 return val;
469 static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
471 int dx, dy, dz, b, l;
472 USBMouseState *s = &hs->ptr;
474 if (!s->mouse_grabbed) {
475 s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, hs,
476 0, "QEMU USB Mouse");
477 s->mouse_grabbed = 1;
480 dx = int_clamp(s->dx, -128, 127);
481 dy = int_clamp(s->dy, -128, 127);
482 dz = int_clamp(s->dz, -128, 127);
484 s->dx -= dx;
485 s->dy -= dy;
486 s->dz -= dz;
488 b = 0;
489 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
490 b |= 0x01;
491 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
492 b |= 0x02;
493 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
494 b |= 0x04;
496 l = 0;
497 if (len > l)
498 buf[l ++] = b;
499 if (len > l)
500 buf[l ++] = dx;
501 if (len > l)
502 buf[l ++] = dy;
503 if (len > l)
504 buf[l ++] = dz;
505 return l;
508 static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
510 int dz, b, l;
511 USBMouseState *s = &hs->ptr;
513 if (!s->mouse_grabbed) {
514 s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs,
515 1, "QEMU USB Tablet");
516 s->mouse_grabbed = 1;
519 dz = int_clamp(s->dz, -128, 127);
520 s->dz -= dz;
522 /* Appears we have to invert the wheel direction */
523 dz = 0 - dz;
524 b = 0;
525 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
526 b |= 0x01;
527 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
528 b |= 0x02;
529 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
530 b |= 0x04;
532 buf[0] = b;
533 buf[1] = s->x & 0xff;
534 buf[2] = s->x >> 8;
535 buf[3] = s->y & 0xff;
536 buf[4] = s->y >> 8;
537 buf[5] = dz;
538 l = 6;
540 return l;
543 static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
545 if (len < 2)
546 return 0;
548 buf[0] = s->modifiers & 0xff;
549 buf[1] = 0;
550 if (s->keys > 6)
551 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
552 else
553 memcpy(buf + 2, s->key, MIN(8, len) - 2);
555 return MIN(8, len);
558 static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
560 if (len > 0) {
561 /* 0x01: Num Lock LED
562 * 0x02: Caps Lock LED
563 * 0x04: Scroll Lock LED
564 * 0x08: Compose LED
565 * 0x10: Kana LED */
566 s->leds = buf[0];
568 return 0;
571 static void usb_mouse_handle_reset(USBDevice *dev)
573 USBHIDState *s = (USBHIDState *)dev;
575 s->ptr.dx = 0;
576 s->ptr.dy = 0;
577 s->ptr.dz = 0;
578 s->ptr.x = 0;
579 s->ptr.y = 0;
580 s->ptr.buttons_state = 0;
581 s->protocol = 1;
584 static void usb_keyboard_handle_reset(USBDevice *dev)
586 USBHIDState *s = (USBHIDState *)dev;
588 qemu_add_kbd_event_handler(usb_keyboard_event, s);
589 s->protocol = 1;
592 static int usb_hid_handle_control(USBDevice *dev, int request, int value,
593 int index, int length, uint8_t *data)
595 USBHIDState *s = (USBHIDState *)dev;
596 int ret = 0;
598 switch(request) {
599 case DeviceRequest | USB_REQ_GET_STATUS:
600 data[0] = (1 << USB_DEVICE_SELF_POWERED) |
601 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
602 data[1] = 0x00;
603 ret = 2;
604 break;
605 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
606 if (value == USB_DEVICE_REMOTE_WAKEUP) {
607 dev->remote_wakeup = 0;
608 } else {
609 goto fail;
611 ret = 0;
612 break;
613 case DeviceOutRequest | USB_REQ_SET_FEATURE:
614 if (value == USB_DEVICE_REMOTE_WAKEUP) {
615 dev->remote_wakeup = 1;
616 } else {
617 goto fail;
619 ret = 0;
620 break;
621 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
622 dev->addr = value;
623 ret = 0;
624 break;
625 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
626 switch(value >> 8) {
627 case USB_DT_DEVICE:
628 memcpy(data, qemu_mouse_dev_descriptor,
629 sizeof(qemu_mouse_dev_descriptor));
630 ret = sizeof(qemu_mouse_dev_descriptor);
631 break;
632 case USB_DT_CONFIG:
633 if (s->kind == USB_MOUSE) {
634 memcpy(data, qemu_mouse_config_descriptor,
635 sizeof(qemu_mouse_config_descriptor));
636 ret = sizeof(qemu_mouse_config_descriptor);
637 } else if (s->kind == USB_TABLET) {
638 memcpy(data, qemu_tablet_config_descriptor,
639 sizeof(qemu_tablet_config_descriptor));
640 ret = sizeof(qemu_tablet_config_descriptor);
641 } else if (s->kind == USB_KEYBOARD) {
642 memcpy(data, qemu_keyboard_config_descriptor,
643 sizeof(qemu_keyboard_config_descriptor));
644 ret = sizeof(qemu_keyboard_config_descriptor);
646 break;
647 case USB_DT_STRING:
648 switch(value & 0xff) {
649 case 0:
650 /* language ids */
651 data[0] = 4;
652 data[1] = 3;
653 data[2] = 0x09;
654 data[3] = 0x04;
655 ret = 4;
656 break;
657 case 1:
658 /* serial number */
659 ret = set_usb_string(data, "1");
660 break;
661 case 2:
662 /* product description */
663 ret = set_usb_string(data, s->dev.devname);
664 break;
665 case 3:
666 /* vendor description */
667 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
668 break;
669 case 4:
670 ret = set_usb_string(data, "HID Mouse");
671 break;
672 case 5:
673 ret = set_usb_string(data, "HID Tablet");
674 break;
675 case 6:
676 ret = set_usb_string(data, "HID Keyboard");
677 break;
678 case 7:
679 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
680 break;
681 default:
682 goto fail;
684 break;
685 default:
686 goto fail;
688 break;
689 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
690 data[0] = 1;
691 ret = 1;
692 break;
693 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
694 ret = 0;
695 break;
696 case DeviceRequest | USB_REQ_GET_INTERFACE:
697 data[0] = 0;
698 ret = 1;
699 break;
700 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
701 ret = 0;
702 break;
703 /* hid specific requests */
704 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
705 switch(value >> 8) {
706 case 0x22:
707 if (s->kind == USB_MOUSE) {
708 memcpy(data, qemu_mouse_hid_report_descriptor,
709 sizeof(qemu_mouse_hid_report_descriptor));
710 ret = sizeof(qemu_mouse_hid_report_descriptor);
711 } else if (s->kind == USB_TABLET) {
712 memcpy(data, qemu_tablet_hid_report_descriptor,
713 sizeof(qemu_tablet_hid_report_descriptor));
714 ret = sizeof(qemu_tablet_hid_report_descriptor);
715 } else if (s->kind == USB_KEYBOARD) {
716 memcpy(data, qemu_keyboard_hid_report_descriptor,
717 sizeof(qemu_keyboard_hid_report_descriptor));
718 ret = sizeof(qemu_keyboard_hid_report_descriptor);
720 break;
721 default:
722 goto fail;
724 break;
725 case GET_REPORT:
726 if (s->kind == USB_MOUSE)
727 ret = usb_mouse_poll(s, data, length);
728 else if (s->kind == USB_TABLET)
729 ret = usb_tablet_poll(s, data, length);
730 else if (s->kind == USB_KEYBOARD)
731 ret = usb_keyboard_poll(&s->kbd, data, length);
732 break;
733 case SET_REPORT:
734 if (s->kind == USB_KEYBOARD)
735 ret = usb_keyboard_write(&s->kbd, data, length);
736 else
737 goto fail;
738 break;
739 case GET_PROTOCOL:
740 if (s->kind != USB_KEYBOARD)
741 goto fail;
742 ret = 1;
743 data[0] = s->protocol;
744 break;
745 case SET_PROTOCOL:
746 if (s->kind != USB_KEYBOARD)
747 goto fail;
748 ret = 0;
749 s->protocol = value;
750 break;
751 case GET_IDLE:
752 ret = 1;
753 data[0] = s->idle;
754 break;
755 case SET_IDLE:
756 s->idle = value;
757 ret = 0;
758 break;
759 default:
760 fail:
761 ret = USB_RET_STALL;
762 break;
764 return ret;
767 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
769 USBHIDState *s = (USBHIDState *)dev;
770 int ret = 0;
772 switch(p->pid) {
773 case USB_TOKEN_IN:
774 if (p->devep == 1) {
775 /* TODO: Implement finite idle delays. */
776 if (!(s->changed || s->idle))
777 return USB_RET_NAK;
778 s->changed = 0;
779 if (s->kind == USB_MOUSE)
780 ret = usb_mouse_poll(s, p->data, p->len);
781 else if (s->kind == USB_TABLET)
782 ret = usb_tablet_poll(s, p->data, p->len);
783 else if (s->kind == USB_KEYBOARD)
784 ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
785 } else {
786 goto fail;
788 break;
789 case USB_TOKEN_OUT:
790 default:
791 fail:
792 ret = USB_RET_STALL;
793 break;
795 return ret;
798 static void usb_hid_handle_destroy(USBDevice *dev)
800 USBHIDState *s = (USBHIDState *)dev;
802 if (s->kind != USB_KEYBOARD)
803 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
804 /* TODO: else */
805 qemu_free(s);
808 USBDevice *usb_tablet_init(void)
810 USBHIDState *s;
812 s = qemu_mallocz(sizeof(USBHIDState));
813 if (!s)
814 return NULL;
815 s->dev.speed = USB_SPEED_FULL;
816 s->dev.handle_packet = usb_generic_handle_packet;
818 s->dev.handle_reset = usb_mouse_handle_reset;
819 s->dev.handle_control = usb_hid_handle_control;
820 s->dev.handle_data = usb_hid_handle_data;
821 s->dev.handle_destroy = usb_hid_handle_destroy;
822 s->kind = USB_TABLET;
823 /* Force poll routine to be run and grab input the first time. */
824 s->changed = 1;
826 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
828 return (USBDevice *)s;
831 USBDevice *usb_mouse_init(void)
833 USBHIDState *s;
835 s = qemu_mallocz(sizeof(USBHIDState));
836 if (!s)
837 return NULL;
838 s->dev.speed = USB_SPEED_FULL;
839 s->dev.handle_packet = usb_generic_handle_packet;
841 s->dev.handle_reset = usb_mouse_handle_reset;
842 s->dev.handle_control = usb_hid_handle_control;
843 s->dev.handle_data = usb_hid_handle_data;
844 s->dev.handle_destroy = usb_hid_handle_destroy;
845 s->kind = USB_MOUSE;
846 /* Force poll routine to be run and grab input the first time. */
847 s->changed = 1;
849 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
851 return (USBDevice *)s;
854 USBDevice *usb_keyboard_init(void)
856 USBHIDState *s;
858 s = qemu_mallocz(sizeof(USBHIDState));
859 if (!s)
860 return NULL;
861 s->dev.speed = USB_SPEED_FULL;
862 s->dev.handle_packet = usb_generic_handle_packet;
864 s->dev.handle_reset = usb_keyboard_handle_reset;
865 s->dev.handle_control = usb_hid_handle_control;
866 s->dev.handle_data = usb_hid_handle_data;
867 s->dev.handle_destroy = usb_hid_handle_destroy;
868 s->kind = USB_KEYBOARD;
870 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");
872 return (USBDevice *) s;