]> git.proxmox.com Git - qemu.git/blame - hw/usb-hid.c
Add USB HID keyboard.
[qemu.git] / hw / usb-hid.c
CommitLineData
59ae540c
FB
1/*
2 * QEMU USB HID devices
3 *
4 * Copyright (c) 2005 Fabrice Bellard
47b2d338 5 * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com)
59ae540c
FB
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 "vl.h"
26
27/* HID interface requests */
28#define GET_REPORT 0xa101
29#define GET_IDLE 0xa102
30#define GET_PROTOCOL 0xa103
47b2d338 31#define SET_REPORT 0x2109
59ae540c
FB
32#define SET_IDLE 0x210a
33#define SET_PROTOCOL 0x210b
34
47b2d338
AZ
35/* HID descriptor types */
36#define USB_DT_HID 0x21
37#define USB_DT_REPORT 0x22
38#define USB_DT_PHY 0x23
39
40#define USB_MOUSE 1
41#define USB_TABLET 2
42#define USB_KEYBOARD 3
09b26c5e 43
59ae540c 44typedef struct USBMouseState {
59ae540c 45 int dx, dy, dz, buttons_state;
09b26c5e 46 int x, y;
09b26c5e 47 int mouse_grabbed;
455204eb 48 QEMUPutMouseEntry *eh_entry;
59ae540c
FB
49} USBMouseState;
50
47b2d338
AZ
51typedef struct USBKeyboardState {
52 uint16_t modifiers;
53 uint8_t leds;
54 uint8_t key[16];
55 int keys;
56} USBKeyboardState;
57
58typedef struct USBHIDState {
59 USBDevice dev;
60 union {
61 USBMouseState ptr;
62 USBKeyboardState kbd;
63 };
64 int kind;
65 int protocol;
66 int idle;
67} USBHIDState;
68
59ae540c
FB
69/* mostly the same values as the Bochs USB Mouse device */
70static const uint8_t qemu_mouse_dev_descriptor[] = {
71 0x12, /* u8 bLength; */
72 0x01, /* u8 bDescriptorType; Device */
e126cf13 73 0x00, 0x01, /* u16 bcdUSB; v1.0 */
59ae540c
FB
74
75 0x00, /* u8 bDeviceClass; */
76 0x00, /* u8 bDeviceSubClass; */
77 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
78 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
79
80 0x27, 0x06, /* u16 idVendor; */
81 0x01, 0x00, /* u16 idProduct; */
82 0x00, 0x00, /* u16 bcdDevice */
83
84 0x03, /* u8 iManufacturer; */
85 0x02, /* u8 iProduct; */
86 0x01, /* u8 iSerialNumber; */
87 0x01 /* u8 bNumConfigurations; */
88};
89
90static 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;
99 Bit 7: must be set,
100 6: Self-powered,
101 5: Remote wakeup,
102 4..0: resvd */
103 50, /* u8 MaxPower; */
104
105 /* USB 1.1:
106 * USB 2.0, single TT organization (mandatory):
107 * one interface, protocol 0
108 *
109 * USB 2.0, multiple TT organization (optional):
110 * two interfaces, protocols 1 (like single TT)
111 * and 2 (multiple TT mode) ... config is
112 * sometimes settable
113 * NOT IMPLEMENTED
114 */
115
116 /* one interface */
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] */
47b2d338 125 0x07, /* u8 if_iInterface; */
59ae540c 126
09b26c5e
FB
127 /* HID descriptor */
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 */
134 50, 0, /* u16 len */
135
59ae540c
FB
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) */
09b26c5e
FB
143};
144
145static 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; */
47b2d338 152 0x05, /* u8 iConfiguration; */
09b26c5e
FB
153 0xa0, /* u8 bmAttributes;
154 Bit 7: must be set,
155 6: Self-powered,
156 5: Remote wakeup,
157 4..0: resvd */
158 50, /* u8 MaxPower; */
159
160 /* USB 1.1:
161 * USB 2.0, single TT organization (mandatory):
162 * one interface, protocol 0
163 *
164 * USB 2.0, multiple TT organization (optional):
165 * two interfaces, protocols 1 (like single TT)
166 * and 2 (multiple TT mode) ... config is
167 * sometimes settable
168 * NOT IMPLEMENTED
169 */
170
171 /* one interface */
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] */
47b2d338 180 0x07, /* u8 if_iInterface; */
59ae540c
FB
181
182 /* HID descriptor */
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 */
09b26c5e
FB
189 74, 0, /* u16 len */
190
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; */
f2f1ac82 197 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
59ae540c
FB
198};
199
47b2d338
AZ
200static 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;
209 Bit 7: must be set,
210 6: Self-powered,
211 5: Remote wakeup,
212 4..0: resvd */
213 0x32, /* u8 MaxPower; */
214
215 /* USB 1.1:
216 * USB 2.0, single TT organization (mandatory):
217 * one interface, protocol 0
218 *
219 * USB 2.0, multiple TT organization (optional):
220 * two interfaces, protocols 1 (like single TT)
221 * and 2 (multiple TT mode) ... config is
222 * sometimes settable
223 * NOT IMPLEMENTED
224 */
225
226 /* one interface */
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; */
236
237 /* HID descriptor */
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 */
245
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) */
253};
254
59ae540c
FB
255static 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,
262 0xC0, 0xC0,
263};
264
09b26c5e
FB
265static 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 */
303};
304
47b2d338
AZ
305static 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 */
338};
339
340#define USB_HID_USAGE_ERROR_ROLLOVER 0x01
341#define USB_HID_USAGE_POSTFAIL 0x02
342#define USB_HID_USAGE_ERROR_UNDEFINED 0x03
343
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. */
346static 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,
363
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,
380};
381
59ae540c
FB
382static void usb_mouse_event(void *opaque,
383 int dx1, int dy1, int dz1, int buttons_state)
384{
385 USBMouseState *s = opaque;
386
387 s->dx += dx1;
388 s->dy += dy1;
389 s->dz += dz1;
390 s->buttons_state = buttons_state;
391}
392
09b26c5e
FB
393static void usb_tablet_event(void *opaque,
394 int x, int y, int dz, int buttons_state)
395{
396 USBMouseState *s = opaque;
397
398 s->x = x;
399 s->y = y;
400 s->dz += dz;
401 s->buttons_state = buttons_state;
402}
403
47b2d338
AZ
404static void usb_keyboard_event(void *opaque, int keycode)
405{
406 USBKeyboardState *s = opaque;
407 uint8_t hid_code, key;
408 int i;
409
410 key = keycode & 0x7f;
411 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
412 s->modifiers &= ~(1 << 8);
413
414 switch (hid_code) {
415 case 0x00:
416 return;
417
418 case 0xe0:
419 if (s->modifiers & (1 << 9)) {
420 s->modifiers ^= 3 << 8;
421 return;
422 }
423 case 0xe1 ... 0xe7:
424 if (keycode & (1 << 7)) {
425 s->modifiers &= ~(1 << (hid_code & 0x0f));
426 return;
427 }
428 case 0xe8 ... 0xef:
429 s->modifiers |= 1 << (hid_code & 0x0f);
430 return;
431 }
432
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;
438 return;
439 }
440 } else {
441 for (i = s->keys - 1; i >= 0; i --)
442 if (s->key[i] == hid_code)
443 return;
444 if (s->keys < sizeof(s->key))
445 s->key[s->keys ++] = hid_code;
446 }
447}
448
59ae540c
FB
449static inline int int_clamp(int val, int vmin, int vmax)
450{
451 if (val < vmin)
452 return vmin;
453 else if (val > vmax)
454 return vmax;
455 else
456 return val;
457}
458
459static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
460{
461 int dx, dy, dz, b, l;
462
09b26c5e 463 if (!s->mouse_grabbed) {
455204eb
TS
464 s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
465 0, "QEMU USB Mouse");
09b26c5e
FB
466 s->mouse_grabbed = 1;
467 }
468
59ae540c
FB
469 dx = int_clamp(s->dx, -128, 127);
470 dy = int_clamp(s->dy, -128, 127);
471 dz = int_clamp(s->dz, -128, 127);
472
473 s->dx -= dx;
474 s->dy -= dy;
475 s->dz -= dz;
476
477 b = 0;
478 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
479 b |= 0x01;
480 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
481 b |= 0x02;
482 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
483 b |= 0x04;
484
485 buf[0] = b;
486 buf[1] = dx;
487 buf[2] = dy;
488 l = 3;
489 if (len >= 4) {
490 buf[3] = dz;
491 l = 4;
492 }
493 return l;
494}
495
09b26c5e
FB
496static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
497{
498 int dz, b, l;
499
500 if (!s->mouse_grabbed) {
455204eb
TS
501 s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
502 1, "QEMU USB Tablet");
09b26c5e
FB
503 s->mouse_grabbed = 1;
504 }
505
506 dz = int_clamp(s->dz, -128, 127);
507 s->dz -= dz;
508
509 /* Appears we have to invert the wheel direction */
510 dz = 0 - dz;
511 b = 0;
512 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
513 b |= 0x01;
514 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
515 b |= 0x02;
516 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
517 b |= 0x04;
518
519 buf[0] = b;
520 buf[1] = s->x & 0xff;
521 buf[2] = s->x >> 8;
522 buf[3] = s->y & 0xff;
523 buf[4] = s->y >> 8;
524 buf[5] = dz;
525 l = 6;
526
527 return l;
528}
529
47b2d338
AZ
530static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
531{
532 if (len < 2)
533 return 0;
534
535 buf[0] = s->modifiers & 0xff;
536 buf[1] = 0;
537 if (s->keys > 6)
538 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
539 else
540 memcpy(buf + 2, s->key, MIN(8, len) - 2);
541
542 return MIN(8, len);
543}
544
545static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
546{
547 if (len > 0) {
548 /* 0x01: Num Lock LED
549 * 0x02: Caps Lock LED
550 * 0x04: Scroll Lock LED
551 * 0x08: Compose LED
552 * 0x10: Kana LED */
553 s->leds = buf[0];
554 }
555 return 0;
556}
557
059809e4 558static void usb_mouse_handle_reset(USBDevice *dev)
59ae540c 559{
47b2d338
AZ
560 USBHIDState *s = (USBHIDState *)dev;
561
562 s->ptr.dx = 0;
563 s->ptr.dy = 0;
564 s->ptr.dz = 0;
565 s->ptr.x = 0;
566 s->ptr.y = 0;
567 s->ptr.buttons_state = 0;
568 s->protocol = 1;
569}
570
571static void usb_keyboard_handle_reset(USBDevice *dev)
572{
573 USBHIDState *s = (USBHIDState *)dev;
574
575 qemu_add_kbd_event_handler(usb_keyboard_event, &s->kbd);
576 s->protocol = 1;
59ae540c
FB
577}
578
47b2d338 579static int usb_hid_handle_control(USBDevice *dev, int request, int value,
59ae540c
FB
580 int index, int length, uint8_t *data)
581{
47b2d338 582 USBHIDState *s = (USBHIDState *)dev;
09b26c5e 583 int ret = 0;
59ae540c
FB
584
585 switch(request) {
586 case DeviceRequest | USB_REQ_GET_STATUS:
587 data[0] = (1 << USB_DEVICE_SELF_POWERED) |
588 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
589 data[1] = 0x00;
590 ret = 2;
591 break;
592 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
593 if (value == USB_DEVICE_REMOTE_WAKEUP) {
594 dev->remote_wakeup = 0;
595 } else {
596 goto fail;
597 }
598 ret = 0;
599 break;
600 case DeviceOutRequest | USB_REQ_SET_FEATURE:
601 if (value == USB_DEVICE_REMOTE_WAKEUP) {
602 dev->remote_wakeup = 1;
603 } else {
604 goto fail;
605 }
606 ret = 0;
607 break;
608 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
609 dev->addr = value;
610 ret = 0;
611 break;
612 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
613 switch(value >> 8) {
614 case USB_DT_DEVICE:
615 memcpy(data, qemu_mouse_dev_descriptor,
616 sizeof(qemu_mouse_dev_descriptor));
617 ret = sizeof(qemu_mouse_dev_descriptor);
618 break;
619 case USB_DT_CONFIG:
09b26c5e
FB
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);
47b2d338
AZ
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);
632 }
59ae540c
FB
633 break;
634 case USB_DT_STRING:
635 switch(value & 0xff) {
636 case 0:
637 /* language ids */
638 data[0] = 4;
639 data[1] = 3;
640 data[2] = 0x09;
641 data[3] = 0x04;
642 ret = 4;
643 break;
644 case 1:
645 /* serial number */
646 ret = set_usb_string(data, "1");
647 break;
648 case 2:
649 /* product description */
47b2d338 650 ret = set_usb_string(data, s->dev.devname);
59ae540c
FB
651 break;
652 case 3:
653 /* vendor description */
654 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
655 break;
656 case 4:
657 ret = set_usb_string(data, "HID Mouse");
658 break;
659 case 5:
47b2d338
AZ
660 ret = set_usb_string(data, "HID Tablet");
661 break;
662 case 6:
663 ret = set_usb_string(data, "HID Keyboard");
664 break;
665 case 7:
59ae540c
FB
666 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
667 break;
668 default:
669 goto fail;
670 }
671 break;
672 default:
673 goto fail;
674 }
675 break;
676 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
677 data[0] = 1;
678 ret = 1;
679 break;
680 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
681 ret = 0;
682 break;
683 case DeviceRequest | USB_REQ_GET_INTERFACE:
684 data[0] = 0;
685 ret = 1;
686 break;
687 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
688 ret = 0;
689 break;
690 /* hid specific requests */
691 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
692 switch(value >> 8) {
693 case 0x22:
09b26c5e
FB
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);
47b2d338
AZ
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);
706 }
707 break;
59ae540c
FB
708 default:
709 goto fail;
710 }
711 break;
712 case GET_REPORT:
09b26c5e 713 if (s->kind == USB_MOUSE)
47b2d338 714 ret = usb_mouse_poll(&s->ptr, data, length);
09b26c5e 715 else if (s->kind == USB_TABLET)
47b2d338
AZ
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);
719 break;
720 case SET_REPORT:
721 if (s->kind == USB_KEYBOARD)
722 ret = usb_keyboard_write(&s->kbd, data, length);
723 else
724 goto fail;
725 break;
726 case GET_PROTOCOL:
727 if (s->kind != USB_KEYBOARD)
728 goto fail;
729 ret = 1;
730 data[0] = s->protocol;
731 break;
732 case SET_PROTOCOL:
733 if (s->kind != USB_KEYBOARD)
734 goto fail;
735 ret = 0;
736 s->protocol = value;
737 break;
738 case GET_IDLE:
739 ret = 1;
740 data[0] = s->idle;
59ae540c
FB
741 break;
742 case SET_IDLE:
47b2d338 743 s->idle = value;
59ae540c
FB
744 ret = 0;
745 break;
746 default:
747 fail:
748 ret = USB_RET_STALL;
749 break;
750 }
751 return ret;
752}
753
47b2d338 754static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
59ae540c 755{
47b2d338 756 USBHIDState *s = (USBHIDState *)dev;
09b26c5e 757 int ret = 0;
59ae540c 758
4d611c9a 759 switch(p->pid) {
59ae540c 760 case USB_TOKEN_IN:
4d611c9a 761 if (p->devep == 1) {
47b2d338
AZ
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);
59ae540c
FB
768 } else {
769 goto fail;
770 }
771 break;
772 case USB_TOKEN_OUT:
773 default:
774 fail:
775 ret = USB_RET_STALL;
776 break;
777 }
778 return ret;
779}
780
47b2d338 781static void usb_hid_handle_destroy(USBDevice *dev)
059809e4 782{
47b2d338 783 USBHIDState *s = (USBHIDState *)dev;
059809e4 784
47b2d338
AZ
785 if (s->kind != USB_KEYBOARD)
786 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
787 /* TODO: else */
059809e4
FB
788 qemu_free(s);
789}
790
09b26c5e
FB
791USBDevice *usb_tablet_init(void)
792{
47b2d338 793 USBHIDState *s;
09b26c5e 794
47b2d338 795 s = qemu_mallocz(sizeof(USBHIDState));
09b26c5e
FB
796 if (!s)
797 return NULL;
798 s->dev.speed = USB_SPEED_FULL;
799 s->dev.handle_packet = usb_generic_handle_packet;
800
801 s->dev.handle_reset = usb_mouse_handle_reset;
47b2d338
AZ
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;
09b26c5e
FB
805 s->kind = USB_TABLET;
806
1f6e24e7
FB
807 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
808
09b26c5e
FB
809 return (USBDevice *)s;
810}
811
59ae540c
FB
812USBDevice *usb_mouse_init(void)
813{
47b2d338 814 USBHIDState *s;
59ae540c 815
47b2d338 816 s = qemu_mallocz(sizeof(USBHIDState));
59ae540c
FB
817 if (!s)
818 return NULL;
819 s->dev.speed = USB_SPEED_FULL;
820 s->dev.handle_packet = usb_generic_handle_packet;
821
822 s->dev.handle_reset = usb_mouse_handle_reset;
47b2d338
AZ
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;
09b26c5e 826 s->kind = USB_MOUSE;
59ae540c 827
1f6e24e7
FB
828 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
829
59ae540c
FB
830 return (USBDevice *)s;
831}
47b2d338
AZ
832
833USBDevice *usb_keyboard_init(void)
834{
835 USBHIDState *s;
836
837 s = qemu_mallocz(sizeof(USBHIDState));
838 if (!s)
839 return NULL;
840 s->dev.speed = USB_SPEED_FULL;
841 s->dev.handle_packet = usb_generic_handle_packet;
842
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;
848
849 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");
850
851 return (USBDevice *) s;
852}