]> Git Repo - qemu.git/blob - hw/usb-hid.c
usb: move USB_REQ_{GET,SET}_CONFIGURATION handling to common code
[qemu.git] / hw / usb-hid.c
1 /*
2  * QEMU USB HID devices
3  *
4  * Copyright (c) 2005 Fabrice Bellard
5  * Copyright (c) 2007 OpenMoko, Inc.  ([email protected])
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 #include "hw.h"
26 #include "console.h"
27 #include "usb.h"
28 #include "usb-desc.h"
29 #include "sysemu.h"
30
31 /* HID interface requests */
32 #define GET_REPORT   0xa101
33 #define GET_IDLE     0xa102
34 #define GET_PROTOCOL 0xa103
35 #define SET_REPORT   0x2109
36 #define SET_IDLE     0x210a
37 #define SET_PROTOCOL 0x210b
38
39 /* HID descriptor types */
40 #define USB_DT_HID    0x21
41 #define USB_DT_REPORT 0x22
42 #define USB_DT_PHY    0x23
43
44 #define USB_MOUSE     1
45 #define USB_TABLET    2
46 #define USB_KEYBOARD  3
47
48 typedef struct USBMouseState {
49     int dx, dy, dz, buttons_state;
50     int x, y;
51     int mouse_grabbed;
52     QEMUPutMouseEntry *eh_entry;
53 } USBMouseState;
54
55 typedef struct USBKeyboardState {
56     uint16_t modifiers;
57     uint8_t leds;
58     uint8_t key[16];
59     int keys;
60 } USBKeyboardState;
61
62 typedef struct USBHIDState {
63     USBDevice dev;
64     union {
65         USBMouseState ptr;
66         USBKeyboardState kbd;
67     };
68     int kind;
69     int protocol;
70     uint8_t idle;
71     int64_t next_idle_clock;
72     int changed;
73     void *datain_opaque;
74     void (*datain)(void *);
75 } USBHIDState;
76
77 enum {
78     STR_MANUFACTURER = 1,
79     STR_PRODUCT_MOUSE,
80     STR_PRODUCT_TABLET,
81     STR_PRODUCT_KEYBOARD,
82     STR_SERIALNUMBER,
83     STR_CONFIG_MOUSE,
84     STR_CONFIG_TABLET,
85     STR_CONFIG_KEYBOARD,
86 };
87
88 static const USBDescStrings desc_strings = {
89     [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
90     [STR_PRODUCT_MOUSE]    = "QEMU USB Mouse",
91     [STR_PRODUCT_TABLET]   = "QEMU USB Tablet",
92     [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
93     [STR_SERIALNUMBER]     = "1",
94     [STR_CONFIG_MOUSE]     = "HID Mouse",
95     [STR_CONFIG_TABLET]    = "HID Tablet",
96     [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
97 };
98
99 static const USBDescIface desc_iface_mouse = {
100     .bInterfaceNumber              = 0,
101     .bNumEndpoints                 = 1,
102     .bInterfaceClass               = USB_CLASS_HID,
103     .bInterfaceSubClass            = 0x01, /* boot */
104     .bInterfaceProtocol            = 0x02,
105     .ndesc                         = 1,
106     .descs = (USBDescOther[]) {
107         {
108             /* HID descriptor */
109             .data = (uint8_t[]) {
110                 0x09,          /*  u8  bLength */
111                 USB_DT_HID,    /*  u8  bDescriptorType */
112                 0x01, 0x00,    /*  u16 HID_class */
113                 0x00,          /*  u8  country_code */
114                 0x01,          /*  u8  num_descriptors */
115                 USB_DT_REPORT, /*  u8  type: Report */
116                 52, 0,         /*  u16 len */
117             },
118         },
119     },
120     .eps = (USBDescEndpoint[]) {
121         {
122             .bEndpointAddress      = USB_DIR_IN | 0x01,
123             .bmAttributes          = USB_ENDPOINT_XFER_INT,
124             .wMaxPacketSize        = 4,
125             .bInterval             = 0x0a,
126         },
127     },
128 };
129
130 static const USBDescIface desc_iface_tablet = {
131     .bInterfaceNumber              = 0,
132     .bNumEndpoints                 = 1,
133     .bInterfaceClass               = USB_CLASS_HID,
134     .bInterfaceSubClass            = 0x01, /* boot */
135     .bInterfaceProtocol            = 0x02,
136     .ndesc                         = 1,
137     .descs = (USBDescOther[]) {
138         {
139             /* HID descriptor */
140             .data = (uint8_t[]) {
141                 0x09,          /*  u8  bLength */
142                 USB_DT_HID,    /*  u8  bDescriptorType */
143                 0x01, 0x00,    /*  u16 HID_class */
144                 0x00,          /*  u8  country_code */
145                 0x01,          /*  u8  num_descriptors */
146                 USB_DT_REPORT, /*  u8  type: Report */
147                 74, 0,         /*  u16 len */
148             },
149         },
150     },
151     .eps = (USBDescEndpoint[]) {
152         {
153             .bEndpointAddress      = USB_DIR_IN | 0x01,
154             .bmAttributes          = USB_ENDPOINT_XFER_INT,
155             .wMaxPacketSize        = 8,
156             .bInterval             = 0x0a,
157         },
158     },
159 };
160
161 static const USBDescIface desc_iface_keyboard = {
162     .bInterfaceNumber              = 0,
163     .bNumEndpoints                 = 1,
164     .bInterfaceClass               = USB_CLASS_HID,
165     .bInterfaceSubClass            = 0x01, /* boot */
166     .bInterfaceProtocol            = 0x01, /* keyboard */
167     .ndesc                         = 1,
168     .descs = (USBDescOther[]) {
169         {
170             /* HID descriptor */
171             .data = (uint8_t[]) {
172                 0x09,          /*  u8  bLength */
173                 USB_DT_HID,    /*  u8  bDescriptorType */
174                 0x11, 0x01,    /*  u16 HID_class */
175                 0x00,          /*  u8  country_code */
176                 0x01,          /*  u8  num_descriptors */
177                 USB_DT_REPORT, /*  u8  type: Report */
178                 0x3f, 0,       /*  u16 len */
179             },
180         },
181     },
182     .eps = (USBDescEndpoint[]) {
183         {
184             .bEndpointAddress      = USB_DIR_IN | 0x01,
185             .bmAttributes          = USB_ENDPOINT_XFER_INT,
186             .wMaxPacketSize        = 8,
187             .bInterval             = 0x0a,
188         },
189     },
190 };
191
192 static const USBDescDevice desc_device_mouse = {
193     .bcdUSB                        = 0x0100,
194     .bMaxPacketSize0               = 8,
195     .bNumConfigurations            = 1,
196     .confs = (USBDescConfig[]) {
197         {
198             .bNumInterfaces        = 1,
199             .bConfigurationValue   = 1,
200             .iConfiguration        = STR_CONFIG_MOUSE,
201             .bmAttributes          = 0xa0,
202             .bMaxPower             = 50,
203             .ifs = &desc_iface_mouse,
204         },
205     },
206 };
207
208 static const USBDescDevice desc_device_tablet = {
209     .bcdUSB                        = 0x0100,
210     .bMaxPacketSize0               = 8,
211     .bNumConfigurations            = 1,
212     .confs = (USBDescConfig[]) {
213         {
214             .bNumInterfaces        = 1,
215             .bConfigurationValue   = 1,
216             .iConfiguration        = STR_CONFIG_TABLET,
217             .bmAttributes          = 0xa0,
218             .bMaxPower             = 50,
219             .ifs = &desc_iface_tablet,
220         },
221     },
222 };
223
224 static const USBDescDevice desc_device_keyboard = {
225     .bcdUSB                        = 0x0100,
226     .bMaxPacketSize0               = 8,
227     .bNumConfigurations            = 1,
228     .confs = (USBDescConfig[]) {
229         {
230             .bNumInterfaces        = 1,
231             .bConfigurationValue   = 1,
232             .iConfiguration        = STR_CONFIG_KEYBOARD,
233             .bmAttributes          = 0xa0,
234             .bMaxPower             = 50,
235             .ifs = &desc_iface_keyboard,
236         },
237     },
238 };
239
240 static const USBDesc desc_mouse = {
241     .id = {
242         .idVendor          = 0x0627,
243         .idProduct         = 0x0001,
244         .bcdDevice         = 0,
245         .iManufacturer     = STR_MANUFACTURER,
246         .iProduct          = STR_PRODUCT_MOUSE,
247         .iSerialNumber     = STR_SERIALNUMBER,
248     },
249     .full = &desc_device_mouse,
250     .str  = desc_strings,
251 };
252
253 static const USBDesc desc_tablet = {
254     .id = {
255         .idVendor          = 0x0627,
256         .idProduct         = 0x0001,
257         .bcdDevice         = 0,
258         .iManufacturer     = STR_MANUFACTURER,
259         .iProduct          = STR_PRODUCT_TABLET,
260         .iSerialNumber     = STR_SERIALNUMBER,
261     },
262     .full = &desc_device_tablet,
263     .str  = desc_strings,
264 };
265
266 static const USBDesc desc_keyboard = {
267     .id = {
268         .idVendor          = 0x0627,
269         .idProduct         = 0x0001,
270         .bcdDevice         = 0,
271         .iManufacturer     = STR_MANUFACTURER,
272         .iProduct          = STR_PRODUCT_KEYBOARD,
273         .iSerialNumber     = STR_SERIALNUMBER,
274     },
275     .full = &desc_device_keyboard,
276     .str  = desc_strings,
277 };
278
279 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
280     0x05, 0x01,         /* Usage Page (Generic Desktop) */
281     0x09, 0x02,         /* Usage (Mouse) */
282     0xa1, 0x01,         /* Collection (Application) */
283     0x09, 0x01,         /*   Usage (Pointer) */
284     0xa1, 0x00,         /*   Collection (Physical) */
285     0x05, 0x09,         /*     Usage Page (Button) */
286     0x19, 0x01,         /*     Usage Minimum (1) */
287     0x29, 0x03,         /*     Usage Maximum (3) */
288     0x15, 0x00,         /*     Logical Minimum (0) */
289     0x25, 0x01,         /*     Logical Maximum (1) */
290     0x95, 0x03,         /*     Report Count (3) */
291     0x75, 0x01,         /*     Report Size (1) */
292     0x81, 0x02,         /*     Input (Data, Variable, Absolute) */
293     0x95, 0x01,         /*     Report Count (1) */
294     0x75, 0x05,         /*     Report Size (5) */
295     0x81, 0x01,         /*     Input (Constant) */
296     0x05, 0x01,         /*     Usage Page (Generic Desktop) */
297     0x09, 0x30,         /*     Usage (X) */
298     0x09, 0x31,         /*     Usage (Y) */
299     0x09, 0x38,         /*     Usage (Wheel) */
300     0x15, 0x81,         /*     Logical Minimum (-0x7f) */
301     0x25, 0x7f,         /*     Logical Maximum (0x7f) */
302     0x75, 0x08,         /*     Report Size (8) */
303     0x95, 0x03,         /*     Report Count (3) */
304     0x81, 0x06,         /*     Input (Data, Variable, Relative) */
305     0xc0,               /*   End Collection */
306     0xc0,               /* End Collection */
307 };
308
309 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
310     0x05, 0x01,         /* Usage Page (Generic Desktop) */
311     0x09, 0x01,         /* Usage (Pointer) */
312     0xa1, 0x01,         /* Collection (Application) */
313     0x09, 0x01,         /*   Usage (Pointer) */
314     0xa1, 0x00,         /*   Collection (Physical) */
315     0x05, 0x09,         /*     Usage Page (Button) */
316     0x19, 0x01,         /*     Usage Minimum (1) */
317     0x29, 0x03,         /*     Usage Maximum (3) */
318     0x15, 0x00,         /*     Logical Minimum (0) */
319     0x25, 0x01,         /*     Logical Maximum (1) */
320     0x95, 0x03,         /*     Report Count (3) */
321     0x75, 0x01,         /*     Report Size (1) */
322     0x81, 0x02,         /*     Input (Data, Variable, Absolute) */
323     0x95, 0x01,         /*     Report Count (1) */
324     0x75, 0x05,         /*     Report Size (5) */
325     0x81, 0x01,         /*     Input (Constant) */
326     0x05, 0x01,         /*     Usage Page (Generic Desktop) */
327     0x09, 0x30,         /*     Usage (X) */
328     0x09, 0x31,         /*     Usage (Y) */
329     0x15, 0x00,         /*     Logical Minimum (0) */
330     0x26, 0xff, 0x7f,   /*     Logical Maximum (0x7fff) */
331     0x35, 0x00,         /*     Physical Minimum (0) */
332     0x46, 0xff, 0x7f,   /*     Physical Maximum (0x7fff) */
333     0x75, 0x10,         /*     Report Size (16) */
334     0x95, 0x02,         /*     Report Count (2) */
335     0x81, 0x02,         /*     Input (Data, Variable, Absolute) */
336     0x05, 0x01,         /*     Usage Page (Generic Desktop) */
337     0x09, 0x38,         /*     Usage (Wheel) */
338     0x15, 0x81,         /*     Logical Minimum (-0x7f) */
339     0x25, 0x7f,         /*     Logical Maximum (0x7f) */
340     0x35, 0x00,         /*     Physical Minimum (same as logical) */
341     0x45, 0x00,         /*     Physical Maximum (same as logical) */
342     0x75, 0x08,         /*     Report Size (8) */
343     0x95, 0x01,         /*     Report Count (1) */
344     0x81, 0x06,         /*     Input (Data, Variable, Relative) */
345     0xc0,               /*   End Collection */
346     0xc0,               /* End Collection */
347 };
348
349 static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
350     0x05, 0x01,         /* Usage Page (Generic Desktop) */
351     0x09, 0x06,         /* Usage (Keyboard) */
352     0xa1, 0x01,         /* Collection (Application) */
353     0x75, 0x01,         /*   Report Size (1) */
354     0x95, 0x08,         /*   Report Count (8) */
355     0x05, 0x07,         /*   Usage Page (Key Codes) */
356     0x19, 0xe0,         /*   Usage Minimum (224) */
357     0x29, 0xe7,         /*   Usage Maximum (231) */
358     0x15, 0x00,         /*   Logical Minimum (0) */
359     0x25, 0x01,         /*   Logical Maximum (1) */
360     0x81, 0x02,         /*   Input (Data, Variable, Absolute) */
361     0x95, 0x01,         /*   Report Count (1) */
362     0x75, 0x08,         /*   Report Size (8) */
363     0x81, 0x01,         /*   Input (Constant) */
364     0x95, 0x05,         /*   Report Count (5) */
365     0x75, 0x01,         /*   Report Size (1) */
366     0x05, 0x08,         /*   Usage Page (LEDs) */
367     0x19, 0x01,         /*   Usage Minimum (1) */
368     0x29, 0x05,         /*   Usage Maximum (5) */
369     0x91, 0x02,         /*   Output (Data, Variable, Absolute) */
370     0x95, 0x01,         /*   Report Count (1) */
371     0x75, 0x03,         /*   Report Size (3) */
372     0x91, 0x01,         /*   Output (Constant) */
373     0x95, 0x06,         /*   Report Count (6) */
374     0x75, 0x08,         /*   Report Size (8) */
375     0x15, 0x00,         /*   Logical Minimum (0) */
376     0x25, 0xff,         /*   Logical Maximum (255) */
377     0x05, 0x07,         /*   Usage Page (Key Codes) */
378     0x19, 0x00,         /*   Usage Minimum (0) */
379     0x29, 0xff,         /*   Usage Maximum (255) */
380     0x81, 0x00,         /*   Input (Data, Array) */
381     0xc0,               /* End Collection */
382 };
383
384 #define USB_HID_USAGE_ERROR_ROLLOVER    0x01
385 #define USB_HID_USAGE_POSTFAIL          0x02
386 #define USB_HID_USAGE_ERROR_UNDEFINED   0x03
387
388 /* Indices are QEMU keycodes, values are from HID Usage Table.  Indices
389  * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d.  */
390 static const uint8_t usb_hid_usage_keys[0x100] = {
391     0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
392     0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
393     0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
394     0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
395     0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
396     0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
397     0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
398     0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
399     0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
400     0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
401     0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
402     0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
403     0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
404     0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
405     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
406     0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
407
408     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411     0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
412     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414     0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
415     0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
416     0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
417     0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
418     0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
419     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
421     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
422     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 };
425
426 static void usb_hid_changed(USBHIDState *hs)
427 {
428     hs->changed = 1;
429
430     if (hs->datain)
431         hs->datain(hs->datain_opaque);
432 }
433
434 static void usb_mouse_event(void *opaque,
435                             int dx1, int dy1, int dz1, int buttons_state)
436 {
437     USBHIDState *hs = opaque;
438     USBMouseState *s = &hs->ptr;
439
440     s->dx += dx1;
441     s->dy += dy1;
442     s->dz += dz1;
443     s->buttons_state = buttons_state;
444
445     usb_hid_changed(hs);
446 }
447
448 static void usb_tablet_event(void *opaque,
449                              int x, int y, int dz, int buttons_state)
450 {
451     USBHIDState *hs = opaque;
452     USBMouseState *s = &hs->ptr;
453
454     s->x = x;
455     s->y = y;
456     s->dz += dz;
457     s->buttons_state = buttons_state;
458
459     usb_hid_changed(hs);
460 }
461
462 static void usb_keyboard_event(void *opaque, int keycode)
463 {
464     USBHIDState *hs = opaque;
465     USBKeyboardState *s = &hs->kbd;
466     uint8_t hid_code, key;
467     int i;
468
469     key = keycode & 0x7f;
470     hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
471     s->modifiers &= ~(1 << 8);
472
473     switch (hid_code) {
474     case 0x00:
475         return;
476
477     case 0xe0:
478         if (s->modifiers & (1 << 9)) {
479             s->modifiers ^= 3 << 8;
480             return;
481         }
482     case 0xe1 ... 0xe7:
483         if (keycode & (1 << 7)) {
484             s->modifiers &= ~(1 << (hid_code & 0x0f));
485             return;
486         }
487     case 0xe8 ... 0xef:
488         s->modifiers |= 1 << (hid_code & 0x0f);
489         return;
490     }
491
492     if (keycode & (1 << 7)) {
493         for (i = s->keys - 1; i >= 0; i --)
494             if (s->key[i] == hid_code) {
495                 s->key[i] = s->key[-- s->keys];
496                 s->key[s->keys] = 0x00;
497                 usb_hid_changed(hs);
498                 break;
499             }
500         if (i < 0)
501             return;
502     } else {
503         for (i = s->keys - 1; i >= 0; i --)
504             if (s->key[i] == hid_code)
505                 break;
506         if (i < 0) {
507             if (s->keys < sizeof(s->key))
508                 s->key[s->keys ++] = hid_code;
509         } else
510             return;
511     }
512
513     usb_hid_changed(hs);
514 }
515
516 static inline int int_clamp(int val, int vmin, int vmax)
517 {
518     if (val < vmin)
519         return vmin;
520     else if (val > vmax)
521         return vmax;
522     else
523         return val;
524 }
525
526 static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
527 {
528     int dx, dy, dz, b, l;
529     USBMouseState *s = &hs->ptr;
530
531     if (!s->mouse_grabbed) {
532         qemu_activate_mouse_event_handler(s->eh_entry);
533         s->mouse_grabbed = 1;
534     }
535
536     dx = int_clamp(s->dx, -127, 127);
537     dy = int_clamp(s->dy, -127, 127);
538     dz = int_clamp(s->dz, -127, 127);
539
540     s->dx -= dx;
541     s->dy -= dy;
542     s->dz -= dz;
543
544     /* Appears we have to invert the wheel direction */
545     dz = 0 - dz;
546
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     l = 0;
556     if (len > l)
557         buf[l ++] = b;
558     if (len > l)
559         buf[l ++] = dx;
560     if (len > l)
561         buf[l ++] = dy;
562     if (len > l)
563         buf[l ++] = dz;
564     return l;
565 }
566
567 static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
568 {
569     int dz, b, l;
570     USBMouseState *s = &hs->ptr;
571
572     if (!s->mouse_grabbed) {
573         qemu_activate_mouse_event_handler(s->eh_entry);
574         s->mouse_grabbed = 1;
575     }
576
577     dz = int_clamp(s->dz, -127, 127);
578     s->dz -= dz;
579
580     /* Appears we have to invert the wheel direction */
581     dz = 0 - dz;
582     b = 0;
583     if (s->buttons_state & MOUSE_EVENT_LBUTTON)
584         b |= 0x01;
585     if (s->buttons_state & MOUSE_EVENT_RBUTTON)
586         b |= 0x02;
587     if (s->buttons_state & MOUSE_EVENT_MBUTTON)
588         b |= 0x04;
589
590     buf[0] = b;
591     buf[1] = s->x & 0xff;
592     buf[2] = s->x >> 8;
593     buf[3] = s->y & 0xff;
594     buf[4] = s->y >> 8;
595     buf[5] = dz;
596     l = 6;
597
598     return l;
599 }
600
601 static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
602 {
603     if (len < 2)
604         return 0;
605
606     buf[0] = s->modifiers & 0xff;
607     buf[1] = 0;
608     if (s->keys > 6)
609         memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
610     else
611         memcpy(buf + 2, s->key, MIN(8, len) - 2);
612
613     return MIN(8, len);
614 }
615
616 static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
617 {
618     if (len > 0) {
619         int ledstate = 0;
620         /* 0x01: Num Lock LED
621          * 0x02: Caps Lock LED
622          * 0x04: Scroll Lock LED
623          * 0x08: Compose LED
624          * 0x10: Kana LED */
625         s->leds = buf[0];
626         if (s->leds & 0x04)
627             ledstate |= QEMU_SCROLL_LOCK_LED;
628         if (s->leds & 0x01)
629             ledstate |= QEMU_NUM_LOCK_LED;
630         if (s->leds & 0x02)
631             ledstate |= QEMU_CAPS_LOCK_LED;
632         kbd_put_ledstate(ledstate);
633     }
634     return 0;
635 }
636
637 static void usb_mouse_handle_reset(USBDevice *dev)
638 {
639     USBHIDState *s = (USBHIDState *)dev;
640
641     s->ptr.dx = 0;
642     s->ptr.dy = 0;
643     s->ptr.dz = 0;
644     s->ptr.x = 0;
645     s->ptr.y = 0;
646     s->ptr.buttons_state = 0;
647     s->protocol = 1;
648 }
649
650 static void usb_keyboard_handle_reset(USBDevice *dev)
651 {
652     USBHIDState *s = (USBHIDState *)dev;
653
654     qemu_add_kbd_event_handler(usb_keyboard_event, s);
655     s->protocol = 1;
656 }
657
658 static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
659 {
660     s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
661 }
662
663 static int usb_hid_handle_control(USBDevice *dev, int request, int value,
664                                   int index, int length, uint8_t *data)
665 {
666     USBHIDState *s = (USBHIDState *)dev;
667     int ret;
668
669     ret = usb_desc_handle_control(dev, request, value, index, length, data);
670     if (ret >= 0) {
671         return ret;
672     }
673
674     ret = 0;
675     switch(request) {
676     case DeviceRequest | USB_REQ_GET_STATUS:
677         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
678             (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
679         data[1] = 0x00;
680         ret = 2;
681         break;
682     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
683         if (value == USB_DEVICE_REMOTE_WAKEUP) {
684             dev->remote_wakeup = 0;
685         } else {
686             goto fail;
687         }
688         ret = 0;
689         break;
690     case DeviceOutRequest | USB_REQ_SET_FEATURE:
691         if (value == USB_DEVICE_REMOTE_WAKEUP) {
692             dev->remote_wakeup = 1;
693         } else {
694             goto fail;
695         }
696         ret = 0;
697         break;
698     case DeviceRequest | USB_REQ_GET_INTERFACE:
699         data[0] = 0;
700         ret = 1;
701         break;
702     case DeviceOutRequest | USB_REQ_SET_INTERFACE:
703         ret = 0;
704         break;
705         /* hid specific requests */
706     case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
707         switch(value >> 8) {
708         case 0x22:
709             if (s->kind == USB_MOUSE) {
710                 memcpy(data, qemu_mouse_hid_report_descriptor,
711                        sizeof(qemu_mouse_hid_report_descriptor));
712                 ret = sizeof(qemu_mouse_hid_report_descriptor);
713             } else if (s->kind == USB_TABLET) {
714                 memcpy(data, qemu_tablet_hid_report_descriptor,
715                        sizeof(qemu_tablet_hid_report_descriptor));
716                 ret = sizeof(qemu_tablet_hid_report_descriptor);
717             } else if (s->kind == USB_KEYBOARD) {
718                 memcpy(data, qemu_keyboard_hid_report_descriptor,
719                        sizeof(qemu_keyboard_hid_report_descriptor));
720                 ret = sizeof(qemu_keyboard_hid_report_descriptor);
721             }
722             break;
723         default:
724             goto fail;
725         }
726         break;
727     case GET_REPORT:
728         if (s->kind == USB_MOUSE)
729             ret = usb_mouse_poll(s, data, length);
730         else if (s->kind == USB_TABLET)
731             ret = usb_tablet_poll(s, data, length);
732         else if (s->kind == USB_KEYBOARD)
733             ret = usb_keyboard_poll(&s->kbd, data, length);
734         break;
735     case SET_REPORT:
736         if (s->kind == USB_KEYBOARD)
737             ret = usb_keyboard_write(&s->kbd, data, length);
738         else
739             goto fail;
740         break;
741     case GET_PROTOCOL:
742         if (s->kind != USB_KEYBOARD)
743             goto fail;
744         ret = 1;
745         data[0] = s->protocol;
746         break;
747     case SET_PROTOCOL:
748         if (s->kind != USB_KEYBOARD)
749             goto fail;
750         ret = 0;
751         s->protocol = value;
752         break;
753     case GET_IDLE:
754         ret = 1;
755         data[0] = s->idle;
756         break;
757     case SET_IDLE:
758         s->idle = (uint8_t) (value >> 8);
759         usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
760         ret = 0;
761         break;
762     default:
763     fail:
764         ret = USB_RET_STALL;
765         break;
766     }
767     return ret;
768 }
769
770 static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
771 {
772     USBHIDState *s = (USBHIDState *)dev;
773     int ret = 0;
774
775     switch(p->pid) {
776     case USB_TOKEN_IN:
777         if (p->devep == 1) {
778             int64_t curtime = qemu_get_clock(vm_clock);
779             if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
780                 return USB_RET_NAK;
781             usb_hid_set_next_idle(s, curtime);
782             s->changed = 0;
783             if (s->kind == USB_MOUSE)
784                 ret = usb_mouse_poll(s, p->data, p->len);
785             else if (s->kind == USB_TABLET)
786                 ret = usb_tablet_poll(s, p->data, p->len);
787             else if (s->kind == USB_KEYBOARD)
788                 ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
789         } else {
790             goto fail;
791         }
792         break;
793     case USB_TOKEN_OUT:
794     default:
795     fail:
796         ret = USB_RET_STALL;
797         break;
798     }
799     return ret;
800 }
801
802 static void usb_hid_handle_destroy(USBDevice *dev)
803 {
804     USBHIDState *s = (USBHIDState *)dev;
805
806     switch(s->kind) {
807     case USB_KEYBOARD:
808         qemu_remove_kbd_event_handler();
809         break;
810     default:
811         qemu_remove_mouse_event_handler(s->ptr.eh_entry);
812     }
813 }
814
815 static int usb_hid_initfn(USBDevice *dev, int kind)
816 {
817     USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
818
819     usb_desc_init(dev);
820     s->kind = kind;
821
822     if (s->kind == USB_MOUSE) {
823         s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
824                                                        0, "QEMU USB Mouse");
825     } else if (s->kind == USB_TABLET) {
826         s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
827                                                        1, "QEMU USB Tablet");
828     }
829         
830     /* Force poll routine to be run and grab input the first time.  */
831     s->changed = 1;
832     return 0;
833 }
834
835 static int usb_tablet_initfn(USBDevice *dev)
836 {
837     return usb_hid_initfn(dev, USB_TABLET);
838 }
839
840 static int usb_mouse_initfn(USBDevice *dev)
841 {
842     return usb_hid_initfn(dev, USB_MOUSE);
843 }
844
845 static int usb_keyboard_initfn(USBDevice *dev)
846 {
847     return usb_hid_initfn(dev, USB_KEYBOARD);
848 }
849
850 void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
851 {
852     USBHIDState *s = (USBHIDState *)dev;
853
854     s->datain_opaque = opaque;
855     s->datain = datain;
856 }
857
858 static struct USBDeviceInfo hid_info[] = {
859     {
860         .product_desc   = "QEMU USB Tablet",
861         .qdev.name      = "usb-tablet",
862         .usbdevice_name = "tablet",
863         .qdev.size      = sizeof(USBHIDState),
864         .usb_desc       = &desc_tablet,
865         .init           = usb_tablet_initfn,
866         .handle_packet  = usb_generic_handle_packet,
867         .handle_reset   = usb_mouse_handle_reset,
868         .handle_control = usb_hid_handle_control,
869         .handle_data    = usb_hid_handle_data,
870         .handle_destroy = usb_hid_handle_destroy,
871     },{
872         .product_desc   = "QEMU USB Mouse",
873         .qdev.name      = "usb-mouse",
874         .usbdevice_name = "mouse",
875         .qdev.size      = sizeof(USBHIDState),
876         .usb_desc       = &desc_mouse,
877         .init           = usb_mouse_initfn,
878         .handle_packet  = usb_generic_handle_packet,
879         .handle_reset   = usb_mouse_handle_reset,
880         .handle_control = usb_hid_handle_control,
881         .handle_data    = usb_hid_handle_data,
882         .handle_destroy = usb_hid_handle_destroy,
883     },{
884         .product_desc   = "QEMU USB Keyboard",
885         .qdev.name      = "usb-kbd",
886         .usbdevice_name = "keyboard",
887         .qdev.size      = sizeof(USBHIDState),
888         .usb_desc       = &desc_keyboard,
889         .init           = usb_keyboard_initfn,
890         .handle_packet  = usb_generic_handle_packet,
891         .handle_reset   = usb_keyboard_handle_reset,
892         .handle_control = usb_hid_handle_control,
893         .handle_data    = usb_hid_handle_data,
894         .handle_destroy = usb_hid_handle_destroy,
895     },{
896         /* end of list */
897     }
898 };
899
900 static void usb_hid_register_devices(void)
901 {
902     usb_qdev_register_many(hid_info);
903 }
904 device_init(usb_hid_register_devices)
This page took 0.076087 seconds and 4 git commands to generate.