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