Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ a2d4e44b

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