Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ 46aaebff

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