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