Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ 1f6e24e7

History | View | Annotate | Download (16 kB)

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