]> git.proxmox.com Git - qemu.git/blob - hw/usb-hid.c
Add mouse wheel in the usb-mouse HID Report (by Daniel Godás).
[qemu.git] / hw / usb-hid.c
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:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
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.
24 */
25 #include "hw.h"
26 #include "console.h"
27 #include "usb.h"
28
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
36
37 /* HID descriptor types */
38 #define USB_DT_HID 0x21
39 #define USB_DT_REPORT 0x22
40 #define USB_DT_PHY 0x23
41
42 #define USB_MOUSE 1
43 #define USB_TABLET 2
44 #define USB_KEYBOARD 3
45
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;
52
53 typedef struct USBKeyboardState {
54 uint16_t modifiers;
55 uint8_t leds;
56 uint8_t key[16];
57 int keys;
58 } USBKeyboardState;
59
60 typedef struct USBHIDState {
61 USBDevice dev;
62 union {
63 USBMouseState ptr;
64 USBKeyboardState kbd;
65 };
66 int kind;
67 int protocol;
68 int idle;
69 int changed;
70 } USBHIDState;
71
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 */
77
78 0x00, /* u8 bDeviceClass; */
79 0x00, /* u8 bDeviceSubClass; */
80 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
81 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
82
83 0x27, 0x06, /* u16 idVendor; */
84 0x01, 0x00, /* u16 idProduct; */
85 0x00, 0x00, /* u16 bcdDevice */
86
87 0x03, /* u8 iManufacturer; */
88 0x02, /* u8 iProduct; */
89 0x01, /* u8 iSerialNumber; */
90 0x01 /* u8 bNumConfigurations; */
91 };
92
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; */
107
108 /* USB 1.1:
109 * USB 2.0, single TT organization (mandatory):
110 * one interface, protocol 0
111 *
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
117 */
118
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; */
129
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 50, 0, /* u16 len */
138
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 0x03, 0x00, /* u16 ep_wMaxPacketSize; */
145 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
146 };
147
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; */
162
163 /* USB 1.1:
164 * USB 2.0, single TT organization (mandatory):
165 * one interface, protocol 0
166 *
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
172 */
173
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; */
184
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 */
193
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) */
201 };
202
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; */
217
218 /* USB 1.1:
219 * USB 2.0, single TT organization (mandatory):
220 * one interface, protocol 0
221 *
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
227 */
228
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; */
239
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 */
248
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) */
256 };
257
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, 0x15, 0x81,
264 0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
265 0x05, 0x01, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7F,
266 0x35, 0x00, 0x45, 0x00, 0x75, 0x08, 0x95, 0x01,
267 0x81, 0x02, 0xC0, 0xC0,
268 };
269
270 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
271 0x05, 0x01, /* Usage Page Generic Desktop */
272 0x09, 0x01, /* Usage Mouse */
273 0xA1, 0x01, /* Collection Application */
274 0x09, 0x01, /* Usage Pointer */
275 0xA1, 0x00, /* Collection Physical */
276 0x05, 0x09, /* Usage Page Button */
277 0x19, 0x01, /* Usage Minimum Button 1 */
278 0x29, 0x03, /* Usage Maximum Button 3 */
279 0x15, 0x00, /* Logical Minimum 0 */
280 0x25, 0x01, /* Logical Maximum 1 */
281 0x95, 0x03, /* Report Count 3 */
282 0x75, 0x01, /* Report Size 1 */
283 0x81, 0x02, /* Input (Data, Var, Abs) */
284 0x95, 0x01, /* Report Count 1 */
285 0x75, 0x05, /* Report Size 5 */
286 0x81, 0x01, /* Input (Cnst, Var, Abs) */
287 0x05, 0x01, /* Usage Page Generic Desktop */
288 0x09, 0x30, /* Usage X */
289 0x09, 0x31, /* Usage Y */
290 0x15, 0x00, /* Logical Minimum 0 */
291 0x26, 0xFF, 0x7F, /* Logical Maximum 0x7fff */
292 0x35, 0x00, /* Physical Minimum 0 */
293 0x46, 0xFE, 0x7F, /* Physical Maximum 0x7fff */
294 0x75, 0x10, /* Report Size 16 */
295 0x95, 0x02, /* Report Count 2 */
296 0x81, 0x02, /* Input (Data, Var, Abs) */
297 0x05, 0x01, /* Usage Page Generic Desktop */
298 0x09, 0x38, /* Usage Wheel */
299 0x15, 0x81, /* Logical Minimum -127 */
300 0x25, 0x7F, /* Logical Maximum 127 */
301 0x35, 0x00, /* Physical Minimum 0 (same as logical) */
302 0x45, 0x00, /* Physical Maximum 0 (same as logical) */
303 0x75, 0x08, /* Report Size 8 */
304 0x95, 0x01, /* Report Count 1 */
305 0x81, 0x02, /* Input (Data, Var, Rel) */
306 0xC0, /* End Collection */
307 0xC0, /* End Collection */
308 };
309
310 static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
311 0x05, 0x01, /* Usage Page (Generic Desktop) */
312 0x09, 0x06, /* Usage (Keyboard) */
313 0xa1, 0x01, /* Collection (Application) */
314 0x75, 0x01, /* Report Size (1) */
315 0x95, 0x08, /* Report Count (8) */
316 0x05, 0x07, /* Usage Page (Key Codes) */
317 0x19, 0xe0, /* Usage Minimum (224) */
318 0x29, 0xe7, /* Usage Maximum (231) */
319 0x15, 0x00, /* Logical Minimum (0) */
320 0x25, 0x01, /* Logical Maximum (1) */
321 0x81, 0x02, /* Input (Data, Variable, Absolute) */
322 0x95, 0x01, /* Report Count (1) */
323 0x75, 0x08, /* Report Size (8) */
324 0x81, 0x01, /* Input (Constant) */
325 0x95, 0x05, /* Report Count (5) */
326 0x75, 0x01, /* Report Size (1) */
327 0x05, 0x08, /* Usage Page (LEDs) */
328 0x19, 0x01, /* Usage Minimum (1) */
329 0x29, 0x05, /* Usage Maximum (5) */
330 0x91, 0x02, /* Output (Data, Variable, Absolute) */
331 0x95, 0x01, /* Report Count (1) */
332 0x75, 0x03, /* Report Size (3) */
333 0x91, 0x01, /* Output (Constant) */
334 0x95, 0x06, /* Report Count (6) */
335 0x75, 0x08, /* Report Size (8) */
336 0x15, 0x00, /* Logical Minimum (0) */
337 0x25, 0xff, /* Logical Maximum (255) */
338 0x05, 0x07, /* Usage Page (Key Codes) */
339 0x19, 0x00, /* Usage Minimum (0) */
340 0x29, 0xff, /* Usage Maximum (255) */
341 0x81, 0x00, /* Input (Data, Array) */
342 0xc0, /* End Collection */
343 };
344
345 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
346 #define USB_HID_USAGE_POSTFAIL 0x02
347 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
348
349 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
350 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
351 static const uint8_t usb_hid_usage_keys[0x100] = {
352 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
353 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
354 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
355 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
356 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
357 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
358 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
359 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
360 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
361 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
362 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
363 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
364 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
368
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
376 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
378 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
379 0x51, 0x4e, 0x49, 0x4c, 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,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 };
386
387 static void usb_mouse_event(void *opaque,
388 int dx1, int dy1, int dz1, int buttons_state)
389 {
390 USBHIDState *hs = opaque;
391 USBMouseState *s = &hs->ptr;
392
393 s->dx += dx1;
394 s->dy += dy1;
395 s->dz += dz1;
396 s->buttons_state = buttons_state;
397 hs->changed = 1;
398 }
399
400 static void usb_tablet_event(void *opaque,
401 int x, int y, int dz, int buttons_state)
402 {
403 USBHIDState *hs = opaque;
404 USBMouseState *s = &hs->ptr;
405
406 s->x = x;
407 s->y = y;
408 s->dz += dz;
409 s->buttons_state = buttons_state;
410 hs->changed = 1;
411 }
412
413 static void usb_keyboard_event(void *opaque, int keycode)
414 {
415 USBHIDState *hs = opaque;
416 USBKeyboardState *s = &hs->kbd;
417 uint8_t hid_code, key;
418 int i;
419
420 key = keycode & 0x7f;
421 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
422 s->modifiers &= ~(1 << 8);
423
424 hs->changed = 1;
425
426 switch (hid_code) {
427 case 0x00:
428 return;
429
430 case 0xe0:
431 if (s->modifiers & (1 << 9)) {
432 s->modifiers ^= 3 << 8;
433 return;
434 }
435 case 0xe1 ... 0xe7:
436 if (keycode & (1 << 7)) {
437 s->modifiers &= ~(1 << (hid_code & 0x0f));
438 return;
439 }
440 case 0xe8 ... 0xef:
441 s->modifiers |= 1 << (hid_code & 0x0f);
442 return;
443 }
444
445 if (keycode & (1 << 7)) {
446 for (i = s->keys - 1; i >= 0; i --)
447 if (s->key[i] == hid_code) {
448 s->key[i] = s->key[-- s->keys];
449 s->key[s->keys] = 0x00;
450 return;
451 }
452 } else {
453 for (i = s->keys - 1; i >= 0; i --)
454 if (s->key[i] == hid_code)
455 return;
456 if (s->keys < sizeof(s->key))
457 s->key[s->keys ++] = hid_code;
458 }
459 }
460
461 static inline int int_clamp(int val, int vmin, int vmax)
462 {
463 if (val < vmin)
464 return vmin;
465 else if (val > vmax)
466 return vmax;
467 else
468 return val;
469 }
470
471 static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
472 {
473 int dx, dy, dz, b, l;
474 USBMouseState *s = &hs->ptr;
475
476 if (!s->mouse_grabbed) {
477 s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, hs,
478 0, "QEMU USB Mouse");
479 s->mouse_grabbed = 1;
480 }
481
482 dx = int_clamp(s->dx, -128, 127);
483 dy = int_clamp(s->dy, -128, 127);
484 dz = int_clamp(s->dz, -128, 127);
485
486 s->dx -= dx;
487 s->dy -= dy;
488 s->dz -= dz;
489
490 b = 0;
491 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
492 b |= 0x01;
493 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
494 b |= 0x02;
495 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
496 b |= 0x04;
497
498 buf[0] = b;
499 buf[1] = dx;
500 buf[2] = dy;
501 l = 3;
502 if (len >= 4) {
503 buf[3] = dz;
504 l = 4;
505 }
506 return l;
507 }
508
509 static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
510 {
511 int dz, b, l;
512 USBMouseState *s = &hs->ptr;
513
514 if (!s->mouse_grabbed) {
515 s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs,
516 1, "QEMU USB Tablet");
517 s->mouse_grabbed = 1;
518 }
519
520 dz = int_clamp(s->dz, -128, 127);
521 s->dz -= dz;
522
523 /* Appears we have to invert the wheel direction */
524 dz = 0 - dz;
525 b = 0;
526 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
527 b |= 0x01;
528 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
529 b |= 0x02;
530 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
531 b |= 0x04;
532
533 buf[0] = b;
534 buf[1] = s->x & 0xff;
535 buf[2] = s->x >> 8;
536 buf[3] = s->y & 0xff;
537 buf[4] = s->y >> 8;
538 buf[5] = dz;
539 l = 6;
540
541 return l;
542 }
543
544 static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
545 {
546 if (len < 2)
547 return 0;
548
549 buf[0] = s->modifiers & 0xff;
550 buf[1] = 0;
551 if (s->keys > 6)
552 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
553 else
554 memcpy(buf + 2, s->key, MIN(8, len) - 2);
555
556 return MIN(8, len);
557 }
558
559 static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
560 {
561 if (len > 0) {
562 /* 0x01: Num Lock LED
563 * 0x02: Caps Lock LED
564 * 0x04: Scroll Lock LED
565 * 0x08: Compose LED
566 * 0x10: Kana LED */
567 s->leds = buf[0];
568 }
569 return 0;
570 }
571
572 static void usb_mouse_handle_reset(USBDevice *dev)
573 {
574 USBHIDState *s = (USBHIDState *)dev;
575
576 s->ptr.dx = 0;
577 s->ptr.dy = 0;
578 s->ptr.dz = 0;
579 s->ptr.x = 0;
580 s->ptr.y = 0;
581 s->ptr.buttons_state = 0;
582 s->protocol = 1;
583 }
584
585 static void usb_keyboard_handle_reset(USBDevice *dev)
586 {
587 USBHIDState *s = (USBHIDState *)dev;
588
589 qemu_add_kbd_event_handler(usb_keyboard_event, s);
590 s->protocol = 1;
591 }
592
593 static int usb_hid_handle_control(USBDevice *dev, int request, int value,
594 int index, int length, uint8_t *data)
595 {
596 USBHIDState *s = (USBHIDState *)dev;
597 int ret = 0;
598
599 switch(request) {
600 case DeviceRequest | USB_REQ_GET_STATUS:
601 data[0] = (1 << USB_DEVICE_SELF_POWERED) |
602 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
603 data[1] = 0x00;
604 ret = 2;
605 break;
606 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
607 if (value == USB_DEVICE_REMOTE_WAKEUP) {
608 dev->remote_wakeup = 0;
609 } else {
610 goto fail;
611 }
612 ret = 0;
613 break;
614 case DeviceOutRequest | USB_REQ_SET_FEATURE:
615 if (value == USB_DEVICE_REMOTE_WAKEUP) {
616 dev->remote_wakeup = 1;
617 } else {
618 goto fail;
619 }
620 ret = 0;
621 break;
622 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
623 dev->addr = value;
624 ret = 0;
625 break;
626 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
627 switch(value >> 8) {
628 case USB_DT_DEVICE:
629 memcpy(data, qemu_mouse_dev_descriptor,
630 sizeof(qemu_mouse_dev_descriptor));
631 ret = sizeof(qemu_mouse_dev_descriptor);
632 break;
633 case USB_DT_CONFIG:
634 if (s->kind == USB_MOUSE) {
635 memcpy(data, qemu_mouse_config_descriptor,
636 sizeof(qemu_mouse_config_descriptor));
637 ret = sizeof(qemu_mouse_config_descriptor);
638 } else if (s->kind == USB_TABLET) {
639 memcpy(data, qemu_tablet_config_descriptor,
640 sizeof(qemu_tablet_config_descriptor));
641 ret = sizeof(qemu_tablet_config_descriptor);
642 } else if (s->kind == USB_KEYBOARD) {
643 memcpy(data, qemu_keyboard_config_descriptor,
644 sizeof(qemu_keyboard_config_descriptor));
645 ret = sizeof(qemu_keyboard_config_descriptor);
646 }
647 break;
648 case USB_DT_STRING:
649 switch(value & 0xff) {
650 case 0:
651 /* language ids */
652 data[0] = 4;
653 data[1] = 3;
654 data[2] = 0x09;
655 data[3] = 0x04;
656 ret = 4;
657 break;
658 case 1:
659 /* serial number */
660 ret = set_usb_string(data, "1");
661 break;
662 case 2:
663 /* product description */
664 ret = set_usb_string(data, s->dev.devname);
665 break;
666 case 3:
667 /* vendor description */
668 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
669 break;
670 case 4:
671 ret = set_usb_string(data, "HID Mouse");
672 break;
673 case 5:
674 ret = set_usb_string(data, "HID Tablet");
675 break;
676 case 6:
677 ret = set_usb_string(data, "HID Keyboard");
678 break;
679 case 7:
680 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
681 break;
682 default:
683 goto fail;
684 }
685 break;
686 default:
687 goto fail;
688 }
689 break;
690 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
691 data[0] = 1;
692 ret = 1;
693 break;
694 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
695 ret = 0;
696 break;
697 case DeviceRequest | USB_REQ_GET_INTERFACE:
698 data[0] = 0;
699 ret = 1;
700 break;
701 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
702 ret = 0;
703 break;
704 /* hid specific requests */
705 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
706 switch(value >> 8) {
707 case 0x22:
708 if (s->kind == USB_MOUSE) {
709 memcpy(data, qemu_mouse_hid_report_descriptor,
710 sizeof(qemu_mouse_hid_report_descriptor));
711 ret = sizeof(qemu_mouse_hid_report_descriptor);
712 } else if (s->kind == USB_TABLET) {
713 memcpy(data, qemu_tablet_hid_report_descriptor,
714 sizeof(qemu_tablet_hid_report_descriptor));
715 ret = sizeof(qemu_tablet_hid_report_descriptor);
716 } else if (s->kind == USB_KEYBOARD) {
717 memcpy(data, qemu_keyboard_hid_report_descriptor,
718 sizeof(qemu_keyboard_hid_report_descriptor));
719 ret = sizeof(qemu_keyboard_hid_report_descriptor);
720 }
721 break;
722 default:
723 goto fail;
724 }
725 break;
726 case GET_REPORT:
727 if (s->kind == USB_MOUSE)
728 ret = usb_mouse_poll(s, data, length);
729 else if (s->kind == USB_TABLET)
730 ret = usb_tablet_poll(s, data, length);
731 else if (s->kind == USB_KEYBOARD)
732 ret = usb_keyboard_poll(&s->kbd, data, length);
733 break;
734 case SET_REPORT:
735 if (s->kind == USB_KEYBOARD)
736 ret = usb_keyboard_write(&s->kbd, data, length);
737 else
738 goto fail;
739 break;
740 case GET_PROTOCOL:
741 if (s->kind != USB_KEYBOARD)
742 goto fail;
743 ret = 1;
744 data[0] = s->protocol;
745 break;
746 case SET_PROTOCOL:
747 if (s->kind != USB_KEYBOARD)
748 goto fail;
749 ret = 0;
750 s->protocol = value;
751 break;
752 case GET_IDLE:
753 ret = 1;
754 data[0] = s->idle;
755 break;
756 case SET_IDLE:
757 s->idle = value;
758 ret = 0;
759 break;
760 default:
761 fail:
762 ret = USB_RET_STALL;
763 break;
764 }
765 return ret;
766 }
767
768 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
769 {
770 USBHIDState *s = (USBHIDState *)dev;
771 int ret = 0;
772
773 switch(p->pid) {
774 case USB_TOKEN_IN:
775 if (p->devep == 1) {
776 /* TODO: Implement finite idle delays. */
777 if (!(s->changed || s->idle))
778 return USB_RET_NAK;
779 s->changed = 0;
780 if (s->kind == USB_MOUSE)
781 ret = usb_mouse_poll(s, p->data, p->len);
782 else if (s->kind == USB_TABLET)
783 ret = usb_tablet_poll(s, p->data, p->len);
784 else if (s->kind == USB_KEYBOARD)
785 ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
786 } else {
787 goto fail;
788 }
789 break;
790 case USB_TOKEN_OUT:
791 default:
792 fail:
793 ret = USB_RET_STALL;
794 break;
795 }
796 return ret;
797 }
798
799 static void usb_hid_handle_destroy(USBDevice *dev)
800 {
801 USBHIDState *s = (USBHIDState *)dev;
802
803 if (s->kind != USB_KEYBOARD)
804 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
805 /* TODO: else */
806 qemu_free(s);
807 }
808
809 USBDevice *usb_tablet_init(void)
810 {
811 USBHIDState *s;
812
813 s = qemu_mallocz(sizeof(USBHIDState));
814 if (!s)
815 return NULL;
816 s->dev.speed = USB_SPEED_FULL;
817 s->dev.handle_packet = usb_generic_handle_packet;
818
819 s->dev.handle_reset = usb_mouse_handle_reset;
820 s->dev.handle_control = usb_hid_handle_control;
821 s->dev.handle_data = usb_hid_handle_data;
822 s->dev.handle_destroy = usb_hid_handle_destroy;
823 s->kind = USB_TABLET;
824 /* Force poll routine to be run and grab input the first time. */
825 s->changed = 1;
826
827 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
828
829 return (USBDevice *)s;
830 }
831
832 USBDevice *usb_mouse_init(void)
833 {
834 USBHIDState *s;
835
836 s = qemu_mallocz(sizeof(USBHIDState));
837 if (!s)
838 return NULL;
839 s->dev.speed = USB_SPEED_FULL;
840 s->dev.handle_packet = usb_generic_handle_packet;
841
842 s->dev.handle_reset = usb_mouse_handle_reset;
843 s->dev.handle_control = usb_hid_handle_control;
844 s->dev.handle_data = usb_hid_handle_data;
845 s->dev.handle_destroy = usb_hid_handle_destroy;
846 s->kind = USB_MOUSE;
847 /* Force poll routine to be run and grab input the first time. */
848 s->changed = 1;
849
850 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
851
852 return (USBDevice *)s;
853 }
854
855 USBDevice *usb_keyboard_init(void)
856 {
857 USBHIDState *s;
858
859 s = qemu_mallocz(sizeof(USBHIDState));
860 if (!s)
861 return NULL;
862 s->dev.speed = USB_SPEED_FULL;
863 s->dev.handle_packet = usb_generic_handle_packet;
864
865 s->dev.handle_reset = usb_keyboard_handle_reset;
866 s->dev.handle_control = usb_hid_handle_control;
867 s->dev.handle_data = usb_hid_handle_data;
868 s->dev.handle_destroy = usb_hid_handle_destroy;
869 s->kind = USB_KEYBOARD;
870
871 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");
872
873 return (USBDevice *) s;
874 }