increase USB table poll interval
[qemu] / hw / usb-hid.c
1 /*
2  * QEMU USB HID devices
3  * 
4  * Copyright (c) 2005 Fabrice Bellard
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "vl.h"
25
26 /* HID interface requests */
27 #define GET_REPORT   0xa101
28 #define GET_IDLE     0xa102
29 #define GET_PROTOCOL 0xa103
30 #define SET_IDLE     0x210a
31 #define SET_PROTOCOL 0x210b
32
33 #define USB_MOUSE  1
34 #define USB_TABLET 2
35
36 typedef struct USBMouseState {
37     USBDevice dev;
38     int dx, dy, dz, buttons_state;
39     int x, y;
40     int kind;
41     int mouse_grabbed;
42     QEMUPutMouseEntry *eh_entry;
43 } USBMouseState;
44
45 /* mostly the same values as the Bochs USB Mouse device */
46 static const uint8_t qemu_mouse_dev_descriptor[] = {
47         0x12,       /*  u8 bLength; */
48         0x01,       /*  u8 bDescriptorType; Device */
49         0x10, 0x00, /*  u16 bcdUSB; v1.0 */
50
51         0x00,       /*  u8  bDeviceClass; */
52         0x00,       /*  u8  bDeviceSubClass; */
53         0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
54         0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
55
56         0x27, 0x06, /*  u16 idVendor; */
57         0x01, 0x00, /*  u16 idProduct; */
58         0x00, 0x00, /*  u16 bcdDevice */
59
60         0x03,       /*  u8  iManufacturer; */
61         0x02,       /*  u8  iProduct; */
62         0x01,       /*  u8  iSerialNumber; */
63         0x01        /*  u8  bNumConfigurations; */
64 };
65
66 static const uint8_t qemu_mouse_config_descriptor[] = {
67         /* one configuration */
68         0x09,       /*  u8  bLength; */
69         0x02,       /*  u8  bDescriptorType; Configuration */
70         0x22, 0x00, /*  u16 wTotalLength; */
71         0x01,       /*  u8  bNumInterfaces; (1) */
72         0x01,       /*  u8  bConfigurationValue; */
73         0x04,       /*  u8  iConfiguration; */
74         0xa0,       /*  u8  bmAttributes; 
75                                  Bit 7: must be set,
76                                      6: Self-powered,
77                                      5: Remote wakeup,
78                                      4..0: resvd */
79         50,         /*  u8  MaxPower; */
80       
81         /* USB 1.1:
82          * USB 2.0, single TT organization (mandatory):
83          *      one interface, protocol 0
84          *
85          * USB 2.0, multiple TT organization (optional):
86          *      two interfaces, protocols 1 (like single TT)
87          *      and 2 (multiple TT mode) ... config is
88          *      sometimes settable
89          *      NOT IMPLEMENTED
90          */
91
92         /* one interface */
93         0x09,       /*  u8  if_bLength; */
94         0x04,       /*  u8  if_bDescriptorType; Interface */
95         0x00,       /*  u8  if_bInterfaceNumber; */
96         0x00,       /*  u8  if_bAlternateSetting; */
97         0x01,       /*  u8  if_bNumEndpoints; */
98         0x03,       /*  u8  if_bInterfaceClass; */
99         0x01,       /*  u8  if_bInterfaceSubClass; */
100         0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
101         0x05,       /*  u8  if_iInterface; */
102      
103         /* HID descriptor */
104         0x09,        /*  u8  bLength; */
105         0x21,        /*  u8 bDescriptorType; */
106         0x01, 0x00,  /*  u16 HID_class */
107         0x00,        /*  u8 country_code */
108         0x01,        /*  u8 num_descriptors */
109         0x22,        /*  u8 type; Report */
110         50, 0,       /*  u16 len */
111
112         /* one endpoint (status change endpoint) */
113         0x07,       /*  u8  ep_bLength; */
114         0x05,       /*  u8  ep_bDescriptorType; Endpoint */
115         0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
116         0x03,       /*  u8  ep_bmAttributes; Interrupt */
117         0x03, 0x00, /*  u16 ep_wMaxPacketSize; */
118         0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
119 };
120
121 static const uint8_t qemu_tablet_config_descriptor[] = {
122         /* one configuration */
123         0x09,       /*  u8  bLength; */
124         0x02,       /*  u8  bDescriptorType; Configuration */
125         0x22, 0x00, /*  u16 wTotalLength; */
126         0x01,       /*  u8  bNumInterfaces; (1) */
127         0x01,       /*  u8  bConfigurationValue; */
128         0x04,       /*  u8  iConfiguration; */
129         0xa0,       /*  u8  bmAttributes; 
130                                  Bit 7: must be set,
131                                      6: Self-powered,
132                                      5: Remote wakeup,
133                                      4..0: resvd */
134         50,         /*  u8  MaxPower; */
135       
136         /* USB 1.1:
137          * USB 2.0, single TT organization (mandatory):
138          *      one interface, protocol 0
139          *
140          * USB 2.0, multiple TT organization (optional):
141          *      two interfaces, protocols 1 (like single TT)
142          *      and 2 (multiple TT mode) ... config is
143          *      sometimes settable
144          *      NOT IMPLEMENTED
145          */
146
147         /* one interface */
148         0x09,       /*  u8  if_bLength; */
149         0x04,       /*  u8  if_bDescriptorType; Interface */
150         0x00,       /*  u8  if_bInterfaceNumber; */
151         0x00,       /*  u8  if_bAlternateSetting; */
152         0x01,       /*  u8  if_bNumEndpoints; */
153         0x03,       /*  u8  if_bInterfaceClass; */
154         0x01,       /*  u8  if_bInterfaceSubClass; */
155         0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
156         0x05,       /*  u8  if_iInterface; */
157
158         /* HID descriptor */
159         0x09,        /*  u8  bLength; */
160         0x21,        /*  u8 bDescriptorType; */
161         0x01, 0x00,  /*  u16 HID_class */
162         0x00,        /*  u8 country_code */
163         0x01,        /*  u8 num_descriptors */
164         0x22,        /*  u8 type; Report */
165         74, 0,       /*  u16 len */
166
167         /* one endpoint (status change endpoint) */
168         0x07,       /*  u8  ep_bLength; */
169         0x05,       /*  u8  ep_bDescriptorType; Endpoint */
170         0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
171         0x03,       /*  u8  ep_bmAttributes; Interrupt */
172         0x08, 0x00, /*  u16 ep_wMaxPacketSize; */
173         0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
174 };
175
176 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
177     0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 
178     0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
179     0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 
180     0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
181     0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81, 
182     0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
183     0xC0, 0xC0,
184 };
185
186 static const uint8_t qemu_tablet_hid_report_descriptor[] = {
187         0x05, 0x01, /* Usage Page Generic Desktop */
188         0x09, 0x01, /* Usage Mouse */
189         0xA1, 0x01, /* Collection Application */
190         0x09, 0x01, /* Usage Pointer */
191         0xA1, 0x00, /* Collection Physical */
192         0x05, 0x09, /* Usage Page Button */
193         0x19, 0x01, /* Usage Minimum Button 1 */
194         0x29, 0x03, /* Usage Maximum Button 3 */
195         0x15, 0x00, /* Logical Minimum 0 */
196         0x25, 0x01, /* Logical Maximum 1 */
197         0x95, 0x03, /* Report Count 3 */
198         0x75, 0x01, /* Report Size 1 */
199         0x81, 0x02, /* Input (Data, Var, Abs) */
200         0x95, 0x01, /* Report Count 1 */
201         0x75, 0x05, /* Report Size 5 */
202         0x81, 0x01, /* Input (Cnst, Var, Abs) */
203         0x05, 0x01, /* Usage Page Generic Desktop */
204         0x09, 0x30, /* Usage X */
205         0x09, 0x31, /* Usage Y */
206         0x15, 0x00, /* Logical Minimum 0 */
207         0x26, 0xFF, 0x7F, /* Logical Maximum 0x7fff */
208         0x35, 0x00, /* Physical Minimum 0 */
209         0x46, 0xFE, 0x7F, /* Physical Maximum 0x7fff */
210         0x75, 0x10, /* Report Size 16 */
211         0x95, 0x02, /* Report Count 2 */
212         0x81, 0x02, /* Input (Data, Var, Abs) */
213         0x05, 0x01, /* Usage Page Generic Desktop */
214         0x09, 0x38, /* Usage Wheel */
215         0x15, 0x81, /* Logical Minimum -127 */
216         0x25, 0x7F, /* Logical Maximum 127 */
217         0x35, 0x00, /* Physical Minimum 0 (same as logical) */
218         0x45, 0x00, /* Physical Maximum 0 (same as logical) */
219         0x75, 0x08, /* Report Size 8 */
220         0x95, 0x01, /* Report Count 1 */
221         0x81, 0x02, /* Input (Data, Var, Rel) */
222         0xC0,       /* End Collection */
223         0xC0,       /* End Collection */
224 };
225
226 static void usb_mouse_event(void *opaque,
227                             int dx1, int dy1, int dz1, int buttons_state)
228 {
229     USBMouseState *s = opaque;
230
231     s->dx += dx1;
232     s->dy += dy1;
233     s->dz += dz1;
234     s->buttons_state = buttons_state;
235 }
236
237 static void usb_tablet_event(void *opaque,
238                              int x, int y, int dz, int buttons_state)
239 {
240     USBMouseState *s = opaque;
241
242     s->x = x;
243     s->y = y;
244     s->dz += dz;
245     s->buttons_state = buttons_state;
246 }
247
248 static inline int int_clamp(int val, int vmin, int vmax)
249 {
250     if (val < vmin)
251         return vmin;
252     else if (val > vmax)
253         return vmax;
254     else
255         return val;
256 }
257
258 static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
259 {
260     int dx, dy, dz, b, l;
261
262     if (!s->mouse_grabbed) {
263         s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
264                                                   0, "QEMU USB Mouse");
265         s->mouse_grabbed = 1;
266     }
267     
268     dx = int_clamp(s->dx, -128, 127);
269     dy = int_clamp(s->dy, -128, 127);
270     dz = int_clamp(s->dz, -128, 127);
271
272     s->dx -= dx;
273     s->dy -= dy;
274     s->dz -= dz;
275     
276     b = 0;
277     if (s->buttons_state & MOUSE_EVENT_LBUTTON)
278         b |= 0x01;
279     if (s->buttons_state & MOUSE_EVENT_RBUTTON)
280         b |= 0x02;
281     if (s->buttons_state & MOUSE_EVENT_MBUTTON)
282         b |= 0x04;
283     
284     buf[0] = b;
285     buf[1] = dx;
286     buf[2] = dy;
287     l = 3;
288     if (len >= 4) {
289         buf[3] = dz;
290         l = 4;
291     }
292     return l;
293 }
294
295 static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
296 {
297     int dz, b, l;
298
299     if (!s->mouse_grabbed) {
300         s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
301                                                   1, "QEMU USB Tablet");
302         s->mouse_grabbed = 1;
303     }
304     
305     dz = int_clamp(s->dz, -128, 127);
306     s->dz -= dz;
307
308     /* Appears we have to invert the wheel direction */
309     dz = 0 - dz;
310     b = 0;
311     if (s->buttons_state & MOUSE_EVENT_LBUTTON)
312         b |= 0x01;
313     if (s->buttons_state & MOUSE_EVENT_RBUTTON)
314         b |= 0x02;
315     if (s->buttons_state & MOUSE_EVENT_MBUTTON)
316         b |= 0x04;
317
318     buf[0] = b;
319     buf[1] = s->x & 0xff;
320     buf[2] = s->x >> 8;
321     buf[3] = s->y & 0xff;
322     buf[4] = s->y >> 8;
323     buf[5] = dz;
324     l = 6;
325
326     return l;
327 }
328
329 static void usb_mouse_handle_reset(USBDevice *dev)
330 {
331     USBMouseState *s = (USBMouseState *)dev;
332
333     s->dx = 0;
334     s->dy = 0;
335     s->dz = 0;
336     s->x = 0;
337     s->y = 0;
338     s->buttons_state = 0;
339 }
340
341 static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
342                                   int index, int length, uint8_t *data)
343 {
344     USBMouseState *s = (USBMouseState *)dev;
345     int ret = 0;
346
347     switch(request) {
348     case DeviceRequest | USB_REQ_GET_STATUS:
349         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
350             (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
351         data[1] = 0x00;
352         ret = 2;
353         break;
354     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
355         if (value == USB_DEVICE_REMOTE_WAKEUP) {
356             dev->remote_wakeup = 0;
357         } else {
358             goto fail;
359         }
360         ret = 0;
361         break;
362     case DeviceOutRequest | USB_REQ_SET_FEATURE:
363         if (value == USB_DEVICE_REMOTE_WAKEUP) {
364             dev->remote_wakeup = 1;
365         } else {
366             goto fail;
367         }
368         ret = 0;
369         break;
370     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
371         dev->addr = value;
372         ret = 0;
373         break;
374     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
375         switch(value >> 8) {
376         case USB_DT_DEVICE:
377             memcpy(data, qemu_mouse_dev_descriptor, 
378                    sizeof(qemu_mouse_dev_descriptor));
379             ret = sizeof(qemu_mouse_dev_descriptor);
380             break;
381         case USB_DT_CONFIG:
382             if (s->kind == USB_MOUSE) {
383                 memcpy(data, qemu_mouse_config_descriptor, 
384                        sizeof(qemu_mouse_config_descriptor));
385                 ret = sizeof(qemu_mouse_config_descriptor);
386             } else if (s->kind == USB_TABLET) {
387                 memcpy(data, qemu_tablet_config_descriptor, 
388                        sizeof(qemu_tablet_config_descriptor));
389                 ret = sizeof(qemu_tablet_config_descriptor);
390             }           
391             break;
392         case USB_DT_STRING:
393             switch(value & 0xff) {
394             case 0:
395                 /* language ids */
396                 data[0] = 4;
397                 data[1] = 3;
398                 data[2] = 0x09;
399                 data[3] = 0x04;
400                 ret = 4;
401                 break;
402             case 1:
403                 /* serial number */
404                 ret = set_usb_string(data, "1");
405                 break;
406             case 2:
407                 /* product description */
408                 if (s->kind == USB_MOUSE)
409                     ret = set_usb_string(data, "QEMU USB Mouse");
410                 else if (s->kind == USB_TABLET)
411                     ret = set_usb_string(data, "QEMU USB Tablet");
412                 break;
413             case 3:
414                 /* vendor description */
415                 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
416                 break;
417             case 4:
418                 ret = set_usb_string(data, "HID Mouse");
419                 break;
420             case 5:
421                 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
422                 break;
423             default:
424                 goto fail;
425             }
426             break;
427         default:
428             goto fail;
429         }
430         break;
431     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
432         data[0] = 1;
433         ret = 1;
434         break;
435     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
436         ret = 0;
437         break;
438     case DeviceRequest | USB_REQ_GET_INTERFACE:
439         data[0] = 0;
440         ret = 1;
441         break;
442     case DeviceOutRequest | USB_REQ_SET_INTERFACE:
443         ret = 0;
444         break;
445         /* hid specific requests */
446     case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
447         switch(value >> 8) {
448         case 0x22:
449             if (s->kind == USB_MOUSE) {
450                 memcpy(data, qemu_mouse_hid_report_descriptor, 
451                        sizeof(qemu_mouse_hid_report_descriptor));
452                 ret = sizeof(qemu_mouse_hid_report_descriptor);
453             } else if (s->kind == USB_TABLET) {
454                 memcpy(data, qemu_tablet_hid_report_descriptor, 
455                        sizeof(qemu_tablet_hid_report_descriptor));
456                 ret = sizeof(qemu_tablet_hid_report_descriptor);
457             }
458             break;
459         default:
460             goto fail;
461         }
462         break;
463     case GET_REPORT:
464         if (s->kind == USB_MOUSE)
465             ret = usb_mouse_poll(s, data, length);
466         else if (s->kind == USB_TABLET)
467             ret = usb_tablet_poll(s, data, length);
468         break;
469     case SET_IDLE:
470         ret = 0;
471         break;
472     default:
473     fail:
474         ret = USB_RET_STALL;
475         break;
476     }
477     return ret;
478 }
479
480 static int usb_mouse_handle_data(USBDevice *dev, USBPacket *p)
481 {
482     USBMouseState *s = (USBMouseState *)dev;
483     int ret = 0;
484
485     switch(p->pid) {
486     case USB_TOKEN_IN:
487         if (p->devep == 1) {
488             if (s->kind == USB_MOUSE)
489                 ret = usb_mouse_poll(s, p->data, p->len);
490             else if (s->kind == USB_TABLET)
491                 ret = usb_tablet_poll(s, p->data, p->len);
492         } else {
493             goto fail;
494         }
495         break;
496     case USB_TOKEN_OUT:
497     default:
498     fail:
499         ret = USB_RET_STALL;
500         break;
501     }
502     return ret;
503 }
504
505 static void usb_mouse_handle_destroy(USBDevice *dev)
506 {
507     USBMouseState *s = (USBMouseState *)dev;
508
509     qemu_remove_mouse_event_handler(s->eh_entry);
510     qemu_free(s);
511 }
512
513 USBDevice *usb_tablet_init(void)
514 {
515     USBMouseState *s;
516
517     s = qemu_mallocz(sizeof(USBMouseState));
518     if (!s)
519         return NULL;
520     s->dev.speed = USB_SPEED_FULL;
521     s->dev.handle_packet = usb_generic_handle_packet;
522
523     s->dev.handle_reset = usb_mouse_handle_reset;
524     s->dev.handle_control = usb_mouse_handle_control;
525     s->dev.handle_data = usb_mouse_handle_data;
526     s->dev.handle_destroy = usb_mouse_handle_destroy;
527     s->kind = USB_TABLET;
528
529     pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
530
531     return (USBDevice *)s;
532 }
533
534 USBDevice *usb_mouse_init(void)
535 {
536     USBMouseState *s;
537
538     s = qemu_mallocz(sizeof(USBMouseState));
539     if (!s)
540         return NULL;
541     s->dev.speed = USB_SPEED_FULL;
542     s->dev.handle_packet = usb_generic_handle_packet;
543
544     s->dev.handle_reset = usb_mouse_handle_reset;
545     s->dev.handle_control = usb_mouse_handle_control;
546     s->dev.handle_data = usb_mouse_handle_data;
547     s->dev.handle_destroy = usb_mouse_handle_destroy;
548     s->kind = USB_MOUSE;
549
550     pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
551
552     return (USBDevice *)s;
553 }