Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ 33d68b5f

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