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