Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ 78ae820c

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