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
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
42 #define USB_KEYBOARD 3
44 typedef struct USBMouseState
{
45 int dx
, dy
, dz
, buttons_state
;
48 QEMUPutMouseEntry
*eh_entry
;
51 typedef struct USBKeyboardState
{
58 typedef struct USBHIDState
{
70 /* mostly the same values as the Bochs USB Mouse device */
71 static const uint8_t qemu_mouse_dev_descriptor
[] = {
72 0x12, /* u8 bLength; */
73 0x01, /* u8 bDescriptorType; Device */
74 0x00, 0x01, /* u16 bcdUSB; v1.0 */
76 0x00, /* u8 bDeviceClass; */
77 0x00, /* u8 bDeviceSubClass; */
78 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
79 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
81 0x27, 0x06, /* u16 idVendor; */
82 0x01, 0x00, /* u16 idProduct; */
83 0x00, 0x00, /* u16 bcdDevice */
85 0x03, /* u8 iManufacturer; */
86 0x02, /* u8 iProduct; */
87 0x01, /* u8 iSerialNumber; */
88 0x01 /* u8 bNumConfigurations; */
91 static const uint8_t qemu_mouse_config_descriptor
[] = {
92 /* one configuration */
93 0x09, /* u8 bLength; */
94 0x02, /* u8 bDescriptorType; Configuration */
95 0x22, 0x00, /* u16 wTotalLength; */
96 0x01, /* u8 bNumInterfaces; (1) */
97 0x01, /* u8 bConfigurationValue; */
98 0x04, /* u8 iConfiguration; */
99 0xa0, /* u8 bmAttributes;
104 50, /* u8 MaxPower; */
107 * USB 2.0, single TT organization (mandatory):
108 * one interface, protocol 0
110 * USB 2.0, multiple TT organization (optional):
111 * two interfaces, protocols 1 (like single TT)
112 * and 2 (multiple TT mode) ... config is
118 0x09, /* u8 if_bLength; */
119 0x04, /* u8 if_bDescriptorType; Interface */
120 0x00, /* u8 if_bInterfaceNumber; */
121 0x00, /* u8 if_bAlternateSetting; */
122 0x01, /* u8 if_bNumEndpoints; */
123 0x03, /* u8 if_bInterfaceClass; */
124 0x01, /* u8 if_bInterfaceSubClass; */
125 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
126 0x07, /* u8 if_iInterface; */
129 0x09, /* u8 bLength; */
130 0x21, /* u8 bDescriptorType; */
131 0x01, 0x00, /* u16 HID_class */
132 0x00, /* u8 country_code */
133 0x01, /* u8 num_descriptors */
134 0x22, /* u8 type; Report */
137 /* one endpoint (status change endpoint) */
138 0x07, /* u8 ep_bLength; */
139 0x05, /* u8 ep_bDescriptorType; Endpoint */
140 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
141 0x03, /* u8 ep_bmAttributes; Interrupt */
142 0x03, 0x00, /* u16 ep_wMaxPacketSize; */
143 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
146 static const uint8_t qemu_tablet_config_descriptor
[] = {
147 /* one configuration */
148 0x09, /* u8 bLength; */
149 0x02, /* u8 bDescriptorType; Configuration */
150 0x22, 0x00, /* u16 wTotalLength; */
151 0x01, /* u8 bNumInterfaces; (1) */
152 0x01, /* u8 bConfigurationValue; */
153 0x05, /* u8 iConfiguration; */
154 0xa0, /* u8 bmAttributes;
159 50, /* u8 MaxPower; */
162 * USB 2.0, single TT organization (mandatory):
163 * one interface, protocol 0
165 * USB 2.0, multiple TT organization (optional):
166 * two interfaces, protocols 1 (like single TT)
167 * and 2 (multiple TT mode) ... config is
173 0x09, /* u8 if_bLength; */
174 0x04, /* u8 if_bDescriptorType; Interface */
175 0x00, /* u8 if_bInterfaceNumber; */
176 0x00, /* u8 if_bAlternateSetting; */
177 0x01, /* u8 if_bNumEndpoints; */
178 0x03, /* u8 if_bInterfaceClass; */
179 0x01, /* u8 if_bInterfaceSubClass; */
180 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
181 0x07, /* u8 if_iInterface; */
184 0x09, /* u8 bLength; */
185 0x21, /* u8 bDescriptorType; */
186 0x01, 0x00, /* u16 HID_class */
187 0x00, /* u8 country_code */
188 0x01, /* u8 num_descriptors */
189 0x22, /* u8 type; Report */
192 /* one endpoint (status change endpoint) */
193 0x07, /* u8 ep_bLength; */
194 0x05, /* u8 ep_bDescriptorType; Endpoint */
195 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
196 0x03, /* u8 ep_bmAttributes; Interrupt */
197 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
198 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
201 static const uint8_t qemu_keyboard_config_descriptor
[] = {
202 /* one configuration */
203 0x09, /* u8 bLength; */
204 USB_DT_CONFIG
, /* u8 bDescriptorType; Configuration */
205 0x22, 0x00, /* u16 wTotalLength; */
206 0x01, /* u8 bNumInterfaces; (1) */
207 0x01, /* u8 bConfigurationValue; */
208 0x06, /* u8 iConfiguration; */
209 0xa0, /* u8 bmAttributes;
214 0x32, /* u8 MaxPower; */
217 * USB 2.0, single TT organization (mandatory):
218 * one interface, protocol 0
220 * USB 2.0, multiple TT organization (optional):
221 * two interfaces, protocols 1 (like single TT)
222 * and 2 (multiple TT mode) ... config is
228 0x09, /* u8 if_bLength; */
229 USB_DT_INTERFACE
, /* u8 if_bDescriptorType; Interface */
230 0x00, /* u8 if_bInterfaceNumber; */
231 0x00, /* u8 if_bAlternateSetting; */
232 0x01, /* u8 if_bNumEndpoints; */
233 0x03, /* u8 if_bInterfaceClass; HID */
234 0x01, /* u8 if_bInterfaceSubClass; Boot */
235 0x01, /* u8 if_bInterfaceProtocol; Keyboard */
236 0x07, /* u8 if_iInterface; */
239 0x09, /* u8 bLength; */
240 USB_DT_HID
, /* u8 bDescriptorType; */
241 0x11, 0x01, /* u16 HID_class */
242 0x00, /* u8 country_code */
243 0x01, /* u8 num_descriptors */
244 USB_DT_REPORT
, /* u8 type; Report */
245 0x3f, 0x00, /* u16 len */
247 /* one endpoint (status change endpoint) */
248 0x07, /* u8 ep_bLength; */
249 USB_DT_ENDPOINT
, /* u8 ep_bDescriptorType; Endpoint */
250 USB_DIR_IN
| 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
251 0x03, /* u8 ep_bmAttributes; Interrupt */
252 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
253 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
256 static const uint8_t qemu_mouse_hid_report_descriptor
[] = {
257 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01,
258 0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
259 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
260 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
261 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81,
262 0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
266 static const uint8_t qemu_tablet_hid_report_descriptor
[] = {
267 0x05, 0x01, /* Usage Page Generic Desktop */
268 0x09, 0x01, /* Usage Mouse */
269 0xA1, 0x01, /* Collection Application */
270 0x09, 0x01, /* Usage Pointer */
271 0xA1, 0x00, /* Collection Physical */
272 0x05, 0x09, /* Usage Page Button */
273 0x19, 0x01, /* Usage Minimum Button 1 */
274 0x29, 0x03, /* Usage Maximum Button 3 */
275 0x15, 0x00, /* Logical Minimum 0 */
276 0x25, 0x01, /* Logical Maximum 1 */
277 0x95, 0x03, /* Report Count 3 */
278 0x75, 0x01, /* Report Size 1 */
279 0x81, 0x02, /* Input (Data, Var, Abs) */
280 0x95, 0x01, /* Report Count 1 */
281 0x75, 0x05, /* Report Size 5 */
282 0x81, 0x01, /* Input (Cnst, Var, Abs) */
283 0x05, 0x01, /* Usage Page Generic Desktop */
284 0x09, 0x30, /* Usage X */
285 0x09, 0x31, /* Usage Y */
286 0x15, 0x00, /* Logical Minimum 0 */
287 0x26, 0xFF, 0x7F, /* Logical Maximum 0x7fff */
288 0x35, 0x00, /* Physical Minimum 0 */
289 0x46, 0xFE, 0x7F, /* Physical Maximum 0x7fff */
290 0x75, 0x10, /* Report Size 16 */
291 0x95, 0x02, /* Report Count 2 */
292 0x81, 0x02, /* Input (Data, Var, Abs) */
293 0x05, 0x01, /* Usage Page Generic Desktop */
294 0x09, 0x38, /* Usage Wheel */
295 0x15, 0x81, /* Logical Minimum -127 */
296 0x25, 0x7F, /* Logical Maximum 127 */
297 0x35, 0x00, /* Physical Minimum 0 (same as logical) */
298 0x45, 0x00, /* Physical Maximum 0 (same as logical) */
299 0x75, 0x08, /* Report Size 8 */
300 0x95, 0x01, /* Report Count 1 */
301 0x81, 0x02, /* Input (Data, Var, Rel) */
302 0xC0, /* End Collection */
303 0xC0, /* End Collection */
306 static const uint8_t qemu_keyboard_hid_report_descriptor
[] = {
307 0x05, 0x01, /* Usage Page (Generic Desktop) */
308 0x09, 0x06, /* Usage (Keyboard) */
309 0xa1, 0x01, /* Collection (Application) */
310 0x75, 0x01, /* Report Size (1) */
311 0x95, 0x08, /* Report Count (8) */
312 0x05, 0x07, /* Usage Page (Key Codes) */
313 0x19, 0xe0, /* Usage Minimum (224) */
314 0x29, 0xe7, /* Usage Maximum (231) */
315 0x15, 0x00, /* Logical Minimum (0) */
316 0x25, 0x01, /* Logical Maximum (1) */
317 0x81, 0x02, /* Input (Data, Variable, Absolute) */
318 0x95, 0x01, /* Report Count (1) */
319 0x75, 0x08, /* Report Size (8) */
320 0x81, 0x01, /* Input (Constant) */
321 0x95, 0x05, /* Report Count (5) */
322 0x75, 0x01, /* Report Size (1) */
323 0x05, 0x08, /* Usage Page (LEDs) */
324 0x19, 0x01, /* Usage Minimum (1) */
325 0x29, 0x05, /* Usage Maximum (5) */
326 0x91, 0x02, /* Output (Data, Variable, Absolute) */
327 0x95, 0x01, /* Report Count (1) */
328 0x75, 0x03, /* Report Size (3) */
329 0x91, 0x01, /* Output (Constant) */
330 0x95, 0x06, /* Report Count (6) */
331 0x75, 0x08, /* Report Size (8) */
332 0x15, 0x00, /* Logical Minimum (0) */
333 0x25, 0xff, /* Logical Maximum (255) */
334 0x05, 0x07, /* Usage Page (Key Codes) */
335 0x19, 0x00, /* Usage Minimum (0) */
336 0x29, 0xff, /* Usage Maximum (255) */
337 0x81, 0x00, /* Input (Data, Array) */
338 0xc0, /* End Collection */
341 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
342 #define USB_HID_USAGE_POSTFAIL 0x02
343 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
345 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
346 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
347 static const uint8_t usb_hid_usage_keys
[0x100] = {
348 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
349 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
350 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
351 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
352 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
353 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
354 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
355 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
356 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
357 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
358 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
359 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
360 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
372 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
374 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
375 0x51, 0x4e, 0x49, 0x4c, 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,
380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 static void usb_mouse_event(void *opaque
,
384 int dx1
, int dy1
, int dz1
, int buttons_state
)
386 USBHIDState
*hs
= opaque
;
387 USBMouseState
*s
= &hs
->ptr
;
392 s
->buttons_state
= buttons_state
;
396 static void usb_tablet_event(void *opaque
,
397 int x
, int y
, int dz
, int buttons_state
)
399 USBHIDState
*hs
= opaque
;
400 USBMouseState
*s
= &hs
->ptr
;
405 s
->buttons_state
= buttons_state
;
409 static void usb_keyboard_event(void *opaque
, int keycode
)
411 USBHIDState
*hs
= opaque
;
412 USBKeyboardState
*s
= &hs
->kbd
;
413 uint8_t hid_code
, key
;
416 key
= keycode
& 0x7f;
417 hid_code
= usb_hid_usage_keys
[key
| ((s
->modifiers
>> 1) & (1 << 7))];
418 s
->modifiers
&= ~(1 << 8);
427 if (s
->modifiers
& (1 << 9)) {
428 s
->modifiers
^= 3 << 8;
432 if (keycode
& (1 << 7)) {
433 s
->modifiers
&= ~(1 << (hid_code
& 0x0f));
437 s
->modifiers
|= 1 << (hid_code
& 0x0f);
441 if (keycode
& (1 << 7)) {
442 for (i
= s
->keys
- 1; i
>= 0; i
--)
443 if (s
->key
[i
] == hid_code
) {
444 s
->key
[i
] = s
->key
[-- s
->keys
];
445 s
->key
[s
->keys
] = 0x00;
449 for (i
= s
->keys
- 1; i
>= 0; i
--)
450 if (s
->key
[i
] == hid_code
)
452 if (s
->keys
< sizeof(s
->key
))
453 s
->key
[s
->keys
++] = hid_code
;
457 static inline int int_clamp(int val
, int vmin
, int vmax
)
467 static int usb_mouse_poll(USBHIDState
*hs
, uint8_t *buf
, int len
)
469 int dx
, dy
, dz
, b
, l
;
470 USBMouseState
*s
= &hs
->ptr
;
472 if (!s
->mouse_grabbed
) {
473 s
->eh_entry
= qemu_add_mouse_event_handler(usb_mouse_event
, hs
,
474 0, "QEMU USB Mouse");
475 s
->mouse_grabbed
= 1;
478 dx
= int_clamp(s
->dx
, -128, 127);
479 dy
= int_clamp(s
->dy
, -128, 127);
480 dz
= int_clamp(s
->dz
, -128, 127);
487 if (s
->buttons_state
& MOUSE_EVENT_LBUTTON
)
489 if (s
->buttons_state
& MOUSE_EVENT_RBUTTON
)
491 if (s
->buttons_state
& MOUSE_EVENT_MBUTTON
)
505 static int usb_tablet_poll(USBHIDState
*hs
, uint8_t *buf
, int len
)
508 USBMouseState
*s
= &hs
->ptr
;
510 if (!s
->mouse_grabbed
) {
511 s
->eh_entry
= qemu_add_mouse_event_handler(usb_tablet_event
, hs
,
512 1, "QEMU USB Tablet");
513 s
->mouse_grabbed
= 1;
516 dz
= int_clamp(s
->dz
, -128, 127);
519 /* Appears we have to invert the wheel direction */
522 if (s
->buttons_state
& MOUSE_EVENT_LBUTTON
)
524 if (s
->buttons_state
& MOUSE_EVENT_RBUTTON
)
526 if (s
->buttons_state
& MOUSE_EVENT_MBUTTON
)
530 buf
[1] = s
->x
& 0xff;
532 buf
[3] = s
->y
& 0xff;
540 static int usb_keyboard_poll(USBKeyboardState
*s
, uint8_t *buf
, int len
)
545 buf
[0] = s
->modifiers
& 0xff;
548 memset(buf
+ 2, USB_HID_USAGE_ERROR_ROLLOVER
, MIN(8, len
) - 2);
550 memcpy(buf
+ 2, s
->key
, MIN(8, len
) - 2);
555 static int usb_keyboard_write(USBKeyboardState
*s
, uint8_t *buf
, int len
)
558 /* 0x01: Num Lock LED
559 * 0x02: Caps Lock LED
560 * 0x04: Scroll Lock LED
568 static void usb_mouse_handle_reset(USBDevice
*dev
)
570 USBHIDState
*s
= (USBHIDState
*)dev
;
577 s
->ptr
.buttons_state
= 0;
581 static void usb_keyboard_handle_reset(USBDevice
*dev
)
583 USBHIDState
*s
= (USBHIDState
*)dev
;
585 qemu_add_kbd_event_handler(usb_keyboard_event
, &s
->kbd
);
589 static int usb_hid_handle_control(USBDevice
*dev
, int request
, int value
,
590 int index
, int length
, uint8_t *data
)
592 USBHIDState
*s
= (USBHIDState
*)dev
;
596 case DeviceRequest
| USB_REQ_GET_STATUS
:
597 data
[0] = (1 << USB_DEVICE_SELF_POWERED
) |
598 (dev
->remote_wakeup
<< USB_DEVICE_REMOTE_WAKEUP
);
602 case DeviceOutRequest
| USB_REQ_CLEAR_FEATURE
:
603 if (value
== USB_DEVICE_REMOTE_WAKEUP
) {
604 dev
->remote_wakeup
= 0;
610 case DeviceOutRequest
| USB_REQ_SET_FEATURE
:
611 if (value
== USB_DEVICE_REMOTE_WAKEUP
) {
612 dev
->remote_wakeup
= 1;
618 case DeviceOutRequest
| USB_REQ_SET_ADDRESS
:
622 case DeviceRequest
| USB_REQ_GET_DESCRIPTOR
:
625 memcpy(data
, qemu_mouse_dev_descriptor
,
626 sizeof(qemu_mouse_dev_descriptor
));
627 ret
= sizeof(qemu_mouse_dev_descriptor
);
630 if (s
->kind
== USB_MOUSE
) {
631 memcpy(data
, qemu_mouse_config_descriptor
,
632 sizeof(qemu_mouse_config_descriptor
));
633 ret
= sizeof(qemu_mouse_config_descriptor
);
634 } else if (s
->kind
== USB_TABLET
) {
635 memcpy(data
, qemu_tablet_config_descriptor
,
636 sizeof(qemu_tablet_config_descriptor
));
637 ret
= sizeof(qemu_tablet_config_descriptor
);
638 } else if (s
->kind
== USB_KEYBOARD
) {
639 memcpy(data
, qemu_keyboard_config_descriptor
,
640 sizeof(qemu_keyboard_config_descriptor
));
641 ret
= sizeof(qemu_keyboard_config_descriptor
);
645 switch(value
& 0xff) {
656 ret
= set_usb_string(data
, "1");
659 /* product description */
660 ret
= set_usb_string(data
, s
->dev
.devname
);
663 /* vendor description */
664 ret
= set_usb_string(data
, "QEMU " QEMU_VERSION
);
667 ret
= set_usb_string(data
, "HID Mouse");
670 ret
= set_usb_string(data
, "HID Tablet");
673 ret
= set_usb_string(data
, "HID Keyboard");
676 ret
= set_usb_string(data
, "Endpoint1 Interrupt Pipe");
686 case DeviceRequest
| USB_REQ_GET_CONFIGURATION
:
690 case DeviceOutRequest
| USB_REQ_SET_CONFIGURATION
:
693 case DeviceRequest
| USB_REQ_GET_INTERFACE
:
697 case DeviceOutRequest
| USB_REQ_SET_INTERFACE
:
700 /* hid specific requests */
701 case InterfaceRequest
| USB_REQ_GET_DESCRIPTOR
:
704 if (s
->kind
== USB_MOUSE
) {
705 memcpy(data
, qemu_mouse_hid_report_descriptor
,
706 sizeof(qemu_mouse_hid_report_descriptor
));
707 ret
= sizeof(qemu_mouse_hid_report_descriptor
);
708 } else if (s
->kind
== USB_TABLET
) {
709 memcpy(data
, qemu_tablet_hid_report_descriptor
,
710 sizeof(qemu_tablet_hid_report_descriptor
));
711 ret
= sizeof(qemu_tablet_hid_report_descriptor
);
712 } else if (s
->kind
== USB_KEYBOARD
) {
713 memcpy(data
, qemu_keyboard_hid_report_descriptor
,
714 sizeof(qemu_keyboard_hid_report_descriptor
));
715 ret
= sizeof(qemu_keyboard_hid_report_descriptor
);
723 if (s
->kind
== USB_MOUSE
)
724 ret
= usb_mouse_poll(s
, data
, length
);
725 else if (s
->kind
== USB_TABLET
)
726 ret
= usb_tablet_poll(s
, data
, length
);
727 else if (s
->kind
== USB_KEYBOARD
)
728 ret
= usb_keyboard_poll(&s
->kbd
, data
, length
);
731 if (s
->kind
== USB_KEYBOARD
)
732 ret
= usb_keyboard_write(&s
->kbd
, data
, length
);
737 if (s
->kind
!= USB_KEYBOARD
)
740 data
[0] = s
->protocol
;
743 if (s
->kind
!= USB_KEYBOARD
)
764 static int usb_hid_handle_data(USBDevice
*dev
, USBPacket
*p
)
766 USBHIDState
*s
= (USBHIDState
*)dev
;
772 /* TODO: Implement finite idle delays. */
773 if (!(s
->changed
|| s
->idle
))
776 if (s
->kind
== USB_MOUSE
)
777 ret
= usb_mouse_poll(s
, p
->data
, p
->len
);
778 else if (s
->kind
== USB_TABLET
)
779 ret
= usb_tablet_poll(s
, p
->data
, p
->len
);
780 else if (s
->kind
== USB_KEYBOARD
)
781 ret
= usb_keyboard_poll(&s
->kbd
, p
->data
, p
->len
);
795 static void usb_hid_handle_destroy(USBDevice
*dev
)
797 USBHIDState
*s
= (USBHIDState
*)dev
;
799 if (s
->kind
!= USB_KEYBOARD
)
800 qemu_remove_mouse_event_handler(s
->ptr
.eh_entry
);
805 USBDevice
*usb_tablet_init(void)
809 s
= qemu_mallocz(sizeof(USBHIDState
));
812 s
->dev
.speed
= USB_SPEED_FULL
;
813 s
->dev
.handle_packet
= usb_generic_handle_packet
;
815 s
->dev
.handle_reset
= usb_mouse_handle_reset
;
816 s
->dev
.handle_control
= usb_hid_handle_control
;
817 s
->dev
.handle_data
= usb_hid_handle_data
;
818 s
->dev
.handle_destroy
= usb_hid_handle_destroy
;
819 s
->kind
= USB_TABLET
;
820 /* Force poll routine to be run and grab input the first time. */
823 pstrcpy(s
->dev
.devname
, sizeof(s
->dev
.devname
), "QEMU USB Tablet");
825 return (USBDevice
*)s
;
828 USBDevice
*usb_mouse_init(void)
832 s
= qemu_mallocz(sizeof(USBHIDState
));
835 s
->dev
.speed
= USB_SPEED_FULL
;
836 s
->dev
.handle_packet
= usb_generic_handle_packet
;
838 s
->dev
.handle_reset
= usb_mouse_handle_reset
;
839 s
->dev
.handle_control
= usb_hid_handle_control
;
840 s
->dev
.handle_data
= usb_hid_handle_data
;
841 s
->dev
.handle_destroy
= usb_hid_handle_destroy
;
843 /* Force poll routine to be run and grab input the first time. */
846 pstrcpy(s
->dev
.devname
, sizeof(s
->dev
.devname
), "QEMU USB Mouse");
848 return (USBDevice
*)s
;
851 USBDevice
*usb_keyboard_init(void)
855 s
= qemu_mallocz(sizeof(USBHIDState
));
858 s
->dev
.speed
= USB_SPEED_FULL
;
859 s
->dev
.handle_packet
= usb_generic_handle_packet
;
861 s
->dev
.handle_reset
= usb_keyboard_handle_reset
;
862 s
->dev
.handle_control
= usb_hid_handle_control
;
863 s
->dev
.handle_data
= usb_hid_handle_data
;
864 s
->dev
.handle_destroy
= usb_hid_handle_destroy
;
865 s
->kind
= USB_KEYBOARD
;
867 pstrcpy(s
->dev
.devname
, sizeof(s
->dev
.devname
), "QEMU USB Keyboard");
869 return (USBDevice
*) s
;