6f9ee827d8d5efdecfe3febcf2e8174bb90156ed
[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 typedef struct USBMouseState {
34     USBDevice dev;
35     int dx, dy, dz, buttons_state;
36 } USBMouseState;
37
38 /* mostly the same values as the Bochs USB Mouse device */
39 static const uint8_t qemu_mouse_dev_descriptor[] = {
40         0x12,       /*  u8 bLength; */
41         0x01,       /*  u8 bDescriptorType; Device */
42         0x10, 0x00, /*  u16 bcdUSB; v1.0 */
43
44         0x00,       /*  u8  bDeviceClass; */
45         0x00,       /*  u8  bDeviceSubClass; */
46         0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
47         0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
48
49         0x27, 0x06, /*  u16 idVendor; */
50         0x01, 0x00, /*  u16 idProduct; */
51         0x00, 0x00, /*  u16 bcdDevice */
52
53         0x03,       /*  u8  iManufacturer; */
54         0x02,       /*  u8  iProduct; */
55         0x01,       /*  u8  iSerialNumber; */
56         0x01        /*  u8  bNumConfigurations; */
57 };
58
59 static const uint8_t qemu_mouse_config_descriptor[] = {
60         /* one configuration */
61         0x09,       /*  u8  bLength; */
62         0x02,       /*  u8  bDescriptorType; Configuration */
63         0x22, 0x00, /*  u16 wTotalLength; */
64         0x01,       /*  u8  bNumInterfaces; (1) */
65         0x01,       /*  u8  bConfigurationValue; */
66         0x04,       /*  u8  iConfiguration; */
67         0xa0,       /*  u8  bmAttributes; 
68                                  Bit 7: must be set,
69                                      6: Self-powered,
70                                      5: Remote wakeup,
71                                      4..0: resvd */
72         50,         /*  u8  MaxPower; */
73       
74         /* USB 1.1:
75          * USB 2.0, single TT organization (mandatory):
76          *      one interface, protocol 0
77          *
78          * USB 2.0, multiple TT organization (optional):
79          *      two interfaces, protocols 1 (like single TT)
80          *      and 2 (multiple TT mode) ... config is
81          *      sometimes settable
82          *      NOT IMPLEMENTED
83          */
84
85         /* one interface */
86         0x09,       /*  u8  if_bLength; */
87         0x04,       /*  u8  if_bDescriptorType; Interface */
88         0x00,       /*  u8  if_bInterfaceNumber; */
89         0x00,       /*  u8  if_bAlternateSetting; */
90         0x01,       /*  u8  if_bNumEndpoints; */
91         0x03,       /*  u8  if_bInterfaceClass; */
92         0x01,       /*  u8  if_bInterfaceSubClass; */
93         0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
94         0x05,       /*  u8  if_iInterface; */
95      
96         /* one endpoint (status change endpoint) */
97         0x07,       /*  u8  ep_bLength; */
98         0x05,       /*  u8  ep_bDescriptorType; Endpoint */
99         0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
100         0x03,       /*  u8  ep_bmAttributes; Interrupt */
101         0x03, 0x00, /*  u16 ep_wMaxPacketSize; */
102         0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
103
104         /* HID descriptor */
105         0x09,        /*  u8  bLength; */
106         0x21,        /*  u8 bDescriptorType; */
107         0x01, 0x00,  /*  u16 HID_class */
108         0x00,        /*  u8 country_code */
109         0x01,        /*  u8 num_descriptors */
110         0x22,        /*  u8 type; Report */
111         50, 0,       /*  u16 len */
112 };
113
114 static const uint8_t qemu_mouse_hid_report_descriptor[] = {
115     0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 
116     0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
117     0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 
118     0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
119     0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81, 
120     0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
121     0xC0, 0xC0,
122 };
123
124 static void usb_mouse_event(void *opaque,
125                             int dx1, int dy1, int dz1, int buttons_state)
126 {
127     USBMouseState *s = opaque;
128
129     s->dx += dx1;
130     s->dy += dy1;
131     s->dz += dz1;
132     s->buttons_state = buttons_state;
133 }
134
135 static inline int int_clamp(int val, int vmin, int vmax)
136 {
137     if (val < vmin)
138         return vmin;
139     else if (val > vmax)
140         return vmax;
141     else
142         return val;
143 }
144
145 static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
146 {
147     int dx, dy, dz, b, l;
148
149     dx = int_clamp(s->dx, -128, 127);
150     dy = int_clamp(s->dy, -128, 127);
151     dz = int_clamp(s->dz, -128, 127);
152
153     s->dx -= dx;
154     s->dy -= dy;
155     s->dz -= dz;
156     
157     b = 0;
158     if (s->buttons_state & MOUSE_EVENT_LBUTTON)
159         b |= 0x01;
160     if (s->buttons_state & MOUSE_EVENT_RBUTTON)
161         b |= 0x02;
162     if (s->buttons_state & MOUSE_EVENT_MBUTTON)
163         b |= 0x04;
164     
165     buf[0] = b;
166     buf[1] = dx;
167     buf[2] = dy;
168     l = 3;
169     if (len >= 4) {
170         buf[3] = dz;
171         l = 4;
172     }
173     return l;
174 }
175
176 static void usb_mouse_handle_reset(USBDevice *dev)
177 {
178     USBMouseState *s = (USBMouseState *)dev;
179
180     s->dx = 0;
181     s->dy = 0;
182     s->dz = 0;
183     s->buttons_state = 0;
184 }
185
186 static int usb_mouse_handle_control(USBDevice *dev, int request, int value,
187                                   int index, int length, uint8_t *data)
188 {
189     USBMouseState *s = (USBMouseState *)dev;
190     int ret;
191
192     switch(request) {
193     case DeviceRequest | USB_REQ_GET_STATUS:
194         data[0] = (1 << USB_DEVICE_SELF_POWERED) |
195             (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
196         data[1] = 0x00;
197         ret = 2;
198         break;
199     case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
200         if (value == USB_DEVICE_REMOTE_WAKEUP) {
201             dev->remote_wakeup = 0;
202         } else {
203             goto fail;
204         }
205         ret = 0;
206         break;
207     case DeviceOutRequest | USB_REQ_SET_FEATURE:
208         if (value == USB_DEVICE_REMOTE_WAKEUP) {
209             dev->remote_wakeup = 1;
210         } else {
211             goto fail;
212         }
213         ret = 0;
214         break;
215     case DeviceOutRequest | USB_REQ_SET_ADDRESS:
216         dev->addr = value;
217         ret = 0;
218         break;
219     case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
220         switch(value >> 8) {
221         case USB_DT_DEVICE:
222             memcpy(data, qemu_mouse_dev_descriptor, 
223                    sizeof(qemu_mouse_dev_descriptor));
224             ret = sizeof(qemu_mouse_dev_descriptor);
225             break;
226         case USB_DT_CONFIG:
227             memcpy(data, qemu_mouse_config_descriptor, 
228                    sizeof(qemu_mouse_config_descriptor));
229             ret = sizeof(qemu_mouse_config_descriptor);
230             break;
231         case USB_DT_STRING:
232             switch(value & 0xff) {
233             case 0:
234                 /* language ids */
235                 data[0] = 4;
236                 data[1] = 3;
237                 data[2] = 0x09;
238                 data[3] = 0x04;
239                 ret = 4;
240                 break;
241             case 1:
242                 /* serial number */
243                 ret = set_usb_string(data, "1");
244                 break;
245             case 2:
246                 /* product description */
247                 ret = set_usb_string(data, "QEMU USB Mouse");
248                 break;
249             case 3:
250                 /* vendor description */
251                 ret = set_usb_string(data, "QEMU " QEMU_VERSION);
252                 break;
253             case 4:
254                 ret = set_usb_string(data, "HID Mouse");
255                 break;
256             case 5:
257                 ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
258                 break;
259             default:
260                 goto fail;
261             }
262             break;
263         default:
264             goto fail;
265         }
266         break;
267     case DeviceRequest | USB_REQ_GET_CONFIGURATION:
268         data[0] = 1;
269         ret = 1;
270         break;
271     case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
272         ret = 0;
273         break;
274     case DeviceRequest | USB_REQ_GET_INTERFACE:
275         data[0] = 0;
276         ret = 1;
277         break;
278     case DeviceOutRequest | USB_REQ_SET_INTERFACE:
279         ret = 0;
280         break;
281         /* hid specific requests */
282     case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
283         switch(value >> 8) {
284         case 0x22:
285             memcpy(data, qemu_mouse_hid_report_descriptor, 
286                    sizeof(qemu_mouse_hid_report_descriptor));
287             ret = sizeof(qemu_mouse_hid_report_descriptor);
288             break;
289         default:
290             goto fail;
291         }
292         break;
293     case GET_REPORT:
294         ret = usb_mouse_poll(s, data, length);
295         break;
296     case SET_IDLE:
297         ret = 0;
298         break;
299     default:
300     fail:
301         ret = USB_RET_STALL;
302         break;
303     }
304     return ret;
305 }
306
307 static int usb_mouse_handle_data(USBDevice *dev, int pid, 
308                                  uint8_t devep, uint8_t *data, int len)
309 {
310     USBMouseState *s = (USBMouseState *)dev;
311     int ret;
312
313     switch(pid) {
314     case USB_TOKEN_IN:
315         if (devep == 1) {
316             ret = usb_mouse_poll(s, data, len);
317         } else {
318             goto fail;
319         }
320         break;
321     case USB_TOKEN_OUT:
322     default:
323     fail:
324         ret = USB_RET_STALL;
325         break;
326     }
327     return ret;
328 }
329
330 USBDevice *usb_mouse_init(void)
331 {
332     USBMouseState *s;
333
334     s = qemu_mallocz(sizeof(USBMouseState));
335     if (!s)
336         return NULL;
337     s->dev.speed = USB_SPEED_FULL;
338     s->dev.handle_packet = usb_generic_handle_packet;
339
340     s->dev.handle_reset = usb_mouse_handle_reset;
341     s->dev.handle_control = usb_mouse_handle_control;
342     s->dev.handle_data = usb_mouse_handle_data;
343
344     qemu_add_mouse_event_handler(usb_mouse_event, s);
345     
346     return (USBDevice *)s;
347 }