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