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
{
69 /* mostly the same values as the Bochs USB Mouse device */
70 static const uint8_t qemu_mouse_dev_descriptor
[] = {
71 0x12, /* u8 bLength; */
72 0x01, /* u8 bDescriptorType; Device */
73 0x00, 0x01, /* u16 bcdUSB; v1.0 */
75 0x00, /* u8 bDeviceClass; */
76 0x00, /* u8 bDeviceSubClass; */
77 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
78 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
80 0x27, 0x06, /* u16 idVendor; */
81 0x01, 0x00, /* u16 idProduct; */
82 0x00, 0x00, /* u16 bcdDevice */
84 0x03, /* u8 iManufacturer; */
85 0x02, /* u8 iProduct; */
86 0x01, /* u8 iSerialNumber; */
87 0x01 /* u8 bNumConfigurations; */
90 static const uint8_t qemu_mouse_config_descriptor
[] = {
91 /* one configuration */
92 0x09, /* u8 bLength; */
93 0x02, /* u8 bDescriptorType; Configuration */
94 0x22, 0x00, /* u16 wTotalLength; */
95 0x01, /* u8 bNumInterfaces; (1) */
96 0x01, /* u8 bConfigurationValue; */
97 0x04, /* u8 iConfiguration; */
98 0xa0, /* u8 bmAttributes;
103 50, /* u8 MaxPower; */
106 * USB 2.0, single TT organization (mandatory):
107 * one interface, protocol 0
109 * USB 2.0, multiple TT organization (optional):
110 * two interfaces, protocols 1 (like single TT)
111 * and 2 (multiple TT mode) ... config is
117 0x09, /* u8 if_bLength; */
118 0x04, /* u8 if_bDescriptorType; Interface */
119 0x00, /* u8 if_bInterfaceNumber; */
120 0x00, /* u8 if_bAlternateSetting; */
121 0x01, /* u8 if_bNumEndpoints; */
122 0x03, /* u8 if_bInterfaceClass; */
123 0x01, /* u8 if_bInterfaceSubClass; */
124 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
125 0x07, /* u8 if_iInterface; */
128 0x09, /* u8 bLength; */
129 0x21, /* u8 bDescriptorType; */
130 0x01, 0x00, /* u16 HID_class */
131 0x00, /* u8 country_code */
132 0x01, /* u8 num_descriptors */
133 0x22, /* u8 type; Report */
136 /* one endpoint (status change endpoint) */
137 0x07, /* u8 ep_bLength; */
138 0x05, /* u8 ep_bDescriptorType; Endpoint */
139 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
140 0x03, /* u8 ep_bmAttributes; Interrupt */
141 0x03, 0x00, /* u16 ep_wMaxPacketSize; */
142 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
145 static const uint8_t qemu_tablet_config_descriptor
[] = {
146 /* one configuration */
147 0x09, /* u8 bLength; */
148 0x02, /* u8 bDescriptorType; Configuration */
149 0x22, 0x00, /* u16 wTotalLength; */
150 0x01, /* u8 bNumInterfaces; (1) */
151 0x01, /* u8 bConfigurationValue; */
152 0x05, /* u8 iConfiguration; */
153 0xa0, /* u8 bmAttributes;
158 50, /* u8 MaxPower; */
161 * USB 2.0, single TT organization (mandatory):
162 * one interface, protocol 0
164 * USB 2.0, multiple TT organization (optional):
165 * two interfaces, protocols 1 (like single TT)
166 * and 2 (multiple TT mode) ... config is
172 0x09, /* u8 if_bLength; */
173 0x04, /* u8 if_bDescriptorType; Interface */
174 0x00, /* u8 if_bInterfaceNumber; */
175 0x00, /* u8 if_bAlternateSetting; */
176 0x01, /* u8 if_bNumEndpoints; */
177 0x03, /* u8 if_bInterfaceClass; */
178 0x01, /* u8 if_bInterfaceSubClass; */
179 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
180 0x07, /* u8 if_iInterface; */
183 0x09, /* u8 bLength; */
184 0x21, /* u8 bDescriptorType; */
185 0x01, 0x00, /* u16 HID_class */
186 0x00, /* u8 country_code */
187 0x01, /* u8 num_descriptors */
188 0x22, /* u8 type; Report */
191 /* one endpoint (status change endpoint) */
192 0x07, /* u8 ep_bLength; */
193 0x05, /* u8 ep_bDescriptorType; Endpoint */
194 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
195 0x03, /* u8 ep_bmAttributes; Interrupt */
196 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
197 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
200 static const uint8_t qemu_keyboard_config_descriptor
[] = {
201 /* one configuration */
202 0x09, /* u8 bLength; */
203 USB_DT_CONFIG
, /* u8 bDescriptorType; Configuration */
204 0x22, 0x00, /* u16 wTotalLength; */
205 0x01, /* u8 bNumInterfaces; (1) */
206 0x01, /* u8 bConfigurationValue; */
207 0x06, /* u8 iConfiguration; */
208 0xa0, /* u8 bmAttributes;
213 0x32, /* u8 MaxPower; */
216 * USB 2.0, single TT organization (mandatory):
217 * one interface, protocol 0
219 * USB 2.0, multiple TT organization (optional):
220 * two interfaces, protocols 1 (like single TT)
221 * and 2 (multiple TT mode) ... config is
227 0x09, /* u8 if_bLength; */
228 USB_DT_INTERFACE
, /* u8 if_bDescriptorType; Interface */
229 0x00, /* u8 if_bInterfaceNumber; */
230 0x00, /* u8 if_bAlternateSetting; */
231 0x01, /* u8 if_bNumEndpoints; */
232 0x03, /* u8 if_bInterfaceClass; HID */
233 0x01, /* u8 if_bInterfaceSubClass; Boot */
234 0x01, /* u8 if_bInterfaceProtocol; Keyboard */
235 0x07, /* u8 if_iInterface; */
238 0x09, /* u8 bLength; */
239 USB_DT_HID
, /* u8 bDescriptorType; */
240 0x11, 0x01, /* u16 HID_class */
241 0x00, /* u8 country_code */
242 0x01, /* u8 num_descriptors */
243 USB_DT_REPORT
, /* u8 type; Report */
244 0x3f, 0x00, /* u16 len */
246 /* one endpoint (status change endpoint) */
247 0x07, /* u8 ep_bLength; */
248 USB_DT_ENDPOINT
, /* u8 ep_bDescriptorType; Endpoint */
249 USB_DIR_IN
| 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
250 0x03, /* u8 ep_bmAttributes; Interrupt */
251 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
252 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
255 static const uint8_t qemu_mouse_hid_report_descriptor
[] = {
256 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01,
257 0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
258 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
259 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
260 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81,
261 0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
265 static const uint8_t qemu_tablet_hid_report_descriptor
[] = {
266 0x05, 0x01, /* Usage Page Generic Desktop */
267 0x09, 0x01, /* Usage Mouse */
268 0xA1, 0x01, /* Collection Application */
269 0x09, 0x01, /* Usage Pointer */
270 0xA1, 0x00, /* Collection Physical */
271 0x05, 0x09, /* Usage Page Button */
272 0x19, 0x01, /* Usage Minimum Button 1 */
273 0x29, 0x03, /* Usage Maximum Button 3 */
274 0x15, 0x00, /* Logical Minimum 0 */
275 0x25, 0x01, /* Logical Maximum 1 */
276 0x95, 0x03, /* Report Count 3 */
277 0x75, 0x01, /* Report Size 1 */
278 0x81, 0x02, /* Input (Data, Var, Abs) */
279 0x95, 0x01, /* Report Count 1 */
280 0x75, 0x05, /* Report Size 5 */
281 0x81, 0x01, /* Input (Cnst, Var, Abs) */
282 0x05, 0x01, /* Usage Page Generic Desktop */
283 0x09, 0x30, /* Usage X */
284 0x09, 0x31, /* Usage Y */
285 0x15, 0x00, /* Logical Minimum 0 */
286 0x26, 0xFF, 0x7F, /* Logical Maximum 0x7fff */
287 0x35, 0x00, /* Physical Minimum 0 */
288 0x46, 0xFE, 0x7F, /* Physical Maximum 0x7fff */
289 0x75, 0x10, /* Report Size 16 */
290 0x95, 0x02, /* Report Count 2 */
291 0x81, 0x02, /* Input (Data, Var, Abs) */
292 0x05, 0x01, /* Usage Page Generic Desktop */
293 0x09, 0x38, /* Usage Wheel */
294 0x15, 0x81, /* Logical Minimum -127 */
295 0x25, 0x7F, /* Logical Maximum 127 */
296 0x35, 0x00, /* Physical Minimum 0 (same as logical) */
297 0x45, 0x00, /* Physical Maximum 0 (same as logical) */
298 0x75, 0x08, /* Report Size 8 */
299 0x95, 0x01, /* Report Count 1 */
300 0x81, 0x02, /* Input (Data, Var, Rel) */
301 0xC0, /* End Collection */
302 0xC0, /* End Collection */
305 static const uint8_t qemu_keyboard_hid_report_descriptor
[] = {
306 0x05, 0x01, /* Usage Page (Generic Desktop) */
307 0x09, 0x06, /* Usage (Keyboard) */
308 0xa1, 0x01, /* Collection (Application) */
309 0x75, 0x01, /* Report Size (1) */
310 0x95, 0x08, /* Report Count (8) */
311 0x05, 0x07, /* Usage Page (Key Codes) */
312 0x19, 0xe0, /* Usage Minimum (224) */
313 0x29, 0xe7, /* Usage Maximum (231) */
314 0x15, 0x00, /* Logical Minimum (0) */
315 0x25, 0x01, /* Logical Maximum (1) */
316 0x81, 0x02, /* Input (Data, Variable, Absolute) */
317 0x95, 0x01, /* Report Count (1) */
318 0x75, 0x08, /* Report Size (8) */
319 0x81, 0x01, /* Input (Constant) */
320 0x95, 0x05, /* Report Count (5) */
321 0x75, 0x01, /* Report Size (1) */
322 0x05, 0x08, /* Usage Page (LEDs) */
323 0x19, 0x01, /* Usage Minimum (1) */
324 0x29, 0x05, /* Usage Maximum (5) */
325 0x91, 0x02, /* Output (Data, Variable, Absolute) */
326 0x95, 0x01, /* Report Count (1) */
327 0x75, 0x03, /* Report Size (3) */
328 0x91, 0x01, /* Output (Constant) */
329 0x95, 0x06, /* Report Count (6) */
330 0x75, 0x08, /* Report Size (8) */
331 0x15, 0x00, /* Logical Minimum (0) */
332 0x25, 0xff, /* Logical Maximum (255) */
333 0x05, 0x07, /* Usage Page (Key Codes) */
334 0x19, 0x00, /* Usage Minimum (0) */
335 0x29, 0xff, /* Usage Maximum (255) */
336 0x81, 0x00, /* Input (Data, Array) */
337 0xc0, /* End Collection */
340 #define USB_HID_USAGE_ERROR_ROLLOVER 0x01
341 #define USB_HID_USAGE_POSTFAIL 0x02
342 #define USB_HID_USAGE_ERROR_UNDEFINED 0x03
344 /* Indices are QEMU keycodes, values are from HID Usage Table. Indices
345 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
346 static const uint8_t usb_hid_usage_keys
[0x100] = {
347 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
348 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
349 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
350 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
351 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
352 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
353 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
354 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
355 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
356 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
357 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
358 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
359 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
371 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
373 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
374 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 static void usb_mouse_event(void *opaque
,
383 int dx1
, int dy1
, int dz1
, int buttons_state
)
385 USBMouseState
*s
= opaque
;
390 s
->buttons_state
= buttons_state
;
393 static void usb_tablet_event(void *opaque
,
394 int x
, int y
, int dz
, int buttons_state
)
396 USBMouseState
*s
= opaque
;
401 s
->buttons_state
= buttons_state
;
404 static void usb_keyboard_event(void *opaque
, int keycode
)
406 USBKeyboardState
*s
= opaque
;
407 uint8_t hid_code
, key
;
410 key
= keycode
& 0x7f;
411 hid_code
= usb_hid_usage_keys
[key
| ((s
->modifiers
>> 1) & (1 << 7))];
412 s
->modifiers
&= ~(1 << 8);
419 if (s
->modifiers
& (1 << 9)) {
420 s
->modifiers
^= 3 << 8;
424 if (keycode
& (1 << 7)) {
425 s
->modifiers
&= ~(1 << (hid_code
& 0x0f));
429 s
->modifiers
|= 1 << (hid_code
& 0x0f);
433 if (keycode
& (1 << 7)) {
434 for (i
= s
->keys
- 1; i
>= 0; i
--)
435 if (s
->key
[i
] == hid_code
) {
436 s
->key
[i
] = s
->key
[-- s
->keys
];
437 s
->key
[s
->keys
] = 0x00;
441 for (i
= s
->keys
- 1; i
>= 0; i
--)
442 if (s
->key
[i
] == hid_code
)
444 if (s
->keys
< sizeof(s
->key
))
445 s
->key
[s
->keys
++] = hid_code
;
449 static inline int int_clamp(int val
, int vmin
, int vmax
)
459 static int usb_mouse_poll(USBMouseState
*s
, uint8_t *buf
, int len
)
461 int dx
, dy
, dz
, b
, l
;
463 if (!s
->mouse_grabbed
) {
464 s
->eh_entry
= qemu_add_mouse_event_handler(usb_mouse_event
, s
,
465 0, "QEMU USB Mouse");
466 s
->mouse_grabbed
= 1;
469 dx
= int_clamp(s
->dx
, -128, 127);
470 dy
= int_clamp(s
->dy
, -128, 127);
471 dz
= int_clamp(s
->dz
, -128, 127);
478 if (s
->buttons_state
& MOUSE_EVENT_LBUTTON
)
480 if (s
->buttons_state
& MOUSE_EVENT_RBUTTON
)
482 if (s
->buttons_state
& MOUSE_EVENT_MBUTTON
)
496 static int usb_tablet_poll(USBMouseState
*s
, uint8_t *buf
, int len
)
500 if (!s
->mouse_grabbed
) {
501 s
->eh_entry
= qemu_add_mouse_event_handler(usb_tablet_event
, s
,
502 1, "QEMU USB Tablet");
503 s
->mouse_grabbed
= 1;
506 dz
= int_clamp(s
->dz
, -128, 127);
509 /* Appears we have to invert the wheel direction */
512 if (s
->buttons_state
& MOUSE_EVENT_LBUTTON
)
514 if (s
->buttons_state
& MOUSE_EVENT_RBUTTON
)
516 if (s
->buttons_state
& MOUSE_EVENT_MBUTTON
)
520 buf
[1] = s
->x
& 0xff;
522 buf
[3] = s
->y
& 0xff;
530 static int usb_keyboard_poll(USBKeyboardState
*s
, uint8_t *buf
, int len
)
535 buf
[0] = s
->modifiers
& 0xff;
538 memset(buf
+ 2, USB_HID_USAGE_ERROR_ROLLOVER
, MIN(8, len
) - 2);
540 memcpy(buf
+ 2, s
->key
, MIN(8, len
) - 2);
545 static int usb_keyboard_write(USBKeyboardState
*s
, uint8_t *buf
, int len
)
548 /* 0x01: Num Lock LED
549 * 0x02: Caps Lock LED
550 * 0x04: Scroll Lock LED
558 static void usb_mouse_handle_reset(USBDevice
*dev
)
560 USBHIDState
*s
= (USBHIDState
*)dev
;
567 s
->ptr
.buttons_state
= 0;
571 static void usb_keyboard_handle_reset(USBDevice
*dev
)
573 USBHIDState
*s
= (USBHIDState
*)dev
;
575 qemu_add_kbd_event_handler(usb_keyboard_event
, &s
->kbd
);
579 static int usb_hid_handle_control(USBDevice
*dev
, int request
, int value
,
580 int index
, int length
, uint8_t *data
)
582 USBHIDState
*s
= (USBHIDState
*)dev
;
586 case DeviceRequest
| USB_REQ_GET_STATUS
:
587 data
[0] = (1 << USB_DEVICE_SELF_POWERED
) |
588 (dev
->remote_wakeup
<< USB_DEVICE_REMOTE_WAKEUP
);
592 case DeviceOutRequest
| USB_REQ_CLEAR_FEATURE
:
593 if (value
== USB_DEVICE_REMOTE_WAKEUP
) {
594 dev
->remote_wakeup
= 0;
600 case DeviceOutRequest
| USB_REQ_SET_FEATURE
:
601 if (value
== USB_DEVICE_REMOTE_WAKEUP
) {
602 dev
->remote_wakeup
= 1;
608 case DeviceOutRequest
| USB_REQ_SET_ADDRESS
:
612 case DeviceRequest
| USB_REQ_GET_DESCRIPTOR
:
615 memcpy(data
, qemu_mouse_dev_descriptor
,
616 sizeof(qemu_mouse_dev_descriptor
));
617 ret
= sizeof(qemu_mouse_dev_descriptor
);
620 if (s
->kind
== USB_MOUSE
) {
621 memcpy(data
, qemu_mouse_config_descriptor
,
622 sizeof(qemu_mouse_config_descriptor
));
623 ret
= sizeof(qemu_mouse_config_descriptor
);
624 } else if (s
->kind
== USB_TABLET
) {
625 memcpy(data
, qemu_tablet_config_descriptor
,
626 sizeof(qemu_tablet_config_descriptor
));
627 ret
= sizeof(qemu_tablet_config_descriptor
);
628 } else if (s
->kind
== USB_KEYBOARD
) {
629 memcpy(data
, qemu_keyboard_config_descriptor
,
630 sizeof(qemu_keyboard_config_descriptor
));
631 ret
= sizeof(qemu_keyboard_config_descriptor
);
635 switch(value
& 0xff) {
646 ret
= set_usb_string(data
, "1");
649 /* product description */
650 ret
= set_usb_string(data
, s
->dev
.devname
);
653 /* vendor description */
654 ret
= set_usb_string(data
, "QEMU " QEMU_VERSION
);
657 ret
= set_usb_string(data
, "HID Mouse");
660 ret
= set_usb_string(data
, "HID Tablet");
663 ret
= set_usb_string(data
, "HID Keyboard");
666 ret
= set_usb_string(data
, "Endpoint1 Interrupt Pipe");
676 case DeviceRequest
| USB_REQ_GET_CONFIGURATION
:
680 case DeviceOutRequest
| USB_REQ_SET_CONFIGURATION
:
683 case DeviceRequest
| USB_REQ_GET_INTERFACE
:
687 case DeviceOutRequest
| USB_REQ_SET_INTERFACE
:
690 /* hid specific requests */
691 case InterfaceRequest
| USB_REQ_GET_DESCRIPTOR
:
694 if (s
->kind
== USB_MOUSE
) {
695 memcpy(data
, qemu_mouse_hid_report_descriptor
,
696 sizeof(qemu_mouse_hid_report_descriptor
));
697 ret
= sizeof(qemu_mouse_hid_report_descriptor
);
698 } else if (s
->kind
== USB_TABLET
) {
699 memcpy(data
, qemu_tablet_hid_report_descriptor
,
700 sizeof(qemu_tablet_hid_report_descriptor
));
701 ret
= sizeof(qemu_tablet_hid_report_descriptor
);
702 } else if (s
->kind
== USB_KEYBOARD
) {
703 memcpy(data
, qemu_keyboard_hid_report_descriptor
,
704 sizeof(qemu_keyboard_hid_report_descriptor
));
705 ret
= sizeof(qemu_keyboard_hid_report_descriptor
);
713 if (s
->kind
== USB_MOUSE
)
714 ret
= usb_mouse_poll(&s
->ptr
, data
, length
);
715 else if (s
->kind
== USB_TABLET
)
716 ret
= usb_tablet_poll(&s
->ptr
, data
, length
);
717 else if (s
->kind
== USB_KEYBOARD
)
718 ret
= usb_keyboard_poll(&s
->kbd
, data
, length
);
721 if (s
->kind
== USB_KEYBOARD
)
722 ret
= usb_keyboard_write(&s
->kbd
, data
, length
);
727 if (s
->kind
!= USB_KEYBOARD
)
730 data
[0] = s
->protocol
;
733 if (s
->kind
!= USB_KEYBOARD
)
754 static int usb_hid_handle_data(USBDevice
*dev
, USBPacket
*p
)
756 USBHIDState
*s
= (USBHIDState
*)dev
;
762 if (s
->kind
== USB_MOUSE
)
763 ret
= usb_mouse_poll(&s
->ptr
, p
->data
, p
->len
);
764 else if (s
->kind
== USB_TABLET
)
765 ret
= usb_tablet_poll(&s
->ptr
, p
->data
, p
->len
);
766 else if (s
->kind
== USB_KEYBOARD
)
767 ret
= usb_keyboard_poll(&s
->kbd
, p
->data
, p
->len
);
781 static void usb_hid_handle_destroy(USBDevice
*dev
)
783 USBHIDState
*s
= (USBHIDState
*)dev
;
785 if (s
->kind
!= USB_KEYBOARD
)
786 qemu_remove_mouse_event_handler(s
->ptr
.eh_entry
);
791 USBDevice
*usb_tablet_init(void)
795 s
= qemu_mallocz(sizeof(USBHIDState
));
798 s
->dev
.speed
= USB_SPEED_FULL
;
799 s
->dev
.handle_packet
= usb_generic_handle_packet
;
801 s
->dev
.handle_reset
= usb_mouse_handle_reset
;
802 s
->dev
.handle_control
= usb_hid_handle_control
;
803 s
->dev
.handle_data
= usb_hid_handle_data
;
804 s
->dev
.handle_destroy
= usb_hid_handle_destroy
;
805 s
->kind
= USB_TABLET
;
807 pstrcpy(s
->dev
.devname
, sizeof(s
->dev
.devname
), "QEMU USB Tablet");
809 return (USBDevice
*)s
;
812 USBDevice
*usb_mouse_init(void)
816 s
= qemu_mallocz(sizeof(USBHIDState
));
819 s
->dev
.speed
= USB_SPEED_FULL
;
820 s
->dev
.handle_packet
= usb_generic_handle_packet
;
822 s
->dev
.handle_reset
= usb_mouse_handle_reset
;
823 s
->dev
.handle_control
= usb_hid_handle_control
;
824 s
->dev
.handle_data
= usb_hid_handle_data
;
825 s
->dev
.handle_destroy
= usb_hid_handle_destroy
;
828 pstrcpy(s
->dev
.devname
, sizeof(s
->dev
.devname
), "QEMU USB Mouse");
830 return (USBDevice
*)s
;
833 USBDevice
*usb_keyboard_init(void)
837 s
= qemu_mallocz(sizeof(USBHIDState
));
840 s
->dev
.speed
= USB_SPEED_FULL
;
841 s
->dev
.handle_packet
= usb_generic_handle_packet
;
843 s
->dev
.handle_reset
= usb_keyboard_handle_reset
;
844 s
->dev
.handle_control
= usb_hid_handle_control
;
845 s
->dev
.handle_data
= usb_hid_handle_data
;
846 s
->dev
.handle_destroy
= usb_hid_handle_destroy
;
847 s
->kind
= USB_KEYBOARD
;
849 pstrcpy(s
->dev
.devname
, sizeof(s
->dev
.devname
), "QEMU USB Keyboard");
851 return (USBDevice
*) s
;