Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ 0534163f

History | View | Annotate | Download (29.3 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 6fef28ee Anthony Liguori
        qemu_activate_mouse_event_handler(s->eh_entry);
515 09b26c5e bellard
        s->mouse_grabbed = 1;
516 09b26c5e bellard
    }
517 3b46e624 ths
518 976f8eef balrog
    dx = int_clamp(s->dx, -127, 127);
519 976f8eef balrog
    dy = int_clamp(s->dy, -127, 127);
520 976f8eef balrog
    dz = int_clamp(s->dz, -127, 127);
521 59ae540c bellard
522 59ae540c bellard
    s->dx -= dx;
523 59ae540c bellard
    s->dy -= dy;
524 59ae540c bellard
    s->dz -= dz;
525 3b46e624 ths
526 976f8eef balrog
    /* Appears we have to invert the wheel direction */
527 976f8eef balrog
    dz = 0 - dz;
528 976f8eef balrog
529 59ae540c bellard
    b = 0;
530 59ae540c bellard
    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
531 59ae540c bellard
        b |= 0x01;
532 59ae540c bellard
    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
533 59ae540c bellard
        b |= 0x02;
534 59ae540c bellard
    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
535 59ae540c bellard
        b |= 0x04;
536 3b46e624 ths
537 c21c583a balrog
    l = 0;
538 c21c583a balrog
    if (len > l)
539 c21c583a balrog
        buf[l ++] = b;
540 c21c583a balrog
    if (len > l)
541 c21c583a balrog
        buf[l ++] = dx;
542 c21c583a balrog
    if (len > l)
543 c21c583a balrog
        buf[l ++] = dy;
544 c21c583a balrog
    if (len > l)
545 c21c583a balrog
        buf[l ++] = dz;
546 59ae540c bellard
    return l;
547 59ae540c bellard
}
548 59ae540c bellard
549 117b3ae6 pbrook
static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
550 09b26c5e bellard
{
551 09b26c5e bellard
    int dz, b, l;
552 117b3ae6 pbrook
    USBMouseState *s = &hs->ptr;
553 09b26c5e bellard
554 09b26c5e bellard
    if (!s->mouse_grabbed) {
555 6fef28ee Anthony Liguori
        qemu_activate_mouse_event_handler(s->eh_entry);
556 09b26c5e bellard
        s->mouse_grabbed = 1;
557 09b26c5e bellard
    }
558 3b46e624 ths
559 976f8eef balrog
    dz = int_clamp(s->dz, -127, 127);
560 09b26c5e bellard
    s->dz -= dz;
561 09b26c5e bellard
562 09b26c5e bellard
    /* Appears we have to invert the wheel direction */
563 09b26c5e bellard
    dz = 0 - dz;
564 09b26c5e bellard
    b = 0;
565 09b26c5e bellard
    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
566 09b26c5e bellard
        b |= 0x01;
567 09b26c5e bellard
    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
568 09b26c5e bellard
        b |= 0x02;
569 09b26c5e bellard
    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
570 09b26c5e bellard
        b |= 0x04;
571 09b26c5e bellard
572 09b26c5e bellard
    buf[0] = b;
573 09b26c5e bellard
    buf[1] = s->x & 0xff;
574 09b26c5e bellard
    buf[2] = s->x >> 8;
575 09b26c5e bellard
    buf[3] = s->y & 0xff;
576 09b26c5e bellard
    buf[4] = s->y >> 8;
577 09b26c5e bellard
    buf[5] = dz;
578 09b26c5e bellard
    l = 6;
579 09b26c5e bellard
580 09b26c5e bellard
    return l;
581 09b26c5e bellard
}
582 09b26c5e bellard
583 47b2d338 balrog
static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
584 47b2d338 balrog
{
585 47b2d338 balrog
    if (len < 2)
586 47b2d338 balrog
        return 0;
587 47b2d338 balrog
588 47b2d338 balrog
    buf[0] = s->modifiers & 0xff;
589 47b2d338 balrog
    buf[1] = 0;
590 47b2d338 balrog
    if (s->keys > 6)
591 47b2d338 balrog
        memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
592 47b2d338 balrog
    else
593 47b2d338 balrog
        memcpy(buf + 2, s->key, MIN(8, len) - 2);
594 47b2d338 balrog
595 47b2d338 balrog
    return MIN(8, len);
596 47b2d338 balrog
}
597 47b2d338 balrog
598 47b2d338 balrog
static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
599 47b2d338 balrog
{
600 47b2d338 balrog
    if (len > 0) {
601 bd87813e Gerd Hoffmann
        int ledstate = 0;
602 47b2d338 balrog
        /* 0x01: Num Lock LED
603 47b2d338 balrog
         * 0x02: Caps Lock LED
604 47b2d338 balrog
         * 0x04: Scroll Lock LED
605 47b2d338 balrog
         * 0x08: Compose LED
606 47b2d338 balrog
         * 0x10: Kana LED */
607 47b2d338 balrog
        s->leds = buf[0];
608 bd87813e Gerd Hoffmann
        if (s->leds & 0x04)
609 bd87813e Gerd Hoffmann
            ledstate |= QEMU_SCROLL_LOCK_LED;
610 bd87813e Gerd Hoffmann
        if (s->leds & 0x01)
611 bd87813e Gerd Hoffmann
            ledstate |= QEMU_NUM_LOCK_LED;
612 bd87813e Gerd Hoffmann
        if (s->leds & 0x02)
613 bd87813e Gerd Hoffmann
            ledstate |= QEMU_CAPS_LOCK_LED;
614 bd87813e Gerd Hoffmann
        kbd_put_ledstate(ledstate);
615 47b2d338 balrog
    }
616 47b2d338 balrog
    return 0;
617 47b2d338 balrog
}
618 47b2d338 balrog
619 059809e4 bellard
static void usb_mouse_handle_reset(USBDevice *dev)
620 59ae540c bellard
{
621 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
622 47b2d338 balrog
623 47b2d338 balrog
    s->ptr.dx = 0;
624 47b2d338 balrog
    s->ptr.dy = 0;
625 47b2d338 balrog
    s->ptr.dz = 0;
626 47b2d338 balrog
    s->ptr.x = 0;
627 47b2d338 balrog
    s->ptr.y = 0;
628 47b2d338 balrog
    s->ptr.buttons_state = 0;
629 47b2d338 balrog
    s->protocol = 1;
630 47b2d338 balrog
}
631 47b2d338 balrog
632 47b2d338 balrog
static void usb_keyboard_handle_reset(USBDevice *dev)
633 47b2d338 balrog
{
634 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
635 47b2d338 balrog
636 926acf8f balrog
    qemu_add_kbd_event_handler(usb_keyboard_event, s);
637 47b2d338 balrog
    s->protocol = 1;
638 59ae540c bellard
}
639 59ae540c bellard
640 68735b6c Kevin O'Connor
static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
641 68735b6c Kevin O'Connor
{
642 68735b6c Kevin O'Connor
    s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
643 68735b6c Kevin O'Connor
}
644 68735b6c Kevin O'Connor
645 47b2d338 balrog
static int usb_hid_handle_control(USBDevice *dev, int request, int value,
646 59ae540c bellard
                                  int index, int length, uint8_t *data)
647 59ae540c bellard
{
648 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
649 09b26c5e bellard
    int ret = 0;
650 59ae540c bellard
651 59ae540c bellard
    switch(request) {
652 59ae540c bellard
    case DeviceRequest | USB_REQ_GET_STATUS:
653 59ae540c bellard
        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
654 59ae540c bellard
            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
655 59ae540c bellard
        data[1] = 0x00;
656 59ae540c bellard
        ret = 2;
657 59ae540c bellard
        break;
658 59ae540c bellard
    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
659 59ae540c bellard
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
660 59ae540c bellard
            dev->remote_wakeup = 0;
661 59ae540c bellard
        } else {
662 59ae540c bellard
            goto fail;
663 59ae540c bellard
        }
664 59ae540c bellard
        ret = 0;
665 59ae540c bellard
        break;
666 59ae540c bellard
    case DeviceOutRequest | USB_REQ_SET_FEATURE:
667 59ae540c bellard
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
668 59ae540c bellard
            dev->remote_wakeup = 1;
669 59ae540c bellard
        } else {
670 59ae540c bellard
            goto fail;
671 59ae540c bellard
        }
672 59ae540c bellard
        ret = 0;
673 59ae540c bellard
        break;
674 59ae540c bellard
    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
675 59ae540c bellard
        dev->addr = value;
676 59ae540c bellard
        ret = 0;
677 59ae540c bellard
        break;
678 59ae540c bellard
    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
679 59ae540c bellard
        switch(value >> 8) {
680 59ae540c bellard
        case USB_DT_DEVICE:
681 5fafdf24 ths
            memcpy(data, qemu_mouse_dev_descriptor,
682 59ae540c bellard
                   sizeof(qemu_mouse_dev_descriptor));
683 59ae540c bellard
            ret = sizeof(qemu_mouse_dev_descriptor);
684 59ae540c bellard
            break;
685 59ae540c bellard
        case USB_DT_CONFIG:
686 09b26c5e bellard
            if (s->kind == USB_MOUSE) {
687 5fafdf24 ths
                memcpy(data, qemu_mouse_config_descriptor,
688 09b26c5e bellard
                       sizeof(qemu_mouse_config_descriptor));
689 09b26c5e bellard
                ret = sizeof(qemu_mouse_config_descriptor);
690 09b26c5e bellard
            } else if (s->kind == USB_TABLET) {
691 5fafdf24 ths
                memcpy(data, qemu_tablet_config_descriptor,
692 09b26c5e bellard
                       sizeof(qemu_tablet_config_descriptor));
693 09b26c5e bellard
                ret = sizeof(qemu_tablet_config_descriptor);
694 47b2d338 balrog
            } else if (s->kind == USB_KEYBOARD) {
695 5fafdf24 ths
                memcpy(data, qemu_keyboard_config_descriptor,
696 47b2d338 balrog
                       sizeof(qemu_keyboard_config_descriptor));
697 47b2d338 balrog
                ret = sizeof(qemu_keyboard_config_descriptor);
698 47b2d338 balrog
            }
699 59ae540c bellard
            break;
700 59ae540c bellard
        case USB_DT_STRING:
701 59ae540c bellard
            switch(value & 0xff) {
702 59ae540c bellard
            case 0:
703 59ae540c bellard
                /* language ids */
704 59ae540c bellard
                data[0] = 4;
705 59ae540c bellard
                data[1] = 3;
706 59ae540c bellard
                data[2] = 0x09;
707 59ae540c bellard
                data[3] = 0x04;
708 59ae540c bellard
                ret = 4;
709 59ae540c bellard
                break;
710 59ae540c bellard
            case 1:
711 59ae540c bellard
                /* serial number */
712 59ae540c bellard
                ret = set_usb_string(data, "1");
713 59ae540c bellard
                break;
714 59ae540c bellard
            case 2:
715 59ae540c bellard
                /* product description */
716 0fe6d12e Markus Armbruster
                ret = set_usb_string(data, s->dev.product_desc);
717 59ae540c bellard
                break;
718 59ae540c bellard
            case 3:
719 59ae540c bellard
                /* vendor description */
720 59ae540c bellard
                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
721 59ae540c bellard
                break;
722 59ae540c bellard
            case 4:
723 59ae540c bellard
                ret = set_usb_string(data, "HID Mouse");
724 59ae540c bellard
                break;
725 59ae540c bellard
            case 5:
726 47b2d338 balrog
                ret = set_usb_string(data, "HID Tablet");
727 47b2d338 balrog
                break;
728 47b2d338 balrog
            case 6:
729 47b2d338 balrog
                ret = set_usb_string(data, "HID Keyboard");
730 47b2d338 balrog
                break;
731 47b2d338 balrog
            case 7:
732 59ae540c bellard
                ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
733 59ae540c bellard
                break;
734 59ae540c bellard
            default:
735 59ae540c bellard
                goto fail;
736 59ae540c bellard
            }
737 59ae540c bellard
            break;
738 59ae540c bellard
        default:
739 59ae540c bellard
            goto fail;
740 59ae540c bellard
        }
741 59ae540c bellard
        break;
742 59ae540c bellard
    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
743 59ae540c bellard
        data[0] = 1;
744 59ae540c bellard
        ret = 1;
745 59ae540c bellard
        break;
746 59ae540c bellard
    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
747 59ae540c bellard
        ret = 0;
748 59ae540c bellard
        break;
749 59ae540c bellard
    case DeviceRequest | USB_REQ_GET_INTERFACE:
750 59ae540c bellard
        data[0] = 0;
751 59ae540c bellard
        ret = 1;
752 59ae540c bellard
        break;
753 59ae540c bellard
    case DeviceOutRequest | USB_REQ_SET_INTERFACE:
754 59ae540c bellard
        ret = 0;
755 59ae540c bellard
        break;
756 59ae540c bellard
        /* hid specific requests */
757 59ae540c bellard
    case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
758 59ae540c bellard
        switch(value >> 8) {
759 59ae540c bellard
        case 0x22:
760 09b26c5e bellard
            if (s->kind == USB_MOUSE) {
761 5fafdf24 ths
                memcpy(data, qemu_mouse_hid_report_descriptor,
762 09b26c5e bellard
                       sizeof(qemu_mouse_hid_report_descriptor));
763 09b26c5e bellard
                ret = sizeof(qemu_mouse_hid_report_descriptor);
764 09b26c5e bellard
            } else if (s->kind == USB_TABLET) {
765 5fafdf24 ths
                memcpy(data, qemu_tablet_hid_report_descriptor,
766 09b26c5e bellard
                       sizeof(qemu_tablet_hid_report_descriptor));
767 09b26c5e bellard
                ret = sizeof(qemu_tablet_hid_report_descriptor);
768 47b2d338 balrog
            } else if (s->kind == USB_KEYBOARD) {
769 5fafdf24 ths
                memcpy(data, qemu_keyboard_hid_report_descriptor,
770 47b2d338 balrog
                       sizeof(qemu_keyboard_hid_report_descriptor));
771 47b2d338 balrog
                ret = sizeof(qemu_keyboard_hid_report_descriptor);
772 47b2d338 balrog
            }
773 47b2d338 balrog
            break;
774 59ae540c bellard
        default:
775 59ae540c bellard
            goto fail;
776 59ae540c bellard
        }
777 59ae540c bellard
        break;
778 59ae540c bellard
    case GET_REPORT:
779 09b26c5e bellard
        if (s->kind == USB_MOUSE)
780 117b3ae6 pbrook
            ret = usb_mouse_poll(s, data, length);
781 09b26c5e bellard
        else if (s->kind == USB_TABLET)
782 117b3ae6 pbrook
            ret = usb_tablet_poll(s, data, length);
783 47b2d338 balrog
        else if (s->kind == USB_KEYBOARD)
784 47b2d338 balrog
            ret = usb_keyboard_poll(&s->kbd, data, length);
785 47b2d338 balrog
        break;
786 47b2d338 balrog
    case SET_REPORT:
787 47b2d338 balrog
        if (s->kind == USB_KEYBOARD)
788 47b2d338 balrog
            ret = usb_keyboard_write(&s->kbd, data, length);
789 47b2d338 balrog
        else
790 47b2d338 balrog
            goto fail;
791 47b2d338 balrog
        break;
792 47b2d338 balrog
    case GET_PROTOCOL:
793 47b2d338 balrog
        if (s->kind != USB_KEYBOARD)
794 47b2d338 balrog
            goto fail;
795 47b2d338 balrog
        ret = 1;
796 47b2d338 balrog
        data[0] = s->protocol;
797 47b2d338 balrog
        break;
798 47b2d338 balrog
    case SET_PROTOCOL:
799 47b2d338 balrog
        if (s->kind != USB_KEYBOARD)
800 47b2d338 balrog
            goto fail;
801 47b2d338 balrog
        ret = 0;
802 47b2d338 balrog
        s->protocol = value;
803 47b2d338 balrog
        break;
804 47b2d338 balrog
    case GET_IDLE:
805 47b2d338 balrog
        ret = 1;
806 47b2d338 balrog
        data[0] = s->idle;
807 59ae540c bellard
        break;
808 59ae540c bellard
    case SET_IDLE:
809 181a29c5 aliguori
        s->idle = (uint8_t) (value >> 8);
810 68735b6c Kevin O'Connor
        usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
811 59ae540c bellard
        ret = 0;
812 59ae540c bellard
        break;
813 59ae540c bellard
    default:
814 59ae540c bellard
    fail:
815 59ae540c bellard
        ret = USB_RET_STALL;
816 59ae540c bellard
        break;
817 59ae540c bellard
    }
818 59ae540c bellard
    return ret;
819 59ae540c bellard
}
820 59ae540c bellard
821 47b2d338 balrog
static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
822 59ae540c bellard
{
823 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
824 09b26c5e bellard
    int ret = 0;
825 59ae540c bellard
826 4d611c9a pbrook
    switch(p->pid) {
827 59ae540c bellard
    case USB_TOKEN_IN:
828 4d611c9a pbrook
        if (p->devep == 1) {
829 68735b6c Kevin O'Connor
            int64_t curtime = qemu_get_clock(vm_clock);
830 68735b6c Kevin O'Connor
            if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
831 117b3ae6 pbrook
                return USB_RET_NAK;
832 68735b6c Kevin O'Connor
            usb_hid_set_next_idle(s, curtime);
833 117b3ae6 pbrook
            s->changed = 0;
834 47b2d338 balrog
            if (s->kind == USB_MOUSE)
835 117b3ae6 pbrook
                ret = usb_mouse_poll(s, p->data, p->len);
836 47b2d338 balrog
            else if (s->kind == USB_TABLET)
837 117b3ae6 pbrook
                ret = usb_tablet_poll(s, p->data, p->len);
838 47b2d338 balrog
            else if (s->kind == USB_KEYBOARD)
839 47b2d338 balrog
                ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
840 59ae540c bellard
        } else {
841 59ae540c bellard
            goto fail;
842 59ae540c bellard
        }
843 59ae540c bellard
        break;
844 59ae540c bellard
    case USB_TOKEN_OUT:
845 59ae540c bellard
    default:
846 59ae540c bellard
    fail:
847 59ae540c bellard
        ret = USB_RET_STALL;
848 59ae540c bellard
        break;
849 59ae540c bellard
    }
850 59ae540c bellard
    return ret;
851 59ae540c bellard
}
852 59ae540c bellard
853 47b2d338 balrog
static void usb_hid_handle_destroy(USBDevice *dev)
854 059809e4 bellard
{
855 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
856 059809e4 bellard
857 47b2d338 balrog
    if (s->kind != USB_KEYBOARD)
858 47b2d338 balrog
        qemu_remove_mouse_event_handler(s->ptr.eh_entry);
859 47b2d338 balrog
    /* TODO: else */
860 059809e4 bellard
}
861 059809e4 bellard
862 806b6024 Gerd Hoffmann
static int usb_hid_initfn(USBDevice *dev, int kind)
863 09b26c5e bellard
{
864 806b6024 Gerd Hoffmann
    USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
865 09b26c5e bellard
    s->dev.speed = USB_SPEED_FULL;
866 806b6024 Gerd Hoffmann
    s->kind = kind;
867 6fef28ee Anthony Liguori
868 6fef28ee Anthony Liguori
    if (s->kind == USB_MOUSE) {
869 6fef28ee Anthony Liguori
        s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
870 6fef28ee Anthony Liguori
                                                       0, "QEMU USB Mouse");
871 6fef28ee Anthony Liguori
    } else if (s->kind == USB_TABLET) {
872 6fef28ee Anthony Liguori
        s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
873 6fef28ee Anthony Liguori
                                                       1, "QEMU USB Tablet");
874 6fef28ee Anthony Liguori
    }
875 6fef28ee Anthony Liguori
        
876 117b3ae6 pbrook
    /* Force poll routine to be run and grab input the first time.  */
877 117b3ae6 pbrook
    s->changed = 1;
878 806b6024 Gerd Hoffmann
    return 0;
879 09b26c5e bellard
}
880 09b26c5e bellard
881 806b6024 Gerd Hoffmann
static int usb_tablet_initfn(USBDevice *dev)
882 59ae540c bellard
{
883 806b6024 Gerd Hoffmann
    return usb_hid_initfn(dev, USB_TABLET);
884 806b6024 Gerd Hoffmann
}
885 59ae540c bellard
886 806b6024 Gerd Hoffmann
static int usb_mouse_initfn(USBDevice *dev)
887 806b6024 Gerd Hoffmann
{
888 806b6024 Gerd Hoffmann
    return usb_hid_initfn(dev, USB_MOUSE);
889 806b6024 Gerd Hoffmann
}
890 59ae540c bellard
891 806b6024 Gerd Hoffmann
static int usb_keyboard_initfn(USBDevice *dev)
892 806b6024 Gerd Hoffmann
{
893 806b6024 Gerd Hoffmann
    return usb_hid_initfn(dev, USB_KEYBOARD);
894 806b6024 Gerd Hoffmann
}
895 59ae540c bellard
896 47e699dc balrog
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
897 47e699dc balrog
{
898 47e699dc balrog
    USBHIDState *s = (USBHIDState *)dev;
899 47e699dc balrog
900 47e699dc balrog
    s->datain_opaque = opaque;
901 47e699dc balrog
    s->datain = datain;
902 47e699dc balrog
}
903 806b6024 Gerd Hoffmann
904 806b6024 Gerd Hoffmann
static struct USBDeviceInfo hid_info[] = {
905 806b6024 Gerd Hoffmann
    {
906 06384698 Markus Armbruster
        .product_desc   = "QEMU USB Tablet",
907 556cd098 Markus Armbruster
        .qdev.name      = "usb-tablet",
908 fa7c70c3 Gerd Hoffmann
        .usbdevice_name = "tablet",
909 806b6024 Gerd Hoffmann
        .qdev.size      = sizeof(USBHIDState),
910 806b6024 Gerd Hoffmann
        .init           = usb_tablet_initfn,
911 806b6024 Gerd Hoffmann
        .handle_packet  = usb_generic_handle_packet,
912 806b6024 Gerd Hoffmann
        .handle_reset   = usb_mouse_handle_reset,
913 806b6024 Gerd Hoffmann
        .handle_control = usb_hid_handle_control,
914 806b6024 Gerd Hoffmann
        .handle_data    = usb_hid_handle_data,
915 806b6024 Gerd Hoffmann
        .handle_destroy = usb_hid_handle_destroy,
916 806b6024 Gerd Hoffmann
    },{
917 06384698 Markus Armbruster
        .product_desc   = "QEMU USB Mouse",
918 556cd098 Markus Armbruster
        .qdev.name      = "usb-mouse",
919 fa7c70c3 Gerd Hoffmann
        .usbdevice_name = "mouse",
920 806b6024 Gerd Hoffmann
        .qdev.size      = sizeof(USBHIDState),
921 806b6024 Gerd Hoffmann
        .init           = usb_mouse_initfn,
922 806b6024 Gerd Hoffmann
        .handle_packet  = usb_generic_handle_packet,
923 806b6024 Gerd Hoffmann
        .handle_reset   = usb_mouse_handle_reset,
924 806b6024 Gerd Hoffmann
        .handle_control = usb_hid_handle_control,
925 806b6024 Gerd Hoffmann
        .handle_data    = usb_hid_handle_data,
926 806b6024 Gerd Hoffmann
        .handle_destroy = usb_hid_handle_destroy,
927 806b6024 Gerd Hoffmann
    },{
928 06384698 Markus Armbruster
        .product_desc   = "QEMU USB Keyboard",
929 556cd098 Markus Armbruster
        .qdev.name      = "usb-kbd",
930 fa7c70c3 Gerd Hoffmann
        .usbdevice_name = "keyboard",
931 806b6024 Gerd Hoffmann
        .qdev.size      = sizeof(USBHIDState),
932 806b6024 Gerd Hoffmann
        .init           = usb_keyboard_initfn,
933 806b6024 Gerd Hoffmann
        .handle_packet  = usb_generic_handle_packet,
934 806b6024 Gerd Hoffmann
        .handle_reset   = usb_keyboard_handle_reset,
935 806b6024 Gerd Hoffmann
        .handle_control = usb_hid_handle_control,
936 806b6024 Gerd Hoffmann
        .handle_data    = usb_hid_handle_data,
937 806b6024 Gerd Hoffmann
        .handle_destroy = usb_hid_handle_destroy,
938 806b6024 Gerd Hoffmann
    },{
939 806b6024 Gerd Hoffmann
        /* end of list */
940 806b6024 Gerd Hoffmann
    }
941 806b6024 Gerd Hoffmann
};
942 806b6024 Gerd Hoffmann
943 806b6024 Gerd Hoffmann
static void usb_hid_register_devices(void)
944 806b6024 Gerd Hoffmann
{
945 806b6024 Gerd Hoffmann
    usb_qdev_register_many(hid_info);
946 806b6024 Gerd Hoffmann
}
947 806b6024 Gerd Hoffmann
device_init(usb_hid_register_devices)