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