Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ cb25a3fb

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