scsi-disk: propagate the required alignment
[qemu/kevin.git] / hw / usb-hid.c
blob882d93346645ba79536aa03c899e3100ae7af9f1
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"
28 #include "sysemu.h"
30 /* HID interface requests */
31 #define GET_REPORT 0xa101
32 #define GET_IDLE 0xa102
33 #define GET_PROTOCOL 0xa103
34 #define SET_REPORT 0x2109
35 #define SET_IDLE 0x210a
36 #define SET_PROTOCOL 0x210b
38 /* HID descriptor types */
39 #define USB_DT_HID 0x21
40 #define USB_DT_REPORT 0x22
41 #define USB_DT_PHY 0x23
43 #define USB_MOUSE 1
44 #define USB_TABLET 2
45 #define USB_KEYBOARD 3
47 typedef struct USBMouseState {
48 int dx, dy, dz, buttons_state;
49 int x, y;
50 int mouse_grabbed;
51 QEMUPutMouseEntry *eh_entry;
52 } USBMouseState;
54 typedef struct USBKeyboardState {
55 uint16_t modifiers;
56 uint8_t leds;
57 uint8_t key[16];
58 int keys;
59 } USBKeyboardState;
61 typedef struct USBHIDState {
62 USBDevice dev;
63 union {
64 USBMouseState ptr;
65 USBKeyboardState kbd;
67 int kind;
68 int protocol;
69 uint8_t idle;
70 int64_t next_idle_clock;
71 int changed;
72 void *datain_opaque;
73 void (*datain)(void *);
74 } USBHIDState;
76 /* mostly the same values as the Bochs USB Mouse device */
77 static const uint8_t qemu_mouse_dev_descriptor[] = {
78 0x12, /* u8 bLength; */
79 0x01, /* u8 bDescriptorType; Device */
80 0x00, 0x01, /* u16 bcdUSB; v1.0 */
82 0x00, /* u8 bDeviceClass; */
83 0x00, /* u8 bDeviceSubClass; */
84 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
85 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
87 0x27, 0x06, /* u16 idVendor; */
88 0x01, 0x00, /* u16 idProduct; */
89 0x00, 0x00, /* u16 bcdDevice */
91 0x03, /* u8 iManufacturer; */
92 0x02, /* u8 iProduct; */
93 0x01, /* u8 iSerialNumber; */
94 0x01 /* u8 bNumConfigurations; */
97 static const uint8_t qemu_mouse_config_descriptor[] = {
98 /* one configuration */
99 0x09, /* u8 bLength; */
100 0x02, /* u8 bDescriptorType; Configuration */
101 0x22, 0x00, /* u16 wTotalLength; */
102 0x01, /* u8 bNumInterfaces; (1) */
103 0x01, /* u8 bConfigurationValue; */
104 0x04, /* u8 iConfiguration; */
105 0xe0, /* u8 bmAttributes;
106 Bit 7: must be set,
107 6: Self-powered,
108 5: Remote wakeup,
109 4..0: resvd */
110 50, /* u8 MaxPower; */
112 /* USB 1.1:
113 * USB 2.0, single TT organization (mandatory):
114 * one interface, protocol 0
116 * USB 2.0, multiple TT organization (optional):
117 * two interfaces, protocols 1 (like single TT)
118 * and 2 (multiple TT mode) ... config is
119 * sometimes settable
120 * NOT IMPLEMENTED
123 /* one interface */
124 0x09, /* u8 if_bLength; */
125 0x04, /* u8 if_bDescriptorType; Interface */
126 0x00, /* u8 if_bInterfaceNumber; */
127 0x00, /* u8 if_bAlternateSetting; */
128 0x01, /* u8 if_bNumEndpoints; */
129 0x03, /* u8 if_bInterfaceClass; */
130 0x01, /* u8 if_bInterfaceSubClass; */
131 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
132 0x07, /* u8 if_iInterface; */
134 /* HID descriptor */
135 0x09, /* u8 bLength; */
136 0x21, /* u8 bDescriptorType; */
137 0x01, 0x00, /* u16 HID_class */
138 0x00, /* u8 country_code */
139 0x01, /* u8 num_descriptors */
140 0x22, /* u8 type; Report */
141 52, 0, /* u16 len */
143 /* one endpoint (status change endpoint) */
144 0x07, /* u8 ep_bLength; */
145 0x05, /* u8 ep_bDescriptorType; Endpoint */
146 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
147 0x03, /* u8 ep_bmAttributes; Interrupt */
148 0x04, 0x00, /* u16 ep_wMaxPacketSize; */
149 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
152 static const uint8_t qemu_tablet_config_descriptor[] = {
153 /* one configuration */
154 0x09, /* u8 bLength; */
155 0x02, /* u8 bDescriptorType; Configuration */
156 0x22, 0x00, /* u16 wTotalLength; */
157 0x01, /* u8 bNumInterfaces; (1) */
158 0x01, /* u8 bConfigurationValue; */
159 0x05, /* u8 iConfiguration; */
160 0xa0, /* u8 bmAttributes;
161 Bit 7: must be set,
162 6: Self-powered,
163 5: Remote wakeup,
164 4..0: resvd */
165 50, /* u8 MaxPower; */
167 /* USB 1.1:
168 * USB 2.0, single TT organization (mandatory):
169 * one interface, protocol 0
171 * USB 2.0, multiple TT organization (optional):
172 * two interfaces, protocols 1 (like single TT)
173 * and 2 (multiple TT mode) ... config is
174 * sometimes settable
175 * NOT IMPLEMENTED
178 /* one interface */
179 0x09, /* u8 if_bLength; */
180 0x04, /* u8 if_bDescriptorType; Interface */
181 0x00, /* u8 if_bInterfaceNumber; */
182 0x00, /* u8 if_bAlternateSetting; */
183 0x01, /* u8 if_bNumEndpoints; */
184 0x03, /* u8 if_bInterfaceClass; */
185 0x01, /* u8 if_bInterfaceSubClass; */
186 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
187 0x07, /* u8 if_iInterface; */
189 /* HID descriptor */
190 0x09, /* u8 bLength; */
191 0x21, /* u8 bDescriptorType; */
192 0x01, 0x00, /* u16 HID_class */
193 0x00, /* u8 country_code */
194 0x01, /* u8 num_descriptors */
195 0x22, /* u8 type; Report */
196 74, 0, /* u16 len */
198 /* one endpoint (status change endpoint) */
199 0x07, /* u8 ep_bLength; */
200 0x05, /* u8 ep_bDescriptorType; Endpoint */
201 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
202 0x03, /* u8 ep_bmAttributes; Interrupt */
203 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
204 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
207 static const uint8_t qemu_keyboard_config_descriptor[] = {
208 /* one configuration */
209 0x09, /* u8 bLength; */
210 USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */
211 0x22, 0x00, /* u16 wTotalLength; */
212 0x01, /* u8 bNumInterfaces; (1) */
213 0x01, /* u8 bConfigurationValue; */
214 0x06, /* u8 iConfiguration; */
215 0xa0, /* u8 bmAttributes;
216 Bit 7: must be set,
217 6: Self-powered,
218 5: Remote wakeup,
219 4..0: resvd */
220 0x32, /* u8 MaxPower; */
222 /* USB 1.1:
223 * USB 2.0, single TT organization (mandatory):
224 * one interface, protocol 0
226 * USB 2.0, multiple TT organization (optional):
227 * two interfaces, protocols 1 (like single TT)
228 * and 2 (multiple TT mode) ... config is
229 * sometimes settable
230 * NOT IMPLEMENTED
233 /* one interface */
234 0x09, /* u8 if_bLength; */
235 USB_DT_INTERFACE, /* u8 if_bDescriptorType; Interface */
236 0x00, /* u8 if_bInterfaceNumber; */
237 0x00, /* u8 if_bAlternateSetting; */
238 0x01, /* u8 if_bNumEndpoints; */
239 0x03, /* u8 if_bInterfaceClass; HID */
240 0x01, /* u8 if_bInterfaceSubClass; Boot */
241 0x01, /* u8 if_bInterfaceProtocol; Keyboard */
242 0x07, /* u8 if_iInterface; */
244 /* HID descriptor */
245 0x09, /* u8 bLength; */
246 USB_DT_HID, /* u8 bDescriptorType; */
247 0x11, 0x01, /* u16 HID_class */
248 0x00, /* u8 country_code */
249 0x01, /* u8 num_descriptors */
250 USB_DT_REPORT, /* u8 type; Report */
251 0x3f, 0x00, /* u16 len */
253 /* one endpoint (status change endpoint) */
254 0x07, /* u8 ep_bLength; */
255 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; Endpoint */
256 USB_DIR_IN | 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
257 0x03, /* u8 ep_bmAttributes; Interrupt */
258 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
259 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
262 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
263 0x05, 0x01, /* Usage Page (Generic Desktop) */
264 0x09, 0x02, /* Usage (Mouse) */
265 0xa1, 0x01, /* Collection (Application) */
266 0x09, 0x01, /* Usage (Pointer) */
267 0xa1, 0x00, /* Collection (Physical) */
268 0x05, 0x09, /* Usage Page (Button) */
269 0x19, 0x01, /* Usage Minimum (1) */
270 0x29, 0x03, /* Usage Maximum (3) */
271 0x15, 0x00, /* Logical Minimum (0) */
272 0x25, 0x01, /* Logical Maximum (1) */
273 0x95, 0x03, /* Report Count (3) */
274 0x75, 0x01, /* Report Size (1) */
275 0x81, 0x02, /* Input (Data, Variable, Absolute) */
276 0x95, 0x01, /* Report Count (1) */
277 0x75, 0x05, /* Report Size (5) */
278 0x81, 0x01, /* Input (Constant) */
279 0x05, 0x01, /* Usage Page (Generic Desktop) */
280 0x09, 0x30, /* Usage (X) */
281 0x09, 0x31, /* Usage (Y) */
282 0x09, 0x38, /* Usage (Wheel) */
283 0x15, 0x81, /* Logical Minimum (-0x7f) */
284 0x25, 0x7f, /* Logical Maximum (0x7f) */
285 0x75, 0x08, /* Report Size (8) */
286 0x95, 0x03, /* Report Count (3) */
287 0x81, 0x06, /* Input (Data, Variable, Relative) */
288 0xc0, /* End Collection */
289 0xc0, /* End Collection */
292 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
293 0x05, 0x01, /* Usage Page (Generic Desktop) */
294 0x09, 0x01, /* Usage (Pointer) */
295 0xa1, 0x01, /* Collection (Application) */
296 0x09, 0x01, /* Usage (Pointer) */
297 0xa1, 0x00, /* Collection (Physical) */
298 0x05, 0x09, /* Usage Page (Button) */
299 0x19, 0x01, /* Usage Minimum (1) */
300 0x29, 0x03, /* Usage Maximum (3) */
301 0x15, 0x00, /* Logical Minimum (0) */
302 0x25, 0x01, /* Logical Maximum (1) */
303 0x95, 0x03, /* Report Count (3) */
304 0x75, 0x01, /* Report Size (1) */
305 0x81, 0x02, /* Input (Data, Variable, Absolute) */
306 0x95, 0x01, /* Report Count (1) */
307 0x75, 0x05, /* Report Size (5) */
308 0x81, 0x01, /* Input (Constant) */
309 0x05, 0x01, /* Usage Page (Generic Desktop) */
310 0x09, 0x30, /* Usage (X) */
311 0x09, 0x31, /* Usage (Y) */
312 0x15, 0x00, /* Logical Minimum (0) */
313 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
314 0x35, 0x00, /* Physical Minimum (0) */
315 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
316 0x75, 0x10, /* Report Size (16) */
317 0x95, 0x02, /* Report Count (2) */
318 0x81, 0x02, /* Input (Data, Variable, Absolute) */
319 0x05, 0x01, /* Usage Page (Generic Desktop) */
320 0x09, 0x38, /* Usage (Wheel) */
321 0x15, 0x81, /* Logical Minimum (-0x7f) */
322 0x25, 0x7f, /* Logical Maximum (0x7f) */
323 0x35, 0x00, /* Physical Minimum (same as logical) */
324 0x45, 0x00, /* Physical Maximum (same as logical) */
325 0x75, 0x08, /* Report Size (8) */
326 0x95, 0x01, /* Report Count (1) */
327 0x81, 0x06, /* Input (Data, Variable, Relative) */
328 0xc0, /* End Collection */
329 0xc0, /* End Collection */
332 static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
333 0x05, 0x01, /* Usage Page (Generic Desktop) */
334 0x09, 0x06, /* Usage (Keyboard) */
335 0xa1, 0x01, /* Collection (Application) */
336 0x75, 0x01, /* Report Size (1) */
337 0x95, 0x08, /* Report Count (8) */
338 0x05, 0x07, /* Usage Page (Key Codes) */
339 0x19, 0xe0, /* Usage Minimum (224) */
340 0x29, 0xe7, /* Usage Maximum (231) */
341 0x15, 0x00, /* Logical Minimum (0) */
342 0x25, 0x01, /* Logical Maximum (1) */
343 0x81, 0x02, /* Input (Data, Variable, Absolute) */
344 0x95, 0x01, /* Report Count (1) */
345 0x75, 0x08, /* Report Size (8) */
346 0x81, 0x01, /* Input (Constant) */
347 0x95, 0x05, /* Report Count (5) */
348 0x75, 0x01, /* Report Size (1) */
349 0x05, 0x08, /* Usage Page (LEDs) */
350 0x19, 0x01, /* Usage Minimum (1) */
351 0x29, 0x05, /* Usage Maximum (5) */
352 0x91, 0x02, /* Output (Data, Variable, Absolute) */
353 0x95, 0x01, /* Report Count (1) */
354 0x75, 0x03, /* Report Size (3) */
355 0x91, 0x01, /* Output (Constant) */
356 0x95, 0x06, /* Report Count (6) */
357 0x75, 0x08, /* Report Size (8) */
358 0x15, 0x00, /* Logical Minimum (0) */
359 0x25, 0xff, /* Logical Maximum (255) */
360 0x05, 0x07, /* Usage Page (Key Codes) */
361 0x19, 0x00, /* Usage Minimum (0) */
362 0x29, 0xff, /* Usage Maximum (255) */
363 0x81, 0x00, /* Input (Data, Array) */
364 0xc0, /* End Collection */
367 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
368 #define USB_HID_USAGE_POSTFAIL 0x02
369 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
371 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
372 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
373 static const uint8_t usb_hid_usage_keys[0x100] = {
374 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
375 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
376 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
377 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
378 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
379 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
380 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
381 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
382 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
383 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
384 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
385 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
386 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
398 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
400 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
401 0x51, 0x4e, 0x49, 0x4c, 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,
406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 static void usb_hid_changed(USBHIDState *hs)
411 hs->changed = 1;
413 if (hs->datain)
414 hs->datain(hs->datain_opaque);
417 static void usb_mouse_event(void *opaque,
418 int dx1, int dy1, int dz1, int buttons_state)
420 USBHIDState *hs = opaque;
421 USBMouseState *s = &hs->ptr;
423 s->dx += dx1;
424 s->dy += dy1;
425 s->dz += dz1;
426 s->buttons_state = buttons_state;
428 usb_hid_changed(hs);
431 static void usb_tablet_event(void *opaque,
432 int x, int y, int dz, int buttons_state)
434 USBHIDState *hs = opaque;
435 USBMouseState *s = &hs->ptr;
437 s->x = x;
438 s->y = y;
439 s->dz += dz;
440 s->buttons_state = buttons_state;
442 usb_hid_changed(hs);
445 static void usb_keyboard_event(void *opaque, int keycode)
447 USBHIDState *hs = opaque;
448 USBKeyboardState *s = &hs->kbd;
449 uint8_t hid_code, key;
450 int i;
452 key = keycode & 0x7f;
453 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
454 s->modifiers &= ~(1 << 8);
456 switch (hid_code) {
457 case 0x00:
458 return;
460 case 0xe0:
461 if (s->modifiers & (1 << 9)) {
462 s->modifiers ^= 3 << 8;
463 return;
465 case 0xe1 ... 0xe7:
466 if (keycode & (1 << 7)) {
467 s->modifiers &= ~(1 << (hid_code & 0x0f));
468 return;
470 case 0xe8 ... 0xef:
471 s->modifiers |= 1 << (hid_code & 0x0f);
472 return;
475 if (keycode & (1 << 7)) {
476 for (i = s->keys - 1; i >= 0; i --)
477 if (s->key[i] == hid_code) {
478 s->key[i] = s->key[-- s->keys];
479 s->key[s->keys] = 0x00;
480 usb_hid_changed(hs);
481 break;
483 if (i < 0)
484 return;
485 } else {
486 for (i = s->keys - 1; i >= 0; i --)
487 if (s->key[i] == hid_code)
488 break;
489 if (i < 0) {
490 if (s->keys < sizeof(s->key))
491 s->key[s->keys ++] = hid_code;
492 } else
493 return;
496 usb_hid_changed(hs);
499 static inline int int_clamp(int val, int vmin, int vmax)
501 if (val < vmin)
502 return vmin;
503 else if (val > vmax)
504 return vmax;
505 else
506 return val;
509 static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
511 int dx, dy, dz, b, l;
512 USBMouseState *s = &hs->ptr;
514 if (!s->mouse_grabbed) {
515 qemu_activate_mouse_event_handler(s->eh_entry);
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 qemu_activate_mouse_event_handler(s->eh_entry);
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 int ledstate = 0;
603 /* 0x01: Num Lock LED
604 * 0x02: Caps Lock LED
605 * 0x04: Scroll Lock LED
606 * 0x08: Compose LED
607 * 0x10: Kana LED */
608 s->leds = buf[0];
609 if (s->leds & 0x04)
610 ledstate |= QEMU_SCROLL_LOCK_LED;
611 if (s->leds & 0x01)
612 ledstate |= QEMU_NUM_LOCK_LED;
613 if (s->leds & 0x02)
614 ledstate |= QEMU_CAPS_LOCK_LED;
615 kbd_put_ledstate(ledstate);
617 return 0;
620 static void usb_mouse_handle_reset(USBDevice *dev)
622 USBHIDState *s = (USBHIDState *)dev;
624 s->ptr.dx = 0;
625 s->ptr.dy = 0;
626 s->ptr.dz = 0;
627 s->ptr.x = 0;
628 s->ptr.y = 0;
629 s->ptr.buttons_state = 0;
630 s->protocol = 1;
633 static void usb_keyboard_handle_reset(USBDevice *dev)
635 USBHIDState *s = (USBHIDState *)dev;
637 qemu_add_kbd_event_handler(usb_keyboard_event, s);
638 s->protocol = 1;
641 static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
643 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
646 static int usb_hid_handle_control(USBDevice *dev, int request, int value,
647 int index, int length, uint8_t *data)
649 USBHIDState *s = (USBHIDState *)dev;
650 int ret = 0;
652 switch(request) {
653 case DeviceRequest | USB_REQ_GET_STATUS:
654 data[0] = (1 << USB_DEVICE_SELF_POWERED) |
655 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
656 data[1] = 0x00;
657 ret = 2;
658 break;
659 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
660 if (value == USB_DEVICE_REMOTE_WAKEUP) {
661 dev->remote_wakeup = 0;
662 } else {
663 goto fail;
665 ret = 0;
666 break;
667 case DeviceOutRequest | USB_REQ_SET_FEATURE:
668 if (value == USB_DEVICE_REMOTE_WAKEUP) {
669 dev->remote_wakeup = 1;
670 } else {
671 goto fail;
673 ret = 0;
674 break;
675 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
676 dev->addr = value;
677 ret = 0;
678 break;
679 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
680 switch(value >> 8) {
681 case USB_DT_DEVICE:
682 memcpy(data, qemu_mouse_dev_descriptor,
683 sizeof(qemu_mouse_dev_descriptor));
684 ret = sizeof(qemu_mouse_dev_descriptor);
685 break;
686 case USB_DT_CONFIG:
687 if (s->kind == USB_MOUSE) {
688 memcpy(data, qemu_mouse_config_descriptor,
689 sizeof(qemu_mouse_config_descriptor));
690 ret = sizeof(qemu_mouse_config_descriptor);
691 } else if (s->kind == USB_TABLET) {
692 memcpy(data, qemu_tablet_config_descriptor,
693 sizeof(qemu_tablet_config_descriptor));
694 ret = sizeof(qemu_tablet_config_descriptor);
695 } else if (s->kind == USB_KEYBOARD) {
696 memcpy(data, qemu_keyboard_config_descriptor,
697 sizeof(qemu_keyboard_config_descriptor));
698 ret = sizeof(qemu_keyboard_config_descriptor);
700 break;
701 case USB_DT_STRING:
702 switch(value & 0xff) {
703 case 0:
704 /* language ids */
705 data[0] = 4;
706 data[1] = 3;
707 data[2] = 0x09;
708 data[3] = 0x04;
709 ret = 4;
710 break;
711 case 1:
712 /* serial number */
713 ret = set_usb_string(data, "1");
714 break;
715 case 2:
716 /* product description */
717 ret = set_usb_string(data, s->dev.product_desc);
718 break;
719 case 3:
720 /* vendor description */
721 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
722 break;
723 case 4:
724 ret = set_usb_string(data, "HID Mouse");
725 break;
726 case 5:
727 ret = set_usb_string(data, "HID Tablet");
728 break;
729 case 6:
730 ret = set_usb_string(data, "HID Keyboard");
731 break;
732 case 7:
733 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
734 break;
735 default:
736 goto fail;
738 break;
739 default:
740 goto fail;
742 break;
743 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
744 data[0] = 1;
745 ret = 1;
746 break;
747 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
748 ret = 0;
749 break;
750 case DeviceRequest | USB_REQ_GET_INTERFACE:
751 data[0] = 0;
752 ret = 1;
753 break;
754 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
755 ret = 0;
756 break;
757 /* hid specific requests */
758 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
759 switch(value >> 8) {
760 case 0x22:
761 if (s->kind == USB_MOUSE) {
762 memcpy(data, qemu_mouse_hid_report_descriptor,
763 sizeof(qemu_mouse_hid_report_descriptor));
764 ret = sizeof(qemu_mouse_hid_report_descriptor);
765 } else if (s->kind == USB_TABLET) {
766 memcpy(data, qemu_tablet_hid_report_descriptor,
767 sizeof(qemu_tablet_hid_report_descriptor));
768 ret = sizeof(qemu_tablet_hid_report_descriptor);
769 } else if (s->kind == USB_KEYBOARD) {
770 memcpy(data, qemu_keyboard_hid_report_descriptor,
771 sizeof(qemu_keyboard_hid_report_descriptor));
772 ret = sizeof(qemu_keyboard_hid_report_descriptor);
774 break;
775 default:
776 goto fail;
778 break;
779 case GET_REPORT:
780 if (s->kind == USB_MOUSE)
781 ret = usb_mouse_poll(s, data, length);
782 else if (s->kind == USB_TABLET)
783 ret = usb_tablet_poll(s, data, length);
784 else if (s->kind == USB_KEYBOARD)
785 ret = usb_keyboard_poll(&s->kbd, data, length);
786 break;
787 case SET_REPORT:
788 if (s->kind == USB_KEYBOARD)
789 ret = usb_keyboard_write(&s->kbd, data, length);
790 else
791 goto fail;
792 break;
793 case GET_PROTOCOL:
794 if (s->kind != USB_KEYBOARD)
795 goto fail;
796 ret = 1;
797 data[0] = s->protocol;
798 break;
799 case SET_PROTOCOL:
800 if (s->kind != USB_KEYBOARD)
801 goto fail;
802 ret = 0;
803 s->protocol = value;
804 break;
805 case GET_IDLE:
806 ret = 1;
807 data[0] = s->idle;
808 break;
809 case SET_IDLE:
810 s->idle = (uint8_t) (value >> 8);
811 usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
812 ret = 0;
813 break;
814 default:
815 fail:
816 ret = USB_RET_STALL;
817 break;
819 return ret;
822 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
824 USBHIDState *s = (USBHIDState *)dev;
825 int ret = 0;
827 switch(p->pid) {
828 case USB_TOKEN_IN:
829 if (p->devep == 1) {
830 int64_t curtime = qemu_get_clock(vm_clock);
831 if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
832 return USB_RET_NAK;
833 usb_hid_set_next_idle(s, curtime);
834 s->changed = 0;
835 if (s->kind == USB_MOUSE)
836 ret = usb_mouse_poll(s, p->data, p->len);
837 else if (s->kind == USB_TABLET)
838 ret = usb_tablet_poll(s, p->data, p->len);
839 else if (s->kind == USB_KEYBOARD)
840 ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
841 } else {
842 goto fail;
844 break;
845 case USB_TOKEN_OUT:
846 default:
847 fail:
848 ret = USB_RET_STALL;
849 break;
851 return ret;
854 static void usb_hid_handle_destroy(USBDevice *dev)
856 USBHIDState *s = (USBHIDState *)dev;
858 switch(s->kind) {
859 case USB_KEYBOARD:
860 qemu_remove_kbd_event_handler();
861 break;
862 default:
863 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
867 static int usb_hid_initfn(USBDevice *dev, int kind)
869 USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
870 s->dev.speed = USB_SPEED_FULL;
871 s->kind = kind;
873 if (s->kind == USB_MOUSE) {
874 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
875 0, "QEMU USB Mouse");
876 } else if (s->kind == USB_TABLET) {
877 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
878 1, "QEMU USB Tablet");
881 /* Force poll routine to be run and grab input the first time. */
882 s->changed = 1;
883 return 0;
886 static int usb_tablet_initfn(USBDevice *dev)
888 return usb_hid_initfn(dev, USB_TABLET);
891 static int usb_mouse_initfn(USBDevice *dev)
893 return usb_hid_initfn(dev, USB_MOUSE);
896 static int usb_keyboard_initfn(USBDevice *dev)
898 return usb_hid_initfn(dev, USB_KEYBOARD);
901 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
903 USBHIDState *s = (USBHIDState *)dev;
905 s->datain_opaque = opaque;
906 s->datain = datain;
909 static struct USBDeviceInfo hid_info[] = {
911 .product_desc = "QEMU USB Tablet",
912 .qdev.name = "usb-tablet",
913 .usbdevice_name = "tablet",
914 .qdev.size = sizeof(USBHIDState),
915 .init = usb_tablet_initfn,
916 .handle_packet = usb_generic_handle_packet,
917 .handle_reset = usb_mouse_handle_reset,
918 .handle_control = usb_hid_handle_control,
919 .handle_data = usb_hid_handle_data,
920 .handle_destroy = usb_hid_handle_destroy,
922 .product_desc = "QEMU USB Mouse",
923 .qdev.name = "usb-mouse",
924 .usbdevice_name = "mouse",
925 .qdev.size = sizeof(USBHIDState),
926 .init = usb_mouse_initfn,
927 .handle_packet = usb_generic_handle_packet,
928 .handle_reset = usb_mouse_handle_reset,
929 .handle_control = usb_hid_handle_control,
930 .handle_data = usb_hid_handle_data,
931 .handle_destroy = usb_hid_handle_destroy,
933 .product_desc = "QEMU USB Keyboard",
934 .qdev.name = "usb-kbd",
935 .usbdevice_name = "keyboard",
936 .qdev.size = sizeof(USBHIDState),
937 .init = usb_keyboard_initfn,
938 .handle_packet = usb_generic_handle_packet,
939 .handle_reset = usb_keyboard_handle_reset,
940 .handle_control = usb_hid_handle_control,
941 .handle_data = usb_hid_handle_data,
942 .handle_destroy = usb_hid_handle_destroy,
944 /* end of list */
948 static void usb_hid_register_devices(void)
950 usb_qdev_register_many(hid_info);
952 device_init(usb_hid_register_devices)