Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ b584726d

History | View | Annotate | Download (28.1 kB)

1 59ae540c bellard
/*
2 59ae540c bellard
 * QEMU USB HID devices
3 5fafdf24 ths
 *
4 59ae540c bellard
 * Copyright (c) 2005 Fabrice Bellard
5 47b2d338 balrog
 * Copyright (c) 2007 OpenMoko, Inc.  (andrew@openedhand.com)
6 5fafdf24 ths
 *
7 59ae540c bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 59ae540c bellard
 * of this software and associated documentation files (the "Software"), to deal
9 59ae540c bellard
 * in the Software without restriction, including without limitation the rights
10 59ae540c bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 59ae540c bellard
 * copies of the Software, and to permit persons to whom the Software is
12 59ae540c bellard
 * furnished to do so, subject to the following conditions:
13 59ae540c bellard
 *
14 59ae540c bellard
 * The above copyright notice and this permission notice shall be included in
15 59ae540c bellard
 * all copies or substantial portions of the Software.
16 59ae540c bellard
 *
17 59ae540c bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 59ae540c bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 59ae540c bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 59ae540c bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 59ae540c bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 59ae540c bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 59ae540c bellard
 * THE SOFTWARE.
24 59ae540c bellard
 */
25 87ecb68b pbrook
#include "hw.h"
26 87ecb68b pbrook
#include "console.h"
27 87ecb68b pbrook
#include "usb.h"
28 59ae540c bellard
29 59ae540c bellard
/* HID interface requests */
30 59ae540c bellard
#define GET_REPORT   0xa101
31 59ae540c bellard
#define GET_IDLE     0xa102
32 59ae540c bellard
#define GET_PROTOCOL 0xa103
33 47b2d338 balrog
#define SET_REPORT   0x2109
34 59ae540c bellard
#define SET_IDLE     0x210a
35 59ae540c bellard
#define SET_PROTOCOL 0x210b
36 59ae540c bellard
37 47b2d338 balrog
/* HID descriptor types */
38 47b2d338 balrog
#define USB_DT_HID    0x21
39 47b2d338 balrog
#define USB_DT_REPORT 0x22
40 47b2d338 balrog
#define USB_DT_PHY    0x23
41 47b2d338 balrog
42 47b2d338 balrog
#define USB_MOUSE     1
43 47b2d338 balrog
#define USB_TABLET    2
44 47b2d338 balrog
#define USB_KEYBOARD  3
45 09b26c5e bellard
46 59ae540c bellard
typedef struct USBMouseState {
47 59ae540c bellard
    int dx, dy, dz, buttons_state;
48 09b26c5e bellard
    int x, y;
49 09b26c5e bellard
    int mouse_grabbed;
50 455204eb ths
    QEMUPutMouseEntry *eh_entry;
51 59ae540c bellard
} USBMouseState;
52 59ae540c bellard
53 47b2d338 balrog
typedef struct USBKeyboardState {
54 47b2d338 balrog
    uint16_t modifiers;
55 47b2d338 balrog
    uint8_t leds;
56 47b2d338 balrog
    uint8_t key[16];
57 47b2d338 balrog
    int keys;
58 47b2d338 balrog
} USBKeyboardState;
59 47b2d338 balrog
60 47b2d338 balrog
typedef struct USBHIDState {
61 47b2d338 balrog
    USBDevice dev;
62 47b2d338 balrog
    union {
63 47b2d338 balrog
        USBMouseState ptr;
64 47b2d338 balrog
        USBKeyboardState kbd;
65 47b2d338 balrog
    };
66 47b2d338 balrog
    int kind;
67 47b2d338 balrog
    int protocol;
68 181a29c5 aliguori
    uint8_t idle;
69 117b3ae6 pbrook
    int changed;
70 47e699dc balrog
    void *datain_opaque;
71 47e699dc balrog
    void (*datain)(void *);
72 47b2d338 balrog
} USBHIDState;
73 47b2d338 balrog
74 59ae540c bellard
/* mostly the same values as the Bochs USB Mouse device */
75 59ae540c bellard
static const uint8_t qemu_mouse_dev_descriptor[] = {
76 59ae540c bellard
        0x12,       /*  u8 bLength; */
77 59ae540c bellard
        0x01,       /*  u8 bDescriptorType; Device */
78 e126cf13 ths
        0x00, 0x01, /*  u16 bcdUSB; v1.0 */
79 59ae540c bellard
80 59ae540c bellard
        0x00,            /*  u8  bDeviceClass; */
81 59ae540c bellard
        0x00,            /*  u8  bDeviceSubClass; */
82 59ae540c bellard
        0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
83 59ae540c bellard
        0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */
84 59ae540c bellard
85 59ae540c bellard
        0x27, 0x06, /*  u16 idVendor; */
86 59ae540c bellard
         0x01, 0x00, /*  u16 idProduct; */
87 59ae540c bellard
        0x00, 0x00, /*  u16 bcdDevice */
88 59ae540c bellard
89 59ae540c bellard
        0x03,       /*  u8  iManufacturer; */
90 59ae540c bellard
        0x02,       /*  u8  iProduct; */
91 59ae540c bellard
        0x01,       /*  u8  iSerialNumber; */
92 59ae540c bellard
        0x01        /*  u8  bNumConfigurations; */
93 59ae540c bellard
};
94 59ae540c bellard
95 59ae540c bellard
static const uint8_t qemu_mouse_config_descriptor[] = {
96 59ae540c bellard
        /* one configuration */
97 59ae540c bellard
        0x09,       /*  u8  bLength; */
98 59ae540c bellard
        0x02,       /*  u8  bDescriptorType; Configuration */
99 59ae540c bellard
        0x22, 0x00, /*  u16 wTotalLength; */
100 59ae540c bellard
        0x01,       /*  u8  bNumInterfaces; (1) */
101 59ae540c bellard
        0x01,       /*  u8  bConfigurationValue; */
102 59ae540c bellard
        0x04,       /*  u8  iConfiguration; */
103 5fafdf24 ths
        0xa0,       /*  u8  bmAttributes;
104 59ae540c bellard
                                 Bit 7: must be set,
105 59ae540c bellard
                                     6: Self-powered,
106 59ae540c bellard
                                     5: Remote wakeup,
107 59ae540c bellard
                                     4..0: resvd */
108 59ae540c bellard
        50,         /*  u8  MaxPower; */
109 3b46e624 ths
110 59ae540c bellard
        /* USB 1.1:
111 59ae540c bellard
         * USB 2.0, single TT organization (mandatory):
112 59ae540c bellard
         *        one interface, protocol 0
113 59ae540c bellard
         *
114 59ae540c bellard
         * USB 2.0, multiple TT organization (optional):
115 59ae540c bellard
         *        two interfaces, protocols 1 (like single TT)
116 59ae540c bellard
         *        and 2 (multiple TT mode) ... config is
117 59ae540c bellard
         *        sometimes settable
118 59ae540c bellard
         *        NOT IMPLEMENTED
119 59ae540c bellard
         */
120 59ae540c bellard
121 59ae540c bellard
        /* one interface */
122 59ae540c bellard
        0x09,       /*  u8  if_bLength; */
123 59ae540c bellard
        0x04,       /*  u8  if_bDescriptorType; Interface */
124 59ae540c bellard
        0x00,       /*  u8  if_bInterfaceNumber; */
125 59ae540c bellard
        0x00,       /*  u8  if_bAlternateSetting; */
126 59ae540c bellard
        0x01,       /*  u8  if_bNumEndpoints; */
127 59ae540c bellard
        0x03,       /*  u8  if_bInterfaceClass; */
128 59ae540c bellard
        0x01,       /*  u8  if_bInterfaceSubClass; */
129 59ae540c bellard
        0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
130 47b2d338 balrog
        0x07,       /*  u8  if_iInterface; */
131 3b46e624 ths
132 09b26c5e bellard
        /* HID descriptor */
133 09b26c5e bellard
        0x09,        /*  u8  bLength; */
134 09b26c5e bellard
        0x21,        /*  u8 bDescriptorType; */
135 09b26c5e bellard
        0x01, 0x00,  /*  u16 HID_class */
136 09b26c5e bellard
        0x00,        /*  u8 country_code */
137 09b26c5e bellard
        0x01,        /*  u8 num_descriptors */
138 09b26c5e bellard
        0x22,        /*  u8 type; Report */
139 c21c583a balrog
        52, 0,       /*  u16 len */
140 09b26c5e bellard
141 59ae540c bellard
        /* one endpoint (status change endpoint) */
142 59ae540c bellard
        0x07,       /*  u8  ep_bLength; */
143 59ae540c bellard
        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
144 59ae540c bellard
        0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
145 59ae540c bellard
         0x03,       /*  u8  ep_bmAttributes; Interrupt */
146 c21c583a balrog
         0x04, 0x00, /*  u16 ep_wMaxPacketSize; */
147 59ae540c bellard
        0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
148 09b26c5e bellard
};
149 09b26c5e bellard
150 09b26c5e bellard
static const uint8_t qemu_tablet_config_descriptor[] = {
151 09b26c5e bellard
        /* one configuration */
152 09b26c5e bellard
        0x09,       /*  u8  bLength; */
153 09b26c5e bellard
        0x02,       /*  u8  bDescriptorType; Configuration */
154 09b26c5e bellard
        0x22, 0x00, /*  u16 wTotalLength; */
155 09b26c5e bellard
        0x01,       /*  u8  bNumInterfaces; (1) */
156 09b26c5e bellard
        0x01,       /*  u8  bConfigurationValue; */
157 47b2d338 balrog
        0x05,       /*  u8  iConfiguration; */
158 5fafdf24 ths
        0xa0,       /*  u8  bmAttributes;
159 09b26c5e bellard
                                 Bit 7: must be set,
160 09b26c5e bellard
                                     6: Self-powered,
161 09b26c5e bellard
                                     5: Remote wakeup,
162 09b26c5e bellard
                                     4..0: resvd */
163 09b26c5e bellard
        50,         /*  u8  MaxPower; */
164 3b46e624 ths
165 09b26c5e bellard
        /* USB 1.1:
166 09b26c5e bellard
         * USB 2.0, single TT organization (mandatory):
167 09b26c5e bellard
         *        one interface, protocol 0
168 09b26c5e bellard
         *
169 09b26c5e bellard
         * USB 2.0, multiple TT organization (optional):
170 09b26c5e bellard
         *        two interfaces, protocols 1 (like single TT)
171 09b26c5e bellard
         *        and 2 (multiple TT mode) ... config is
172 09b26c5e bellard
         *        sometimes settable
173 09b26c5e bellard
         *        NOT IMPLEMENTED
174 09b26c5e bellard
         */
175 09b26c5e bellard
176 09b26c5e bellard
        /* one interface */
177 09b26c5e bellard
        0x09,       /*  u8  if_bLength; */
178 09b26c5e bellard
        0x04,       /*  u8  if_bDescriptorType; Interface */
179 09b26c5e bellard
        0x00,       /*  u8  if_bInterfaceNumber; */
180 09b26c5e bellard
        0x00,       /*  u8  if_bAlternateSetting; */
181 09b26c5e bellard
        0x01,       /*  u8  if_bNumEndpoints; */
182 09b26c5e bellard
        0x03,       /*  u8  if_bInterfaceClass; */
183 09b26c5e bellard
        0x01,       /*  u8  if_bInterfaceSubClass; */
184 09b26c5e bellard
        0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
185 47b2d338 balrog
        0x07,       /*  u8  if_iInterface; */
186 59ae540c bellard
187 59ae540c bellard
        /* HID descriptor */
188 59ae540c bellard
        0x09,        /*  u8  bLength; */
189 59ae540c bellard
        0x21,        /*  u8 bDescriptorType; */
190 59ae540c bellard
        0x01, 0x00,  /*  u16 HID_class */
191 59ae540c bellard
        0x00,        /*  u8 country_code */
192 59ae540c bellard
        0x01,        /*  u8 num_descriptors */
193 59ae540c bellard
        0x22,        /*  u8 type; Report */
194 09b26c5e bellard
        74, 0,       /*  u16 len */
195 09b26c5e bellard
196 09b26c5e bellard
        /* one endpoint (status change endpoint) */
197 09b26c5e bellard
        0x07,       /*  u8  ep_bLength; */
198 09b26c5e bellard
        0x05,       /*  u8  ep_bDescriptorType; Endpoint */
199 09b26c5e bellard
        0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
200 09b26c5e bellard
         0x03,       /*  u8  ep_bmAttributes; Interrupt */
201 09b26c5e bellard
         0x08, 0x00, /*  u16 ep_wMaxPacketSize; */
202 f2f1ac82 bellard
        0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
203 59ae540c bellard
};
204 59ae540c bellard
205 47b2d338 balrog
static const uint8_t qemu_keyboard_config_descriptor[] = {
206 47b2d338 balrog
    /* one configuration */
207 47b2d338 balrog
    0x09,                /*  u8  bLength; */
208 47b2d338 balrog
    USB_DT_CONFIG,        /*  u8  bDescriptorType; Configuration */
209 47b2d338 balrog
    0x22, 0x00,                /*  u16 wTotalLength; */
210 47b2d338 balrog
    0x01,                /*  u8  bNumInterfaces; (1) */
211 47b2d338 balrog
    0x01,                /*  u8  bConfigurationValue; */
212 47b2d338 balrog
    0x06,                /*  u8  iConfiguration; */
213 5fafdf24 ths
    0xa0,                /*  u8  bmAttributes;
214 47b2d338 balrog
                                Bit 7: must be set,
215 47b2d338 balrog
                                    6: Self-powered,
216 47b2d338 balrog
                                    5: Remote wakeup,
217 47b2d338 balrog
                                    4..0: resvd */
218 47b2d338 balrog
    0x32,                /*  u8  MaxPower; */
219 47b2d338 balrog
220 47b2d338 balrog
    /* USB 1.1:
221 47b2d338 balrog
     * USB 2.0, single TT organization (mandatory):
222 47b2d338 balrog
     *        one interface, protocol 0
223 47b2d338 balrog
     *
224 47b2d338 balrog
     * USB 2.0, multiple TT organization (optional):
225 47b2d338 balrog
     *        two interfaces, protocols 1 (like single TT)
226 47b2d338 balrog
     *        and 2 (multiple TT mode) ... config is
227 47b2d338 balrog
     *        sometimes settable
228 47b2d338 balrog
     *        NOT IMPLEMENTED
229 47b2d338 balrog
     */
230 47b2d338 balrog
231 47b2d338 balrog
    /* one interface */
232 47b2d338 balrog
    0x09,                /*  u8  if_bLength; */
233 47b2d338 balrog
    USB_DT_INTERFACE,        /*  u8  if_bDescriptorType; Interface */
234 47b2d338 balrog
    0x00,                /*  u8  if_bInterfaceNumber; */
235 47b2d338 balrog
    0x00,                /*  u8  if_bAlternateSetting; */
236 47b2d338 balrog
    0x01,                /*  u8  if_bNumEndpoints; */
237 47b2d338 balrog
    0x03,                /*  u8  if_bInterfaceClass; HID */
238 47b2d338 balrog
    0x01,                /*  u8  if_bInterfaceSubClass; Boot */
239 47b2d338 balrog
    0x01,                /*  u8  if_bInterfaceProtocol; Keyboard */
240 47b2d338 balrog
    0x07,                /*  u8  if_iInterface; */
241 47b2d338 balrog
242 47b2d338 balrog
    /* HID descriptor */
243 47b2d338 balrog
    0x09,                /*  u8  bLength; */
244 47b2d338 balrog
    USB_DT_HID,                /*  u8  bDescriptorType; */
245 47b2d338 balrog
    0x11, 0x01,                /*  u16 HID_class */
246 47b2d338 balrog
    0x00,                /*  u8  country_code */
247 47b2d338 balrog
    0x01,                /*  u8  num_descriptors */
248 47b2d338 balrog
    USB_DT_REPORT,        /*  u8  type; Report */
249 47b2d338 balrog
    0x3f, 0x00,                /*  u16 len */
250 47b2d338 balrog
251 47b2d338 balrog
    /* one endpoint (status change endpoint) */
252 47b2d338 balrog
    0x07,                /*  u8  ep_bLength; */
253 47b2d338 balrog
    USB_DT_ENDPOINT,        /*  u8  ep_bDescriptorType; Endpoint */
254 47b2d338 balrog
    USB_DIR_IN | 0x01,        /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
255 47b2d338 balrog
    0x03,                /*  u8  ep_bmAttributes; Interrupt */
256 47b2d338 balrog
    0x08, 0x00,                /*  u16 ep_wMaxPacketSize; */
257 47b2d338 balrog
    0x0a,                /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
258 47b2d338 balrog
};
259 47b2d338 balrog
260 59ae540c bellard
static const uint8_t qemu_mouse_hid_report_descriptor[] = {
261 976f8eef balrog
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
262 976f8eef balrog
    0x09, 0x02,                /* Usage (Mouse) */
263 976f8eef balrog
    0xa1, 0x01,                /* Collection (Application) */
264 976f8eef balrog
    0x09, 0x01,                /*   Usage (Pointer) */
265 976f8eef balrog
    0xa1, 0x00,                /*   Collection (Physical) */
266 976f8eef balrog
    0x05, 0x09,                /*     Usage Page (Button) */
267 976f8eef balrog
    0x19, 0x01,                /*     Usage Minimum (1) */
268 976f8eef balrog
    0x29, 0x03,                /*     Usage Maximum (3) */
269 976f8eef balrog
    0x15, 0x00,                /*     Logical Minimum (0) */
270 976f8eef balrog
    0x25, 0x01,                /*     Logical Maximum (1) */
271 976f8eef balrog
    0x95, 0x03,                /*     Report Count (3) */
272 976f8eef balrog
    0x75, 0x01,                /*     Report Size (1) */
273 976f8eef balrog
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
274 976f8eef balrog
    0x95, 0x01,                /*     Report Count (1) */
275 976f8eef balrog
    0x75, 0x05,                /*     Report Size (5) */
276 976f8eef balrog
    0x81, 0x01,                /*     Input (Constant) */
277 976f8eef balrog
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
278 976f8eef balrog
    0x09, 0x30,                /*     Usage (X) */
279 976f8eef balrog
    0x09, 0x31,                /*     Usage (Y) */
280 976f8eef balrog
    0x09, 0x38,                /*     Usage (Wheel) */
281 976f8eef balrog
    0x15, 0x81,                /*     Logical Minimum (-0x7f) */
282 976f8eef balrog
    0x25, 0x7f,                /*     Logical Maximum (0x7f) */
283 976f8eef balrog
    0x75, 0x08,                /*     Report Size (8) */
284 976f8eef balrog
    0x95, 0x03,                /*     Report Count (3) */
285 976f8eef balrog
    0x81, 0x06,                /*     Input (Data, Variable, Relative) */
286 976f8eef balrog
    0xc0,                /*   End Collection */
287 976f8eef balrog
    0xc0,                /* End Collection */
288 59ae540c bellard
};
289 59ae540c bellard
290 09b26c5e bellard
static const uint8_t qemu_tablet_hid_report_descriptor[] = {
291 976f8eef balrog
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
292 976f8eef balrog
    0x09, 0x01,                /* Usage (Pointer) */
293 976f8eef balrog
    0xa1, 0x01,                /* Collection (Application) */
294 976f8eef balrog
    0x09, 0x01,                /*   Usage (Pointer) */
295 976f8eef balrog
    0xa1, 0x00,                /*   Collection (Physical) */
296 976f8eef balrog
    0x05, 0x09,                /*     Usage Page (Button) */
297 976f8eef balrog
    0x19, 0x01,                /*     Usage Minimum (1) */
298 976f8eef balrog
    0x29, 0x03,                /*     Usage Maximum (3) */
299 976f8eef balrog
    0x15, 0x00,                /*     Logical Minimum (0) */
300 976f8eef balrog
    0x25, 0x01,                /*     Logical Maximum (1) */
301 976f8eef balrog
    0x95, 0x03,                /*     Report Count (3) */
302 976f8eef balrog
    0x75, 0x01,                /*     Report Size (1) */
303 976f8eef balrog
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
304 976f8eef balrog
    0x95, 0x01,                /*     Report Count (1) */
305 976f8eef balrog
    0x75, 0x05,                /*     Report Size (5) */
306 976f8eef balrog
    0x81, 0x01,                /*     Input (Constant) */
307 976f8eef balrog
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
308 976f8eef balrog
    0x09, 0x30,                /*     Usage (X) */
309 976f8eef balrog
    0x09, 0x31,                /*     Usage (Y) */
310 976f8eef balrog
    0x15, 0x00,                /*     Logical Minimum (0) */
311 de5c2d0a balrog
    0x26, 0xff, 0x7f,        /*     Logical Maximum (0x7fff) */
312 976f8eef balrog
    0x35, 0x00,                /*     Physical Minimum (0) */
313 de5c2d0a balrog
    0x46, 0xff, 0x7f,        /*     Physical Maximum (0x7fff) */
314 976f8eef balrog
    0x75, 0x10,                /*     Report Size (16) */
315 976f8eef balrog
    0x95, 0x02,                /*     Report Count (2) */
316 976f8eef balrog
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
317 976f8eef balrog
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
318 976f8eef balrog
    0x09, 0x38,                /*     Usage (Wheel) */
319 976f8eef balrog
    0x15, 0x81,                /*     Logical Minimum (-0x7f) */
320 976f8eef balrog
    0x25, 0x7f,                /*     Logical Maximum (0x7f) */
321 976f8eef balrog
    0x35, 0x00,                /*     Physical Minimum (same as logical) */
322 976f8eef balrog
    0x45, 0x00,                /*     Physical Maximum (same as logical) */
323 976f8eef balrog
    0x75, 0x08,                /*     Report Size (8) */
324 976f8eef balrog
    0x95, 0x01,                /*     Report Count (1) */
325 976f8eef balrog
    0x81, 0x06,                /*     Input (Data, Variable, Relative) */
326 976f8eef balrog
    0xc0,                /*   End Collection */
327 976f8eef balrog
    0xc0,                /* End Collection */
328 09b26c5e bellard
};
329 09b26c5e bellard
330 47b2d338 balrog
static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
331 47b2d338 balrog
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
332 47b2d338 balrog
    0x09, 0x06,                /* Usage (Keyboard) */
333 47b2d338 balrog
    0xa1, 0x01,                /* Collection (Application) */
334 47b2d338 balrog
    0x75, 0x01,                /*   Report Size (1) */
335 47b2d338 balrog
    0x95, 0x08,                /*   Report Count (8) */
336 47b2d338 balrog
    0x05, 0x07,                /*   Usage Page (Key Codes) */
337 47b2d338 balrog
    0x19, 0xe0,                /*   Usage Minimum (224) */
338 47b2d338 balrog
    0x29, 0xe7,                /*   Usage Maximum (231) */
339 47b2d338 balrog
    0x15, 0x00,                /*   Logical Minimum (0) */
340 47b2d338 balrog
    0x25, 0x01,                /*   Logical Maximum (1) */
341 47b2d338 balrog
    0x81, 0x02,                /*   Input (Data, Variable, Absolute) */
342 47b2d338 balrog
    0x95, 0x01,                /*   Report Count (1) */
343 47b2d338 balrog
    0x75, 0x08,                /*   Report Size (8) */
344 47b2d338 balrog
    0x81, 0x01,                /*   Input (Constant) */
345 47b2d338 balrog
    0x95, 0x05,                /*   Report Count (5) */
346 47b2d338 balrog
    0x75, 0x01,                /*   Report Size (1) */
347 47b2d338 balrog
    0x05, 0x08,                /*   Usage Page (LEDs) */
348 47b2d338 balrog
    0x19, 0x01,                /*   Usage Minimum (1) */
349 47b2d338 balrog
    0x29, 0x05,                /*   Usage Maximum (5) */
350 47b2d338 balrog
    0x91, 0x02,                /*   Output (Data, Variable, Absolute) */
351 47b2d338 balrog
    0x95, 0x01,                /*   Report Count (1) */
352 47b2d338 balrog
    0x75, 0x03,                /*   Report Size (3) */
353 47b2d338 balrog
    0x91, 0x01,                /*   Output (Constant) */
354 47b2d338 balrog
    0x95, 0x06,                /*   Report Count (6) */
355 47b2d338 balrog
    0x75, 0x08,                /*   Report Size (8) */
356 47b2d338 balrog
    0x15, 0x00,                /*   Logical Minimum (0) */
357 47b2d338 balrog
    0x25, 0xff,                /*   Logical Maximum (255) */
358 47b2d338 balrog
    0x05, 0x07,                /*   Usage Page (Key Codes) */
359 47b2d338 balrog
    0x19, 0x00,                /*   Usage Minimum (0) */
360 47b2d338 balrog
    0x29, 0xff,                /*   Usage Maximum (255) */
361 47b2d338 balrog
    0x81, 0x00,                /*   Input (Data, Array) */
362 47b2d338 balrog
    0xc0,                /* End Collection */
363 47b2d338 balrog
};
364 47b2d338 balrog
365 47b2d338 balrog
#define USB_HID_USAGE_ERROR_ROLLOVER        0x01
366 47b2d338 balrog
#define USB_HID_USAGE_POSTFAIL                0x02
367 47b2d338 balrog
#define USB_HID_USAGE_ERROR_UNDEFINED        0x03
368 47b2d338 balrog
369 47b2d338 balrog
/* Indices are QEMU keycodes, values are from HID Usage Table.  Indices
370 47b2d338 balrog
 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d.  */
371 47b2d338 balrog
static const uint8_t usb_hid_usage_keys[0x100] = {
372 47b2d338 balrog
    0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
373 47b2d338 balrog
    0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
374 47b2d338 balrog
    0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
375 47b2d338 balrog
    0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
376 47b2d338 balrog
    0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
377 47b2d338 balrog
    0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
378 47b2d338 balrog
    0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
379 47b2d338 balrog
    0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
380 47b2d338 balrog
    0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
381 47b2d338 balrog
    0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
382 47b2d338 balrog
    0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
383 47b2d338 balrog
    0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
384 47b2d338 balrog
    0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
385 47b2d338 balrog
    0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
386 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
388 47b2d338 balrog
389 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
390 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
392 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
393 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
395 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
396 47b2d338 balrog
    0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
398 47b2d338 balrog
    0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
399 47b2d338 balrog
    0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
400 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
404 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
405 47b2d338 balrog
};
406 47b2d338 balrog
407 47e699dc balrog
static void usb_hid_changed(USBHIDState *hs)
408 47e699dc balrog
{
409 47e699dc balrog
    hs->changed = 1;
410 47e699dc balrog
411 47e699dc balrog
    if (hs->datain)
412 47e699dc balrog
        hs->datain(hs->datain_opaque);
413 47e699dc balrog
}
414 47e699dc balrog
415 59ae540c bellard
static void usb_mouse_event(void *opaque,
416 59ae540c bellard
                            int dx1, int dy1, int dz1, int buttons_state)
417 59ae540c bellard
{
418 117b3ae6 pbrook
    USBHIDState *hs = opaque;
419 117b3ae6 pbrook
    USBMouseState *s = &hs->ptr;
420 59ae540c bellard
421 59ae540c bellard
    s->dx += dx1;
422 59ae540c bellard
    s->dy += dy1;
423 59ae540c bellard
    s->dz += dz1;
424 59ae540c bellard
    s->buttons_state = buttons_state;
425 47e699dc balrog
426 47e699dc balrog
    usb_hid_changed(hs);
427 59ae540c bellard
}
428 59ae540c bellard
429 09b26c5e bellard
static void usb_tablet_event(void *opaque,
430 09b26c5e bellard
                             int x, int y, int dz, int buttons_state)
431 09b26c5e bellard
{
432 117b3ae6 pbrook
    USBHIDState *hs = opaque;
433 117b3ae6 pbrook
    USBMouseState *s = &hs->ptr;
434 09b26c5e bellard
435 09b26c5e bellard
    s->x = x;
436 09b26c5e bellard
    s->y = y;
437 09b26c5e bellard
    s->dz += dz;
438 09b26c5e bellard
    s->buttons_state = buttons_state;
439 47e699dc balrog
440 47e699dc balrog
    usb_hid_changed(hs);
441 09b26c5e bellard
}
442 09b26c5e bellard
443 47b2d338 balrog
static void usb_keyboard_event(void *opaque, int keycode)
444 47b2d338 balrog
{
445 117b3ae6 pbrook
    USBHIDState *hs = opaque;
446 117b3ae6 pbrook
    USBKeyboardState *s = &hs->kbd;
447 47b2d338 balrog
    uint8_t hid_code, key;
448 47b2d338 balrog
    int i;
449 47b2d338 balrog
450 47b2d338 balrog
    key = keycode & 0x7f;
451 47b2d338 balrog
    hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
452 47b2d338 balrog
    s->modifiers &= ~(1 << 8);
453 47b2d338 balrog
454 47b2d338 balrog
    switch (hid_code) {
455 47b2d338 balrog
    case 0x00:
456 47b2d338 balrog
        return;
457 47b2d338 balrog
458 47b2d338 balrog
    case 0xe0:
459 47b2d338 balrog
        if (s->modifiers & (1 << 9)) {
460 47b2d338 balrog
            s->modifiers ^= 3 << 8;
461 47b2d338 balrog
            return;
462 47b2d338 balrog
        }
463 47b2d338 balrog
    case 0xe1 ... 0xe7:
464 47b2d338 balrog
        if (keycode & (1 << 7)) {
465 47b2d338 balrog
            s->modifiers &= ~(1 << (hid_code & 0x0f));
466 47b2d338 balrog
            return;
467 47b2d338 balrog
        }
468 47b2d338 balrog
    case 0xe8 ... 0xef:
469 47b2d338 balrog
        s->modifiers |= 1 << (hid_code & 0x0f);
470 47b2d338 balrog
        return;
471 47b2d338 balrog
    }
472 47b2d338 balrog
473 47b2d338 balrog
    if (keycode & (1 << 7)) {
474 47b2d338 balrog
        for (i = s->keys - 1; i >= 0; i --)
475 47b2d338 balrog
            if (s->key[i] == hid_code) {
476 47b2d338 balrog
                s->key[i] = s->key[-- s->keys];
477 47b2d338 balrog
                s->key[s->keys] = 0x00;
478 47e699dc balrog
                usb_hid_changed(hs);
479 47e699dc balrog
                break;
480 47b2d338 balrog
            }
481 47e699dc balrog
        if (i < 0)
482 47e699dc balrog
            return;
483 47b2d338 balrog
    } else {
484 47b2d338 balrog
        for (i = s->keys - 1; i >= 0; i --)
485 47b2d338 balrog
            if (s->key[i] == hid_code)
486 47e699dc balrog
                break;
487 47e699dc balrog
        if (i < 0) {
488 47e699dc balrog
            if (s->keys < sizeof(s->key))
489 47e699dc balrog
                s->key[s->keys ++] = hid_code;
490 47e699dc balrog
        } else
491 47e699dc balrog
            return;
492 47b2d338 balrog
    }
493 47e699dc balrog
494 47e699dc balrog
    usb_hid_changed(hs);
495 47b2d338 balrog
}
496 47b2d338 balrog
497 59ae540c bellard
static inline int int_clamp(int val, int vmin, int vmax)
498 59ae540c bellard
{
499 59ae540c bellard
    if (val < vmin)
500 59ae540c bellard
        return vmin;
501 59ae540c bellard
    else if (val > vmax)
502 59ae540c bellard
        return vmax;
503 59ae540c bellard
    else
504 59ae540c bellard
        return val;
505 59ae540c bellard
}
506 59ae540c bellard
507 117b3ae6 pbrook
static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
508 59ae540c bellard
{
509 59ae540c bellard
    int dx, dy, dz, b, l;
510 117b3ae6 pbrook
    USBMouseState *s = &hs->ptr;
511 59ae540c bellard
512 09b26c5e bellard
    if (!s->mouse_grabbed) {
513 117b3ae6 pbrook
        s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, hs,
514 455204eb ths
                                                  0, "QEMU USB Mouse");
515 09b26c5e bellard
        s->mouse_grabbed = 1;
516 09b26c5e bellard
    }
517 3b46e624 ths
518 976f8eef balrog
    dx = int_clamp(s->dx, -127, 127);
519 976f8eef balrog
    dy = int_clamp(s->dy, -127, 127);
520 976f8eef balrog
    dz = int_clamp(s->dz, -127, 127);
521 59ae540c bellard
522 59ae540c bellard
    s->dx -= dx;
523 59ae540c bellard
    s->dy -= dy;
524 59ae540c bellard
    s->dz -= dz;
525 3b46e624 ths
526 976f8eef balrog
    /* Appears we have to invert the wheel direction */
527 976f8eef balrog
    dz = 0 - dz;
528 976f8eef balrog
529 59ae540c bellard
    b = 0;
530 59ae540c bellard
    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
531 59ae540c bellard
        b |= 0x01;
532 59ae540c bellard
    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
533 59ae540c bellard
        b |= 0x02;
534 59ae540c bellard
    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
535 59ae540c bellard
        b |= 0x04;
536 3b46e624 ths
537 c21c583a balrog
    l = 0;
538 c21c583a balrog
    if (len > l)
539 c21c583a balrog
        buf[l ++] = b;
540 c21c583a balrog
    if (len > l)
541 c21c583a balrog
        buf[l ++] = dx;
542 c21c583a balrog
    if (len > l)
543 c21c583a balrog
        buf[l ++] = dy;
544 c21c583a balrog
    if (len > l)
545 c21c583a balrog
        buf[l ++] = dz;
546 59ae540c bellard
    return l;
547 59ae540c bellard
}
548 59ae540c bellard
549 117b3ae6 pbrook
static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
550 09b26c5e bellard
{
551 09b26c5e bellard
    int dz, b, l;
552 117b3ae6 pbrook
    USBMouseState *s = &hs->ptr;
553 09b26c5e bellard
554 09b26c5e bellard
    if (!s->mouse_grabbed) {
555 117b3ae6 pbrook
        s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs,
556 455204eb ths
                                                  1, "QEMU USB Tablet");
557 09b26c5e bellard
        s->mouse_grabbed = 1;
558 09b26c5e bellard
    }
559 3b46e624 ths
560 976f8eef balrog
    dz = int_clamp(s->dz, -127, 127);
561 09b26c5e bellard
    s->dz -= dz;
562 09b26c5e bellard
563 09b26c5e bellard
    /* Appears we have to invert the wheel direction */
564 09b26c5e bellard
    dz = 0 - dz;
565 09b26c5e bellard
    b = 0;
566 09b26c5e bellard
    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
567 09b26c5e bellard
        b |= 0x01;
568 09b26c5e bellard
    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
569 09b26c5e bellard
        b |= 0x02;
570 09b26c5e bellard
    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
571 09b26c5e bellard
        b |= 0x04;
572 09b26c5e bellard
573 09b26c5e bellard
    buf[0] = b;
574 09b26c5e bellard
    buf[1] = s->x & 0xff;
575 09b26c5e bellard
    buf[2] = s->x >> 8;
576 09b26c5e bellard
    buf[3] = s->y & 0xff;
577 09b26c5e bellard
    buf[4] = s->y >> 8;
578 09b26c5e bellard
    buf[5] = dz;
579 09b26c5e bellard
    l = 6;
580 09b26c5e bellard
581 09b26c5e bellard
    return l;
582 09b26c5e bellard
}
583 09b26c5e bellard
584 47b2d338 balrog
static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
585 47b2d338 balrog
{
586 47b2d338 balrog
    if (len < 2)
587 47b2d338 balrog
        return 0;
588 47b2d338 balrog
589 47b2d338 balrog
    buf[0] = s->modifiers & 0xff;
590 47b2d338 balrog
    buf[1] = 0;
591 47b2d338 balrog
    if (s->keys > 6)
592 47b2d338 balrog
        memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
593 47b2d338 balrog
    else
594 47b2d338 balrog
        memcpy(buf + 2, s->key, MIN(8, len) - 2);
595 47b2d338 balrog
596 47b2d338 balrog
    return MIN(8, len);
597 47b2d338 balrog
}
598 47b2d338 balrog
599 47b2d338 balrog
static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
600 47b2d338 balrog
{
601 47b2d338 balrog
    if (len > 0) {
602 47b2d338 balrog
        /* 0x01: Num Lock LED
603 47b2d338 balrog
         * 0x02: Caps Lock LED
604 47b2d338 balrog
         * 0x04: Scroll Lock LED
605 47b2d338 balrog
         * 0x08: Compose LED
606 47b2d338 balrog
         * 0x10: Kana LED */
607 47b2d338 balrog
        s->leds = buf[0];
608 47b2d338 balrog
    }
609 47b2d338 balrog
    return 0;
610 47b2d338 balrog
}
611 47b2d338 balrog
612 059809e4 bellard
static void usb_mouse_handle_reset(USBDevice *dev)
613 59ae540c bellard
{
614 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
615 47b2d338 balrog
616 47b2d338 balrog
    s->ptr.dx = 0;
617 47b2d338 balrog
    s->ptr.dy = 0;
618 47b2d338 balrog
    s->ptr.dz = 0;
619 47b2d338 balrog
    s->ptr.x = 0;
620 47b2d338 balrog
    s->ptr.y = 0;
621 47b2d338 balrog
    s->ptr.buttons_state = 0;
622 47b2d338 balrog
    s->protocol = 1;
623 47b2d338 balrog
}
624 47b2d338 balrog
625 47b2d338 balrog
static void usb_keyboard_handle_reset(USBDevice *dev)
626 47b2d338 balrog
{
627 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
628 47b2d338 balrog
629 926acf8f balrog
    qemu_add_kbd_event_handler(usb_keyboard_event, s);
630 47b2d338 balrog
    s->protocol = 1;
631 59ae540c bellard
}
632 59ae540c bellard
633 47b2d338 balrog
static int usb_hid_handle_control(USBDevice *dev, int request, int value,
634 59ae540c bellard
                                  int index, int length, uint8_t *data)
635 59ae540c bellard
{
636 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
637 09b26c5e bellard
    int ret = 0;
638 59ae540c bellard
639 59ae540c bellard
    switch(request) {
640 59ae540c bellard
    case DeviceRequest | USB_REQ_GET_STATUS:
641 59ae540c bellard
        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
642 59ae540c bellard
            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
643 59ae540c bellard
        data[1] = 0x00;
644 59ae540c bellard
        ret = 2;
645 59ae540c bellard
        break;
646 59ae540c bellard
    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
647 59ae540c bellard
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
648 59ae540c bellard
            dev->remote_wakeup = 0;
649 59ae540c bellard
        } else {
650 59ae540c bellard
            goto fail;
651 59ae540c bellard
        }
652 59ae540c bellard
        ret = 0;
653 59ae540c bellard
        break;
654 59ae540c bellard
    case DeviceOutRequest | USB_REQ_SET_FEATURE:
655 59ae540c bellard
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
656 59ae540c bellard
            dev->remote_wakeup = 1;
657 59ae540c bellard
        } else {
658 59ae540c bellard
            goto fail;
659 59ae540c bellard
        }
660 59ae540c bellard
        ret = 0;
661 59ae540c bellard
        break;
662 59ae540c bellard
    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
663 59ae540c bellard
        dev->addr = value;
664 59ae540c bellard
        ret = 0;
665 59ae540c bellard
        break;
666 59ae540c bellard
    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
667 59ae540c bellard
        switch(value >> 8) {
668 59ae540c bellard
        case USB_DT_DEVICE:
669 5fafdf24 ths
            memcpy(data, qemu_mouse_dev_descriptor,
670 59ae540c bellard
                   sizeof(qemu_mouse_dev_descriptor));
671 59ae540c bellard
            ret = sizeof(qemu_mouse_dev_descriptor);
672 59ae540c bellard
            break;
673 59ae540c bellard
        case USB_DT_CONFIG:
674 09b26c5e bellard
            if (s->kind == USB_MOUSE) {
675 5fafdf24 ths
                memcpy(data, qemu_mouse_config_descriptor,
676 09b26c5e bellard
                       sizeof(qemu_mouse_config_descriptor));
677 09b26c5e bellard
                ret = sizeof(qemu_mouse_config_descriptor);
678 09b26c5e bellard
            } else if (s->kind == USB_TABLET) {
679 5fafdf24 ths
                memcpy(data, qemu_tablet_config_descriptor,
680 09b26c5e bellard
                       sizeof(qemu_tablet_config_descriptor));
681 09b26c5e bellard
                ret = sizeof(qemu_tablet_config_descriptor);
682 47b2d338 balrog
            } else if (s->kind == USB_KEYBOARD) {
683 5fafdf24 ths
                memcpy(data, qemu_keyboard_config_descriptor,
684 47b2d338 balrog
                       sizeof(qemu_keyboard_config_descriptor));
685 47b2d338 balrog
                ret = sizeof(qemu_keyboard_config_descriptor);
686 47b2d338 balrog
            }
687 59ae540c bellard
            break;
688 59ae540c bellard
        case USB_DT_STRING:
689 59ae540c bellard
            switch(value & 0xff) {
690 59ae540c bellard
            case 0:
691 59ae540c bellard
                /* language ids */
692 59ae540c bellard
                data[0] = 4;
693 59ae540c bellard
                data[1] = 3;
694 59ae540c bellard
                data[2] = 0x09;
695 59ae540c bellard
                data[3] = 0x04;
696 59ae540c bellard
                ret = 4;
697 59ae540c bellard
                break;
698 59ae540c bellard
            case 1:
699 59ae540c bellard
                /* serial number */
700 59ae540c bellard
                ret = set_usb_string(data, "1");
701 59ae540c bellard
                break;
702 59ae540c bellard
            case 2:
703 59ae540c bellard
                /* product description */
704 47b2d338 balrog
                ret = set_usb_string(data, s->dev.devname);
705 59ae540c bellard
                break;
706 59ae540c bellard
            case 3:
707 59ae540c bellard
                /* vendor description */
708 59ae540c bellard
                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
709 59ae540c bellard
                break;
710 59ae540c bellard
            case 4:
711 59ae540c bellard
                ret = set_usb_string(data, "HID Mouse");
712 59ae540c bellard
                break;
713 59ae540c bellard
            case 5:
714 47b2d338 balrog
                ret = set_usb_string(data, "HID Tablet");
715 47b2d338 balrog
                break;
716 47b2d338 balrog
            case 6:
717 47b2d338 balrog
                ret = set_usb_string(data, "HID Keyboard");
718 47b2d338 balrog
                break;
719 47b2d338 balrog
            case 7:
720 59ae540c bellard
                ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
721 59ae540c bellard
                break;
722 59ae540c bellard
            default:
723 59ae540c bellard
                goto fail;
724 59ae540c bellard
            }
725 59ae540c bellard
            break;
726 59ae540c bellard
        default:
727 59ae540c bellard
            goto fail;
728 59ae540c bellard
        }
729 59ae540c bellard
        break;
730 59ae540c bellard
    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
731 59ae540c bellard
        data[0] = 1;
732 59ae540c bellard
        ret = 1;
733 59ae540c bellard
        break;
734 59ae540c bellard
    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
735 59ae540c bellard
        ret = 0;
736 59ae540c bellard
        break;
737 59ae540c bellard
    case DeviceRequest | USB_REQ_GET_INTERFACE:
738 59ae540c bellard
        data[0] = 0;
739 59ae540c bellard
        ret = 1;
740 59ae540c bellard
        break;
741 59ae540c bellard
    case DeviceOutRequest | USB_REQ_SET_INTERFACE:
742 59ae540c bellard
        ret = 0;
743 59ae540c bellard
        break;
744 59ae540c bellard
        /* hid specific requests */
745 59ae540c bellard
    case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
746 59ae540c bellard
        switch(value >> 8) {
747 59ae540c bellard
        case 0x22:
748 09b26c5e bellard
            if (s->kind == USB_MOUSE) {
749 5fafdf24 ths
                memcpy(data, qemu_mouse_hid_report_descriptor,
750 09b26c5e bellard
                       sizeof(qemu_mouse_hid_report_descriptor));
751 09b26c5e bellard
                ret = sizeof(qemu_mouse_hid_report_descriptor);
752 09b26c5e bellard
            } else if (s->kind == USB_TABLET) {
753 5fafdf24 ths
                memcpy(data, qemu_tablet_hid_report_descriptor,
754 09b26c5e bellard
                       sizeof(qemu_tablet_hid_report_descriptor));
755 09b26c5e bellard
                ret = sizeof(qemu_tablet_hid_report_descriptor);
756 47b2d338 balrog
            } else if (s->kind == USB_KEYBOARD) {
757 5fafdf24 ths
                memcpy(data, qemu_keyboard_hid_report_descriptor,
758 47b2d338 balrog
                       sizeof(qemu_keyboard_hid_report_descriptor));
759 47b2d338 balrog
                ret = sizeof(qemu_keyboard_hid_report_descriptor);
760 47b2d338 balrog
            }
761 47b2d338 balrog
            break;
762 59ae540c bellard
        default:
763 59ae540c bellard
            goto fail;
764 59ae540c bellard
        }
765 59ae540c bellard
        break;
766 59ae540c bellard
    case GET_REPORT:
767 09b26c5e bellard
        if (s->kind == USB_MOUSE)
768 117b3ae6 pbrook
            ret = usb_mouse_poll(s, data, length);
769 09b26c5e bellard
        else if (s->kind == USB_TABLET)
770 117b3ae6 pbrook
            ret = usb_tablet_poll(s, data, length);
771 47b2d338 balrog
        else if (s->kind == USB_KEYBOARD)
772 47b2d338 balrog
            ret = usb_keyboard_poll(&s->kbd, data, length);
773 47b2d338 balrog
        break;
774 47b2d338 balrog
    case SET_REPORT:
775 47b2d338 balrog
        if (s->kind == USB_KEYBOARD)
776 47b2d338 balrog
            ret = usb_keyboard_write(&s->kbd, data, length);
777 47b2d338 balrog
        else
778 47b2d338 balrog
            goto fail;
779 47b2d338 balrog
        break;
780 47b2d338 balrog
    case GET_PROTOCOL:
781 47b2d338 balrog
        if (s->kind != USB_KEYBOARD)
782 47b2d338 balrog
            goto fail;
783 47b2d338 balrog
        ret = 1;
784 47b2d338 balrog
        data[0] = s->protocol;
785 47b2d338 balrog
        break;
786 47b2d338 balrog
    case SET_PROTOCOL:
787 47b2d338 balrog
        if (s->kind != USB_KEYBOARD)
788 47b2d338 balrog
            goto fail;
789 47b2d338 balrog
        ret = 0;
790 47b2d338 balrog
        s->protocol = value;
791 47b2d338 balrog
        break;
792 47b2d338 balrog
    case GET_IDLE:
793 47b2d338 balrog
        ret = 1;
794 47b2d338 balrog
        data[0] = s->idle;
795 59ae540c bellard
        break;
796 59ae540c bellard
    case SET_IDLE:
797 181a29c5 aliguori
        s->idle = (uint8_t) (value >> 8);
798 59ae540c bellard
        ret = 0;
799 59ae540c bellard
        break;
800 59ae540c bellard
    default:
801 59ae540c bellard
    fail:
802 59ae540c bellard
        ret = USB_RET_STALL;
803 59ae540c bellard
        break;
804 59ae540c bellard
    }
805 59ae540c bellard
    return ret;
806 59ae540c bellard
}
807 59ae540c bellard
808 47b2d338 balrog
static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
809 59ae540c bellard
{
810 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
811 09b26c5e bellard
    int ret = 0;
812 59ae540c bellard
813 4d611c9a pbrook
    switch(p->pid) {
814 59ae540c bellard
    case USB_TOKEN_IN:
815 4d611c9a pbrook
        if (p->devep == 1) {
816 117b3ae6 pbrook
            /* TODO: Implement finite idle delays.  */
817 117b3ae6 pbrook
            if (!(s->changed || s->idle))
818 117b3ae6 pbrook
                return USB_RET_NAK;
819 117b3ae6 pbrook
            s->changed = 0;
820 47b2d338 balrog
            if (s->kind == USB_MOUSE)
821 117b3ae6 pbrook
                ret = usb_mouse_poll(s, p->data, p->len);
822 47b2d338 balrog
            else if (s->kind == USB_TABLET)
823 117b3ae6 pbrook
                ret = usb_tablet_poll(s, p->data, p->len);
824 47b2d338 balrog
            else if (s->kind == USB_KEYBOARD)
825 47b2d338 balrog
                ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
826 59ae540c bellard
        } else {
827 59ae540c bellard
            goto fail;
828 59ae540c bellard
        }
829 59ae540c bellard
        break;
830 59ae540c bellard
    case USB_TOKEN_OUT:
831 59ae540c bellard
    default:
832 59ae540c bellard
    fail:
833 59ae540c bellard
        ret = USB_RET_STALL;
834 59ae540c bellard
        break;
835 59ae540c bellard
    }
836 59ae540c bellard
    return ret;
837 59ae540c bellard
}
838 59ae540c bellard
839 47b2d338 balrog
static void usb_hid_handle_destroy(USBDevice *dev)
840 059809e4 bellard
{
841 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
842 059809e4 bellard
843 47b2d338 balrog
    if (s->kind != USB_KEYBOARD)
844 47b2d338 balrog
        qemu_remove_mouse_event_handler(s->ptr.eh_entry);
845 47b2d338 balrog
    /* TODO: else */
846 059809e4 bellard
    qemu_free(s);
847 059809e4 bellard
}
848 059809e4 bellard
849 09b26c5e bellard
USBDevice *usb_tablet_init(void)
850 09b26c5e bellard
{
851 47b2d338 balrog
    USBHIDState *s;
852 09b26c5e bellard
853 47b2d338 balrog
    s = qemu_mallocz(sizeof(USBHIDState));
854 09b26c5e bellard
    s->dev.speed = USB_SPEED_FULL;
855 09b26c5e bellard
    s->dev.handle_packet = usb_generic_handle_packet;
856 09b26c5e bellard
857 09b26c5e bellard
    s->dev.handle_reset = usb_mouse_handle_reset;
858 47b2d338 balrog
    s->dev.handle_control = usb_hid_handle_control;
859 47b2d338 balrog
    s->dev.handle_data = usb_hid_handle_data;
860 47b2d338 balrog
    s->dev.handle_destroy = usb_hid_handle_destroy;
861 09b26c5e bellard
    s->kind = USB_TABLET;
862 117b3ae6 pbrook
    /* Force poll routine to be run and grab input the first time.  */
863 117b3ae6 pbrook
    s->changed = 1;
864 09b26c5e bellard
865 1f6e24e7 bellard
    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
866 1f6e24e7 bellard
867 09b26c5e bellard
    return (USBDevice *)s;
868 09b26c5e bellard
}
869 09b26c5e bellard
870 59ae540c bellard
USBDevice *usb_mouse_init(void)
871 59ae540c bellard
{
872 47b2d338 balrog
    USBHIDState *s;
873 59ae540c bellard
874 47b2d338 balrog
    s = qemu_mallocz(sizeof(USBHIDState));
875 59ae540c bellard
    s->dev.speed = USB_SPEED_FULL;
876 59ae540c bellard
    s->dev.handle_packet = usb_generic_handle_packet;
877 59ae540c bellard
878 59ae540c bellard
    s->dev.handle_reset = usb_mouse_handle_reset;
879 47b2d338 balrog
    s->dev.handle_control = usb_hid_handle_control;
880 47b2d338 balrog
    s->dev.handle_data = usb_hid_handle_data;
881 47b2d338 balrog
    s->dev.handle_destroy = usb_hid_handle_destroy;
882 09b26c5e bellard
    s->kind = USB_MOUSE;
883 117b3ae6 pbrook
    /* Force poll routine to be run and grab input the first time.  */
884 117b3ae6 pbrook
    s->changed = 1;
885 59ae540c bellard
886 1f6e24e7 bellard
    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
887 1f6e24e7 bellard
888 59ae540c bellard
    return (USBDevice *)s;
889 59ae540c bellard
}
890 47b2d338 balrog
891 47b2d338 balrog
USBDevice *usb_keyboard_init(void)
892 47b2d338 balrog
{
893 47b2d338 balrog
    USBHIDState *s;
894 47b2d338 balrog
895 47b2d338 balrog
    s = qemu_mallocz(sizeof(USBHIDState));
896 47b2d338 balrog
    s->dev.speed = USB_SPEED_FULL;
897 47b2d338 balrog
    s->dev.handle_packet = usb_generic_handle_packet;
898 47b2d338 balrog
899 47b2d338 balrog
    s->dev.handle_reset = usb_keyboard_handle_reset;
900 47b2d338 balrog
    s->dev.handle_control = usb_hid_handle_control;
901 47b2d338 balrog
    s->dev.handle_data = usb_hid_handle_data;
902 47b2d338 balrog
    s->dev.handle_destroy = usb_hid_handle_destroy;
903 47b2d338 balrog
    s->kind = USB_KEYBOARD;
904 47b2d338 balrog
905 47b2d338 balrog
    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");
906 47b2d338 balrog
907 47b2d338 balrog
    return (USBDevice *) s;
908 47b2d338 balrog
}
909 47e699dc balrog
910 47e699dc balrog
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
911 47e699dc balrog
{
912 47e699dc balrog
    USBHIDState *s = (USBHIDState *)dev;
913 47e699dc balrog
914 47e699dc balrog
    s->datain_opaque = opaque;
915 47e699dc balrog
    s->datain = datain;
916 47e699dc balrog
}