Rearrange SCSI disk emulation code.
[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, int destroy)
327 {
328     USBMouseState *s = (USBMouseState *)dev;
329
330     if (destroy) {
331         qemu_add_mouse_event_handler(NULL, NULL, 0);
332         qemu_free(s);
333         return;
334     }
335
336     s->dx = 0;
337     s->dy = 0;
338     s->dz = 0;
339     s->x = 0;
340     s->y = 0;
341     s->buttons_state = 0;
342 }
343
344 static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
345                                   int index, int length, uint8_t *data)
346 {
347     USBMouseState *s = (USBMouseState *)dev;
348     int ret = 0;
349
350     switch(request) {
351     case DeviceRequest | USB_REQ_GET_STATUS:
352         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
353             (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
354         data[1] = 0x00;
355         ret = 2;
356         break;
357     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
358         if (value == USB_DEVICE_REMOTE_WAKEUP) {
359             dev->remote_wakeup = 0;
360         } else {
361             goto fail;
362         }
363         ret = 0;
364         break;
365     case DeviceOutRequest | USB_REQ_SET_FEATURE:
366         if (value == USB_DEVICE_REMOTE_WAKEUP) {
367             dev->remote_wakeup = 1;
368         } else {
369             goto fail;
370         }
371         ret = 0;
372         break;
373     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
374         dev->addr = value;
375         ret = 0;
376         break;
377     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
378         switch(value >> 8) {
379         case USB_DT_DEVICE:
380             memcpy(data, qemu_mouse_dev_descriptor, 
381                    sizeof(qemu_mouse_dev_descriptor));
382             ret = sizeof(qemu_mouse_dev_descriptor);
383             break;
384         case USB_DT_CONFIG:
385             if (s->kind == USB_MOUSE) {
386                 memcpy(data, qemu_mouse_config_descriptor, 
387                        sizeof(qemu_mouse_config_descriptor));
388                 ret = sizeof(qemu_mouse_config_descriptor);
389             } else if (s->kind == USB_TABLET) {
390                 memcpy(data, qemu_tablet_config_descriptor, 
391                        sizeof(qemu_tablet_config_descriptor));
392                 ret = sizeof(qemu_tablet_config_descriptor);
393             }           
394             break;
395         case USB_DT_STRING:
396             switch(value & 0xff) {
397             case 0:
398                 /* language ids */
399                 data[0] = 4;
400                 data[1] = 3;
401                 data[2] = 0x09;
402                 data[3] = 0x04;
403                 ret = 4;
404                 break;
405             case 1:
406                 /* serial number */
407                 ret = set_usb_string(data, "1");
408                 break;
409             case 2:
410                 /* product description */
411                 if (s->kind == USB_MOUSE)
412                     ret = set_usb_string(data, "QEMU USB Mouse");
413                 else if (s->kind == USB_TABLET)
414                     ret = set_usb_string(data, "QEMU USB Tablet");
415                 break;
416             case 3:
417                 /* vendor description */
418                 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
419                 break;
420             case 4:
421                 ret = set_usb_string(data, "HID Mouse");
422                 break;
423             case 5:
424                 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
425                 break;
426             default:
427                 goto fail;
428             }
429             break;
430         default:
431             goto fail;
432         }
433         break;
434     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
435         data[0] = 1;
436         ret = 1;
437         break;
438     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
439         ret = 0;
440         break;
441     case DeviceRequest | USB_REQ_GET_INTERFACE:
442         data[0] = 0;
443         ret = 1;
444         break;
445     case DeviceOutRequest | USB_REQ_SET_INTERFACE:
446         ret = 0;
447         break;
448         /* hid specific requests */
449     case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
450         switch(value >> 8) {
451         case 0x22:
452             if (s->kind == USB_MOUSE) {
453                 memcpy(data, qemu_mouse_hid_report_descriptor, 
454                        sizeof(qemu_mouse_hid_report_descriptor));
455                 ret = sizeof(qemu_mouse_hid_report_descriptor);
456             } else if (s->kind == USB_TABLET) {
457                 memcpy(data, qemu_tablet_hid_report_descriptor, 
458                        sizeof(qemu_tablet_hid_report_descriptor));
459                 ret = sizeof(qemu_tablet_hid_report_descriptor);
460             }
461             break;
462         default:
463             goto fail;
464         }
465         break;
466     case GET_REPORT:
467         if (s->kind == USB_MOUSE)
468             ret = usb_mouse_poll(s, data, length);
469         else if (s->kind == USB_TABLET)
470             ret = usb_tablet_poll(s, data, length);
471         break;
472     case SET_IDLE:
473         ret = 0;
474         break;
475     default:
476     fail:
477         ret = USB_RET_STALL;
478         break;
479     }
480     return ret;
481 }
482
483 static int usb_mouse_handle_data(USBDevice *dev, int pid, 
484                                  uint8_t devep, uint8_t *data, int len)
485 {
486     USBMouseState *s = (USBMouseState *)dev;
487     int ret = 0;
488
489     switch(pid) {
490     case USB_TOKEN_IN:
491         if (devep == 1) {
492             if (s->kind == USB_MOUSE)
493                 ret = usb_mouse_poll(s, data, len);
494             else if (s->kind == USB_TABLET)
495                 ret = usb_tablet_poll(s, data, len);
496         } else {
497             goto fail;
498         }
499         break;
500     case USB_TOKEN_OUT:
501     default:
502     fail:
503         ret = USB_RET_STALL;
504         break;
505     }
506     return ret;
507 }
508
509 USBDevice *usb_tablet_init(void)
510 {
511     USBMouseState *s;
512
513     s = qemu_mallocz(sizeof(USBMouseState));
514     if (!s)
515         return NULL;
516     s->dev.speed = USB_SPEED_FULL;
517     s->dev.handle_packet = usb_generic_handle_packet;
518
519     s->dev.handle_reset = usb_mouse_handle_reset;
520     s->dev.handle_control = usb_mouse_handle_control;
521     s->dev.handle_data = usb_mouse_handle_data;
522     s->kind = USB_TABLET;
523
524     return (USBDevice *)s;
525 }
526
527 USBDevice *usb_mouse_init(void)
528 {
529     USBMouseState *s;
530
531     s = qemu_mallocz(sizeof(USBMouseState));
532     if (!s)
533         return NULL;
534     s->dev.speed = USB_SPEED_FULL;
535     s->dev.handle_packet = usb_generic_handle_packet;
536
537     s->dev.handle_reset = usb_mouse_handle_reset;
538     s->dev.handle_control = usb_mouse_handle_control;
539     s->dev.handle_data = usb_mouse_handle_data;
540     s->kind = USB_MOUSE;
541
542     return (USBDevice *)s;
543 }