]> git.proxmox.com Git - qemu.git/blame - hw/usb-hid.c
softfloat: fix floatx80_is_{quiet,signaling}_nan()
[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"
666daa68 28#include "sysemu.h"
59ae540c
FB
29
30/* HID interface requests */
31#define GET_REPORT 0xa101
32#define GET_IDLE 0xa102
33#define GET_PROTOCOL 0xa103
47b2d338 34#define SET_REPORT 0x2109
59ae540c
FB
35#define SET_IDLE 0x210a
36#define SET_PROTOCOL 0x210b
37
47b2d338
AZ
38/* HID descriptor types */
39#define USB_DT_HID 0x21
40#define USB_DT_REPORT 0x22
41#define USB_DT_PHY 0x23
42
43#define USB_MOUSE 1
44#define USB_TABLET 2
45#define USB_KEYBOARD 3
09b26c5e 46
59ae540c 47typedef struct USBMouseState {
59ae540c 48 int dx, dy, dz, buttons_state;
09b26c5e 49 int x, y;
09b26c5e 50 int mouse_grabbed;
455204eb 51 QEMUPutMouseEntry *eh_entry;
59ae540c
FB
52} USBMouseState;
53
47b2d338
AZ
54typedef struct USBKeyboardState {
55 uint16_t modifiers;
56 uint8_t leds;
57 uint8_t key[16];
58 int keys;
59} USBKeyboardState;
60
61typedef struct USBHIDState {
62 USBDevice dev;
63 union {
64 USBMouseState ptr;
65 USBKeyboardState kbd;
66 };
67 int kind;
68 int protocol;
181a29c5 69 uint8_t idle;
68735b6c 70 int64_t next_idle_clock;
117b3ae6 71 int changed;
47e699dc
AZ
72 void *datain_opaque;
73 void (*datain)(void *);
47b2d338
AZ
74} USBHIDState;
75
59ae540c
FB
76/* mostly the same values as the Bochs USB Mouse device */
77static const uint8_t qemu_mouse_dev_descriptor[] = {
78 0x12, /* u8 bLength; */
79 0x01, /* u8 bDescriptorType; Device */
e126cf13 80 0x00, 0x01, /* u16 bcdUSB; v1.0 */
59ae540c
FB
81
82 0x00, /* u8 bDeviceClass; */
83 0x00, /* u8 bDeviceSubClass; */
84 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
85 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
86
87 0x27, 0x06, /* u16 idVendor; */
88 0x01, 0x00, /* u16 idProduct; */
89 0x00, 0x00, /* u16 bcdDevice */
90
91 0x03, /* u8 iManufacturer; */
92 0x02, /* u8 iProduct; */
93 0x01, /* u8 iSerialNumber; */
94 0x01 /* u8 bNumConfigurations; */
95};
96
97static const uint8_t qemu_mouse_config_descriptor[] = {
98 /* one configuration */
99 0x09, /* u8 bLength; */
100 0x02, /* u8 bDescriptorType; Configuration */
101 0x22, 0x00, /* u16 wTotalLength; */
102 0x01, /* u8 bNumInterfaces; (1) */
103 0x01, /* u8 bConfigurationValue; */
104 0x04, /* u8 iConfiguration; */
659139d7 105 0xe0, /* u8 bmAttributes;
59ae540c
FB
106 Bit 7: must be set,
107 6: Self-powered,
108 5: Remote wakeup,
109 4..0: resvd */
110 50, /* u8 MaxPower; */
3b46e624 111
59ae540c
FB
112 /* USB 1.1:
113 * USB 2.0, single TT organization (mandatory):
114 * one interface, protocol 0
115 *
116 * USB 2.0, multiple TT organization (optional):
117 * two interfaces, protocols 1 (like single TT)
118 * and 2 (multiple TT mode) ... config is
119 * sometimes settable
120 * NOT IMPLEMENTED
121 */
122
123 /* one interface */
124 0x09, /* u8 if_bLength; */
125 0x04, /* u8 if_bDescriptorType; Interface */
126 0x00, /* u8 if_bInterfaceNumber; */
127 0x00, /* u8 if_bAlternateSetting; */
128 0x01, /* u8 if_bNumEndpoints; */
129 0x03, /* u8 if_bInterfaceClass; */
130 0x01, /* u8 if_bInterfaceSubClass; */
131 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
47b2d338 132 0x07, /* u8 if_iInterface; */
3b46e624 133
09b26c5e
FB
134 /* HID descriptor */
135 0x09, /* u8 bLength; */
136 0x21, /* u8 bDescriptorType; */
137 0x01, 0x00, /* u16 HID_class */
138 0x00, /* u8 country_code */
139 0x01, /* u8 num_descriptors */
140 0x22, /* u8 type; Report */
c21c583a 141 52, 0, /* u16 len */
09b26c5e 142
59ae540c
FB
143 /* one endpoint (status change endpoint) */
144 0x07, /* u8 ep_bLength; */
145 0x05, /* u8 ep_bDescriptorType; Endpoint */
146 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
147 0x03, /* u8 ep_bmAttributes; Interrupt */
c21c583a 148 0x04, 0x00, /* u16 ep_wMaxPacketSize; */
59ae540c 149 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
09b26c5e
FB
150};
151
152static const uint8_t qemu_tablet_config_descriptor[] = {
153 /* one configuration */
154 0x09, /* u8 bLength; */
155 0x02, /* u8 bDescriptorType; Configuration */
156 0x22, 0x00, /* u16 wTotalLength; */
157 0x01, /* u8 bNumInterfaces; (1) */
158 0x01, /* u8 bConfigurationValue; */
47b2d338 159 0x05, /* u8 iConfiguration; */
5fafdf24 160 0xa0, /* u8 bmAttributes;
09b26c5e
FB
161 Bit 7: must be set,
162 6: Self-powered,
163 5: Remote wakeup,
164 4..0: resvd */
165 50, /* u8 MaxPower; */
3b46e624 166
09b26c5e
FB
167 /* USB 1.1:
168 * USB 2.0, single TT organization (mandatory):
169 * one interface, protocol 0
170 *
171 * USB 2.0, multiple TT organization (optional):
172 * two interfaces, protocols 1 (like single TT)
173 * and 2 (multiple TT mode) ... config is
174 * sometimes settable
175 * NOT IMPLEMENTED
176 */
177
178 /* one interface */
179 0x09, /* u8 if_bLength; */
180 0x04, /* u8 if_bDescriptorType; Interface */
181 0x00, /* u8 if_bInterfaceNumber; */
182 0x00, /* u8 if_bAlternateSetting; */
183 0x01, /* u8 if_bNumEndpoints; */
184 0x03, /* u8 if_bInterfaceClass; */
185 0x01, /* u8 if_bInterfaceSubClass; */
186 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
47b2d338 187 0x07, /* u8 if_iInterface; */
59ae540c
FB
188
189 /* HID descriptor */
190 0x09, /* u8 bLength; */
191 0x21, /* u8 bDescriptorType; */
192 0x01, 0x00, /* u16 HID_class */
193 0x00, /* u8 country_code */
194 0x01, /* u8 num_descriptors */
195 0x22, /* u8 type; Report */
09b26c5e
FB
196 74, 0, /* u16 len */
197
198 /* one endpoint (status change endpoint) */
199 0x07, /* u8 ep_bLength; */
200 0x05, /* u8 ep_bDescriptorType; Endpoint */
201 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
202 0x03, /* u8 ep_bmAttributes; Interrupt */
203 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
f2f1ac82 204 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
59ae540c
FB
205};
206
47b2d338
AZ
207static const uint8_t qemu_keyboard_config_descriptor[] = {
208 /* one configuration */
209 0x09, /* u8 bLength; */
210 USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */
211 0x22, 0x00, /* u16 wTotalLength; */
212 0x01, /* u8 bNumInterfaces; (1) */
213 0x01, /* u8 bConfigurationValue; */
214 0x06, /* u8 iConfiguration; */
5fafdf24 215 0xa0, /* u8 bmAttributes;
47b2d338
AZ
216 Bit 7: must be set,
217 6: Self-powered,
218 5: Remote wakeup,
219 4..0: resvd */
220 0x32, /* u8 MaxPower; */
221
222 /* USB 1.1:
223 * USB 2.0, single TT organization (mandatory):
224 * one interface, protocol 0
225 *
226 * USB 2.0, multiple TT organization (optional):
227 * two interfaces, protocols 1 (like single TT)
228 * and 2 (multiple TT mode) ... config is
229 * sometimes settable
230 * NOT IMPLEMENTED
231 */
232
233 /* one interface */
234 0x09, /* u8 if_bLength; */
235 USB_DT_INTERFACE, /* u8 if_bDescriptorType; Interface */
236 0x00, /* u8 if_bInterfaceNumber; */
237 0x00, /* u8 if_bAlternateSetting; */
238 0x01, /* u8 if_bNumEndpoints; */
239 0x03, /* u8 if_bInterfaceClass; HID */
240 0x01, /* u8 if_bInterfaceSubClass; Boot */
241 0x01, /* u8 if_bInterfaceProtocol; Keyboard */
242 0x07, /* u8 if_iInterface; */
243
244 /* HID descriptor */
245 0x09, /* u8 bLength; */
246 USB_DT_HID, /* u8 bDescriptorType; */
247 0x11, 0x01, /* u16 HID_class */
248 0x00, /* u8 country_code */
249 0x01, /* u8 num_descriptors */
250 USB_DT_REPORT, /* u8 type; Report */
251 0x3f, 0x00, /* u16 len */
252
253 /* one endpoint (status change endpoint) */
254 0x07, /* u8 ep_bLength; */
255 USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; Endpoint */
256 USB_DIR_IN | 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
257 0x03, /* u8 ep_bmAttributes; Interrupt */
258 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
259 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
260};
261
59ae540c 262static const uint8_t qemu_mouse_hid_report_descriptor[] = {
976f8eef
AZ
263 0x05, 0x01, /* Usage Page (Generic Desktop) */
264 0x09, 0x02, /* Usage (Mouse) */
265 0xa1, 0x01, /* Collection (Application) */
266 0x09, 0x01, /* Usage (Pointer) */
267 0xa1, 0x00, /* Collection (Physical) */
268 0x05, 0x09, /* Usage Page (Button) */
269 0x19, 0x01, /* Usage Minimum (1) */
270 0x29, 0x03, /* Usage Maximum (3) */
271 0x15, 0x00, /* Logical Minimum (0) */
272 0x25, 0x01, /* Logical Maximum (1) */
273 0x95, 0x03, /* Report Count (3) */
274 0x75, 0x01, /* Report Size (1) */
275 0x81, 0x02, /* Input (Data, Variable, Absolute) */
276 0x95, 0x01, /* Report Count (1) */
277 0x75, 0x05, /* Report Size (5) */
278 0x81, 0x01, /* Input (Constant) */
279 0x05, 0x01, /* Usage Page (Generic Desktop) */
280 0x09, 0x30, /* Usage (X) */
281 0x09, 0x31, /* Usage (Y) */
282 0x09, 0x38, /* Usage (Wheel) */
283 0x15, 0x81, /* Logical Minimum (-0x7f) */
284 0x25, 0x7f, /* Logical Maximum (0x7f) */
285 0x75, 0x08, /* Report Size (8) */
286 0x95, 0x03, /* Report Count (3) */
287 0x81, 0x06, /* Input (Data, Variable, Relative) */
288 0xc0, /* End Collection */
289 0xc0, /* End Collection */
59ae540c
FB
290};
291
09b26c5e 292static const uint8_t qemu_tablet_hid_report_descriptor[] = {
976f8eef
AZ
293 0x05, 0x01, /* Usage Page (Generic Desktop) */
294 0x09, 0x01, /* Usage (Pointer) */
295 0xa1, 0x01, /* Collection (Application) */
296 0x09, 0x01, /* Usage (Pointer) */
297 0xa1, 0x00, /* Collection (Physical) */
298 0x05, 0x09, /* Usage Page (Button) */
299 0x19, 0x01, /* Usage Minimum (1) */
300 0x29, 0x03, /* Usage Maximum (3) */
301 0x15, 0x00, /* Logical Minimum (0) */
302 0x25, 0x01, /* Logical Maximum (1) */
303 0x95, 0x03, /* Report Count (3) */
304 0x75, 0x01, /* Report Size (1) */
305 0x81, 0x02, /* Input (Data, Variable, Absolute) */
306 0x95, 0x01, /* Report Count (1) */
307 0x75, 0x05, /* Report Size (5) */
308 0x81, 0x01, /* Input (Constant) */
309 0x05, 0x01, /* Usage Page (Generic Desktop) */
310 0x09, 0x30, /* Usage (X) */
311 0x09, 0x31, /* Usage (Y) */
312 0x15, 0x00, /* Logical Minimum (0) */
de5c2d0a 313 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */
976f8eef 314 0x35, 0x00, /* Physical Minimum (0) */
de5c2d0a 315 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */
976f8eef
AZ
316 0x75, 0x10, /* Report Size (16) */
317 0x95, 0x02, /* Report Count (2) */
318 0x81, 0x02, /* Input (Data, Variable, Absolute) */
319 0x05, 0x01, /* Usage Page (Generic Desktop) */
320 0x09, 0x38, /* Usage (Wheel) */
321 0x15, 0x81, /* Logical Minimum (-0x7f) */
322 0x25, 0x7f, /* Logical Maximum (0x7f) */
323 0x35, 0x00, /* Physical Minimum (same as logical) */
324 0x45, 0x00, /* Physical Maximum (same as logical) */
325 0x75, 0x08, /* Report Size (8) */
326 0x95, 0x01, /* Report Count (1) */
327 0x81, 0x06, /* Input (Data, Variable, Relative) */
328 0xc0, /* End Collection */
329 0xc0, /* End Collection */
09b26c5e
FB
330};
331
47b2d338
AZ
332static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
333 0x05, 0x01, /* Usage Page (Generic Desktop) */
334 0x09, 0x06, /* Usage (Keyboard) */
335 0xa1, 0x01, /* Collection (Application) */
336 0x75, 0x01, /* Report Size (1) */
337 0x95, 0x08, /* Report Count (8) */
338 0x05, 0x07, /* Usage Page (Key Codes) */
339 0x19, 0xe0, /* Usage Minimum (224) */
340 0x29, 0xe7, /* Usage Maximum (231) */
341 0x15, 0x00, /* Logical Minimum (0) */
342 0x25, 0x01, /* Logical Maximum (1) */
343 0x81, 0x02, /* Input (Data, Variable, Absolute) */
344 0x95, 0x01, /* Report Count (1) */
345 0x75, 0x08, /* Report Size (8) */
346 0x81, 0x01, /* Input (Constant) */
347 0x95, 0x05, /* Report Count (5) */
348 0x75, 0x01, /* Report Size (1) */
349 0x05, 0x08, /* Usage Page (LEDs) */
350 0x19, 0x01, /* Usage Minimum (1) */
351 0x29, 0x05, /* Usage Maximum (5) */
352 0x91, 0x02, /* Output (Data, Variable, Absolute) */
353 0x95, 0x01, /* Report Count (1) */
354 0x75, 0x03, /* Report Size (3) */
355 0x91, 0x01, /* Output (Constant) */
356 0x95, 0x06, /* Report Count (6) */
357 0x75, 0x08, /* Report Size (8) */
358 0x15, 0x00, /* Logical Minimum (0) */
359 0x25, 0xff, /* Logical Maximum (255) */
360 0x05, 0x07, /* Usage Page (Key Codes) */
361 0x19, 0x00, /* Usage Minimum (0) */
362 0x29, 0xff, /* Usage Maximum (255) */
363 0x81, 0x00, /* Input (Data, Array) */
364 0xc0, /* End Collection */
365};
366
367#define USB_HID_USAGE_ERROR_ROLLOVER 0x01
368#define USB_HID_USAGE_POSTFAIL 0x02
369#define USB_HID_USAGE_ERROR_UNDEFINED 0x03
370
371/* Indices are QEMU keycodes, values are from HID Usage Table. Indices
372 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */
373static const uint8_t usb_hid_usage_keys[0x100] = {
374 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
375 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
376 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
377 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
378 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
379 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
380 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
381 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
382 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
383 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
384 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
385 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
386 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
387 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
390
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
393 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
398 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
400 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
401 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
a8fb7ff3 402 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
47b2d338
AZ
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
407};
408
47e699dc
AZ
409static void usb_hid_changed(USBHIDState *hs)
410{
411 hs->changed = 1;
412
413 if (hs->datain)
414 hs->datain(hs->datain_opaque);
415}
416
59ae540c
FB
417static void usb_mouse_event(void *opaque,
418 int dx1, int dy1, int dz1, int buttons_state)
419{
117b3ae6
PB
420 USBHIDState *hs = opaque;
421 USBMouseState *s = &hs->ptr;
59ae540c
FB
422
423 s->dx += dx1;
424 s->dy += dy1;
425 s->dz += dz1;
426 s->buttons_state = buttons_state;
47e699dc
AZ
427
428 usb_hid_changed(hs);
59ae540c
FB
429}
430
09b26c5e
FB
431static void usb_tablet_event(void *opaque,
432 int x, int y, int dz, int buttons_state)
433{
117b3ae6
PB
434 USBHIDState *hs = opaque;
435 USBMouseState *s = &hs->ptr;
09b26c5e
FB
436
437 s->x = x;
438 s->y = y;
439 s->dz += dz;
440 s->buttons_state = buttons_state;
47e699dc
AZ
441
442 usb_hid_changed(hs);
09b26c5e
FB
443}
444
47b2d338
AZ
445static void usb_keyboard_event(void *opaque, int keycode)
446{
117b3ae6
PB
447 USBHIDState *hs = opaque;
448 USBKeyboardState *s = &hs->kbd;
47b2d338
AZ
449 uint8_t hid_code, key;
450 int i;
451
452 key = keycode & 0x7f;
453 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
454 s->modifiers &= ~(1 << 8);
455
456 switch (hid_code) {
457 case 0x00:
458 return;
459
460 case 0xe0:
461 if (s->modifiers & (1 << 9)) {
462 s->modifiers ^= 3 << 8;
463 return;
464 }
465 case 0xe1 ... 0xe7:
466 if (keycode & (1 << 7)) {
467 s->modifiers &= ~(1 << (hid_code & 0x0f));
468 return;
469 }
470 case 0xe8 ... 0xef:
471 s->modifiers |= 1 << (hid_code & 0x0f);
472 return;
473 }
474
475 if (keycode & (1 << 7)) {
476 for (i = s->keys - 1; i >= 0; i --)
477 if (s->key[i] == hid_code) {
478 s->key[i] = s->key[-- s->keys];
479 s->key[s->keys] = 0x00;
47e699dc
AZ
480 usb_hid_changed(hs);
481 break;
47b2d338 482 }
47e699dc
AZ
483 if (i < 0)
484 return;
47b2d338
AZ
485 } else {
486 for (i = s->keys - 1; i >= 0; i --)
487 if (s->key[i] == hid_code)
47e699dc
AZ
488 break;
489 if (i < 0) {
490 if (s->keys < sizeof(s->key))
491 s->key[s->keys ++] = hid_code;
492 } else
493 return;
47b2d338 494 }
47e699dc
AZ
495
496 usb_hid_changed(hs);
47b2d338
AZ
497}
498
59ae540c
FB
499static inline int int_clamp(int val, int vmin, int vmax)
500{
501 if (val < vmin)
502 return vmin;
503 else if (val > vmax)
504 return vmax;
505 else
506 return val;
507}
508
117b3ae6 509static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
59ae540c
FB
510{
511 int dx, dy, dz, b, l;
117b3ae6 512 USBMouseState *s = &hs->ptr;
59ae540c 513
09b26c5e 514 if (!s->mouse_grabbed) {
6fef28ee 515 qemu_activate_mouse_event_handler(s->eh_entry);
09b26c5e
FB
516 s->mouse_grabbed = 1;
517 }
3b46e624 518
976f8eef
AZ
519 dx = int_clamp(s->dx, -127, 127);
520 dy = int_clamp(s->dy, -127, 127);
521 dz = int_clamp(s->dz, -127, 127);
59ae540c
FB
522
523 s->dx -= dx;
524 s->dy -= dy;
525 s->dz -= dz;
3b46e624 526
976f8eef
AZ
527 /* Appears we have to invert the wheel direction */
528 dz = 0 - dz;
529
59ae540c
FB
530 b = 0;
531 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
532 b |= 0x01;
533 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
534 b |= 0x02;
535 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
536 b |= 0x04;
3b46e624 537
c21c583a
AZ
538 l = 0;
539 if (len > l)
540 buf[l ++] = b;
541 if (len > l)
542 buf[l ++] = dx;
543 if (len > l)
544 buf[l ++] = dy;
545 if (len > l)
546 buf[l ++] = dz;
59ae540c
FB
547 return l;
548}
549
117b3ae6 550static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
09b26c5e
FB
551{
552 int dz, b, l;
117b3ae6 553 USBMouseState *s = &hs->ptr;
09b26c5e
FB
554
555 if (!s->mouse_grabbed) {
6fef28ee 556 qemu_activate_mouse_event_handler(s->eh_entry);
09b26c5e
FB
557 s->mouse_grabbed = 1;
558 }
3b46e624 559
976f8eef 560 dz = int_clamp(s->dz, -127, 127);
09b26c5e
FB
561 s->dz -= dz;
562
563 /* Appears we have to invert the wheel direction */
564 dz = 0 - dz;
565 b = 0;
566 if (s->buttons_state & MOUSE_EVENT_LBUTTON)
567 b |= 0x01;
568 if (s->buttons_state & MOUSE_EVENT_RBUTTON)
569 b |= 0x02;
570 if (s->buttons_state & MOUSE_EVENT_MBUTTON)
571 b |= 0x04;
572
573 buf[0] = b;
574 buf[1] = s->x & 0xff;
575 buf[2] = s->x >> 8;
576 buf[3] = s->y & 0xff;
577 buf[4] = s->y >> 8;
578 buf[5] = dz;
579 l = 6;
580
581 return l;
582}
583
47b2d338
AZ
584static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
585{
586 if (len < 2)
587 return 0;
588
589 buf[0] = s->modifiers & 0xff;
590 buf[1] = 0;
591 if (s->keys > 6)
592 memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
593 else
594 memcpy(buf + 2, s->key, MIN(8, len) - 2);
595
596 return MIN(8, len);
597}
598
599static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
600{
601 if (len > 0) {
bd87813e 602 int ledstate = 0;
47b2d338
AZ
603 /* 0x01: Num Lock LED
604 * 0x02: Caps Lock LED
605 * 0x04: Scroll Lock LED
606 * 0x08: Compose LED
607 * 0x10: Kana LED */
608 s->leds = buf[0];
bd87813e
GH
609 if (s->leds & 0x04)
610 ledstate |= QEMU_SCROLL_LOCK_LED;
611 if (s->leds & 0x01)
612 ledstate |= QEMU_NUM_LOCK_LED;
613 if (s->leds & 0x02)
614 ledstate |= QEMU_CAPS_LOCK_LED;
615 kbd_put_ledstate(ledstate);
47b2d338
AZ
616 }
617 return 0;
618}
619
059809e4 620static void usb_mouse_handle_reset(USBDevice *dev)
59ae540c 621{
47b2d338
AZ
622 USBHIDState *s = (USBHIDState *)dev;
623
624 s->ptr.dx = 0;
625 s->ptr.dy = 0;
626 s->ptr.dz = 0;
627 s->ptr.x = 0;
628 s->ptr.y = 0;
629 s->ptr.buttons_state = 0;
630 s->protocol = 1;
631}
632
633static void usb_keyboard_handle_reset(USBDevice *dev)
634{
635 USBHIDState *s = (USBHIDState *)dev;
636
926acf8f 637 qemu_add_kbd_event_handler(usb_keyboard_event, s);
47b2d338 638 s->protocol = 1;
59ae540c
FB
639}
640
68735b6c
KC
641static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
642{
643 s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
644}
645
47b2d338 646static int usb_hid_handle_control(USBDevice *dev, int request, int value,
59ae540c
FB
647 int index, int length, uint8_t *data)
648{
47b2d338 649 USBHIDState *s = (USBHIDState *)dev;
09b26c5e 650 int ret = 0;
59ae540c
FB
651
652 switch(request) {
653 case DeviceRequest | USB_REQ_GET_STATUS:
654 data[0] = (1 << USB_DEVICE_SELF_POWERED) |
655 (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
656 data[1] = 0x00;
657 ret = 2;
658 break;
659 case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
660 if (value == USB_DEVICE_REMOTE_WAKEUP) {
661 dev->remote_wakeup = 0;
662 } else {
663 goto fail;
664 }
665 ret = 0;
666 break;
667 case DeviceOutRequest | USB_REQ_SET_FEATURE:
668 if (value == USB_DEVICE_REMOTE_WAKEUP) {
669 dev->remote_wakeup = 1;
670 } else {
671 goto fail;
672 }
673 ret = 0;
674 break;
675 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
676 dev->addr = value;
677 ret = 0;
678 break;
679 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
680 switch(value >> 8) {
681 case USB_DT_DEVICE:
5fafdf24 682 memcpy(data, qemu_mouse_dev_descriptor,
59ae540c
FB
683 sizeof(qemu_mouse_dev_descriptor));
684 ret = sizeof(qemu_mouse_dev_descriptor);
685 break;
686 case USB_DT_CONFIG:
09b26c5e 687 if (s->kind == USB_MOUSE) {
5fafdf24 688 memcpy(data, qemu_mouse_config_descriptor,
09b26c5e
FB
689 sizeof(qemu_mouse_config_descriptor));
690 ret = sizeof(qemu_mouse_config_descriptor);
691 } else if (s->kind == USB_TABLET) {
5fafdf24 692 memcpy(data, qemu_tablet_config_descriptor,
09b26c5e
FB
693 sizeof(qemu_tablet_config_descriptor));
694 ret = sizeof(qemu_tablet_config_descriptor);
47b2d338 695 } else if (s->kind == USB_KEYBOARD) {
5fafdf24 696 memcpy(data, qemu_keyboard_config_descriptor,
47b2d338
AZ
697 sizeof(qemu_keyboard_config_descriptor));
698 ret = sizeof(qemu_keyboard_config_descriptor);
699 }
59ae540c
FB
700 break;
701 case USB_DT_STRING:
702 switch(value & 0xff) {
703 case 0:
704 /* language ids */
705 data[0] = 4;
706 data[1] = 3;
707 data[2] = 0x09;
708 data[3] = 0x04;
709 ret = 4;
710 break;
711 case 1:
712 /* serial number */
713 ret = set_usb_string(data, "1");
714 break;
715 case 2:
716 /* product description */
0fe6d12e 717 ret = set_usb_string(data, s->dev.product_desc);
59ae540c
FB
718 break;
719 case 3:
720 /* vendor description */
721 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
722 break;
723 case 4:
724 ret = set_usb_string(data, "HID Mouse");
725 break;
726 case 5:
47b2d338
AZ
727 ret = set_usb_string(data, "HID Tablet");
728 break;
729 case 6:
730 ret = set_usb_string(data, "HID Keyboard");
731 break;
732 case 7:
59ae540c
FB
733 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
734 break;
735 default:
736 goto fail;
737 }
738 break;
739 default:
740 goto fail;
741 }
742 break;
743 case DeviceRequest | USB_REQ_GET_CONFIGURATION:
744 data[0] = 1;
745 ret = 1;
746 break;
747 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
748 ret = 0;
749 break;
750 case DeviceRequest | USB_REQ_GET_INTERFACE:
751 data[0] = 0;
752 ret = 1;
753 break;
754 case DeviceOutRequest | USB_REQ_SET_INTERFACE:
755 ret = 0;
756 break;
757 /* hid specific requests */
758 case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
759 switch(value >> 8) {
760 case 0x22:
09b26c5e 761 if (s->kind == USB_MOUSE) {
5fafdf24 762 memcpy(data, qemu_mouse_hid_report_descriptor,
09b26c5e
FB
763 sizeof(qemu_mouse_hid_report_descriptor));
764 ret = sizeof(qemu_mouse_hid_report_descriptor);
765 } else if (s->kind == USB_TABLET) {
5fafdf24 766 memcpy(data, qemu_tablet_hid_report_descriptor,
09b26c5e
FB
767 sizeof(qemu_tablet_hid_report_descriptor));
768 ret = sizeof(qemu_tablet_hid_report_descriptor);
47b2d338 769 } else if (s->kind == USB_KEYBOARD) {
5fafdf24 770 memcpy(data, qemu_keyboard_hid_report_descriptor,
47b2d338
AZ
771 sizeof(qemu_keyboard_hid_report_descriptor));
772 ret = sizeof(qemu_keyboard_hid_report_descriptor);
773 }
774 break;
59ae540c
FB
775 default:
776 goto fail;
777 }
778 break;
779 case GET_REPORT:
09b26c5e 780 if (s->kind == USB_MOUSE)
117b3ae6 781 ret = usb_mouse_poll(s, data, length);
09b26c5e 782 else if (s->kind == USB_TABLET)
117b3ae6 783 ret = usb_tablet_poll(s, data, length);
47b2d338
AZ
784 else if (s->kind == USB_KEYBOARD)
785 ret = usb_keyboard_poll(&s->kbd, data, length);
786 break;
787 case SET_REPORT:
788 if (s->kind == USB_KEYBOARD)
789 ret = usb_keyboard_write(&s->kbd, data, length);
790 else
791 goto fail;
792 break;
793 case GET_PROTOCOL:
794 if (s->kind != USB_KEYBOARD)
795 goto fail;
796 ret = 1;
797 data[0] = s->protocol;
798 break;
799 case SET_PROTOCOL:
800 if (s->kind != USB_KEYBOARD)
801 goto fail;
802 ret = 0;
803 s->protocol = value;
804 break;
805 case GET_IDLE:
806 ret = 1;
807 data[0] = s->idle;
59ae540c
FB
808 break;
809 case SET_IDLE:
181a29c5 810 s->idle = (uint8_t) (value >> 8);
68735b6c 811 usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
59ae540c
FB
812 ret = 0;
813 break;
814 default:
815 fail:
816 ret = USB_RET_STALL;
817 break;
818 }
819 return ret;
820}
821
47b2d338 822static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
59ae540c 823{
47b2d338 824 USBHIDState *s = (USBHIDState *)dev;
09b26c5e 825 int ret = 0;
59ae540c 826
4d611c9a 827 switch(p->pid) {
59ae540c 828 case USB_TOKEN_IN:
4d611c9a 829 if (p->devep == 1) {
68735b6c
KC
830 int64_t curtime = qemu_get_clock(vm_clock);
831 if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
117b3ae6 832 return USB_RET_NAK;
68735b6c 833 usb_hid_set_next_idle(s, curtime);
117b3ae6 834 s->changed = 0;
47b2d338 835 if (s->kind == USB_MOUSE)
117b3ae6 836 ret = usb_mouse_poll(s, p->data, p->len);
47b2d338 837 else if (s->kind == USB_TABLET)
117b3ae6 838 ret = usb_tablet_poll(s, p->data, p->len);
47b2d338
AZ
839 else if (s->kind == USB_KEYBOARD)
840 ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
59ae540c
FB
841 } else {
842 goto fail;
843 }
844 break;
845 case USB_TOKEN_OUT:
846 default:
847 fail:
848 ret = USB_RET_STALL;
849 break;
850 }
851 return ret;
852}
853
47b2d338 854static void usb_hid_handle_destroy(USBDevice *dev)
059809e4 855{
47b2d338 856 USBHIDState *s = (USBHIDState *)dev;
059809e4 857
46aaebff
JS
858 switch(s->kind) {
859 case USB_KEYBOARD:
860 qemu_remove_kbd_event_handler();
861 break;
862 default:
47b2d338 863 qemu_remove_mouse_event_handler(s->ptr.eh_entry);
46aaebff 864 }
059809e4
FB
865}
866
806b6024 867static int usb_hid_initfn(USBDevice *dev, int kind)
09b26c5e 868{
806b6024 869 USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
09b26c5e 870 s->dev.speed = USB_SPEED_FULL;
806b6024 871 s->kind = kind;
6fef28ee
AL
872
873 if (s->kind == USB_MOUSE) {
874 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
875 0, "QEMU USB Mouse");
876 } else if (s->kind == USB_TABLET) {
877 s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
878 1, "QEMU USB Tablet");
879 }
880
117b3ae6
PB
881 /* Force poll routine to be run and grab input the first time. */
882 s->changed = 1;
806b6024 883 return 0;
09b26c5e
FB
884}
885
806b6024 886static int usb_tablet_initfn(USBDevice *dev)
59ae540c 887{
806b6024
GH
888 return usb_hid_initfn(dev, USB_TABLET);
889}
59ae540c 890
806b6024
GH
891static int usb_mouse_initfn(USBDevice *dev)
892{
893 return usb_hid_initfn(dev, USB_MOUSE);
894}
59ae540c 895
806b6024
GH
896static int usb_keyboard_initfn(USBDevice *dev)
897{
898 return usb_hid_initfn(dev, USB_KEYBOARD);
899}
59ae540c 900
47e699dc
AZ
901void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
902{
903 USBHIDState *s = (USBHIDState *)dev;
904
905 s->datain_opaque = opaque;
906 s->datain = datain;
907}
806b6024
GH
908
909static struct USBDeviceInfo hid_info[] = {
910 {
06384698 911 .product_desc = "QEMU USB Tablet",
556cd098 912 .qdev.name = "usb-tablet",
fa7c70c3 913 .usbdevice_name = "tablet",
806b6024
GH
914 .qdev.size = sizeof(USBHIDState),
915 .init = usb_tablet_initfn,
916 .handle_packet = usb_generic_handle_packet,
917 .handle_reset = usb_mouse_handle_reset,
918 .handle_control = usb_hid_handle_control,
919 .handle_data = usb_hid_handle_data,
920 .handle_destroy = usb_hid_handle_destroy,
921 },{
06384698 922 .product_desc = "QEMU USB Mouse",
556cd098 923 .qdev.name = "usb-mouse",
fa7c70c3 924 .usbdevice_name = "mouse",
806b6024
GH
925 .qdev.size = sizeof(USBHIDState),
926 .init = usb_mouse_initfn,
927 .handle_packet = usb_generic_handle_packet,
928 .handle_reset = usb_mouse_handle_reset,
929 .handle_control = usb_hid_handle_control,
930 .handle_data = usb_hid_handle_data,
931 .handle_destroy = usb_hid_handle_destroy,
932 },{
06384698 933 .product_desc = "QEMU USB Keyboard",
556cd098 934 .qdev.name = "usb-kbd",
fa7c70c3 935 .usbdevice_name = "keyboard",
806b6024
GH
936 .qdev.size = sizeof(USBHIDState),
937 .init = usb_keyboard_initfn,
938 .handle_packet = usb_generic_handle_packet,
939 .handle_reset = usb_keyboard_handle_reset,
940 .handle_control = usb_hid_handle_control,
941 .handle_data = usb_hid_handle_data,
942 .handle_destroy = usb_hid_handle_destroy,
943 },{
944 /* end of list */
945 }
946};
947
948static void usb_hid_register_devices(void)
949{
950 usb_qdev_register_many(hid_info);
951}
952device_init(usb_hid_register_devices)