Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ 3b46e624

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