usb-hid.c 26.7 KB
Newer Older
B
bellard 已提交
1 2
/*
 * QEMU USB HID devices
3
 *
B
bellard 已提交
4
 * Copyright (c) 2005 Fabrice Bellard
B
balrog 已提交
5
 * Copyright (c) 2007 OpenMoko, Inc.  (andrew@openedhand.com)
6
 *
B
bellard 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
P
pbrook 已提交
25 26 27
#include "hw.h"
#include "console.h"
#include "usb.h"
B
bellard 已提交
28 29 30 31 32

/* HID interface requests */
#define GET_REPORT   0xa101
#define GET_IDLE     0xa102
#define GET_PROTOCOL 0xa103
B
balrog 已提交
33
#define SET_REPORT   0x2109
B
bellard 已提交
34 35 36
#define SET_IDLE     0x210a
#define SET_PROTOCOL 0x210b

B
balrog 已提交
37 38 39 40 41 42 43 44
/* HID descriptor types */
#define USB_DT_HID    0x21
#define USB_DT_REPORT 0x22
#define USB_DT_PHY    0x23

#define USB_MOUSE     1
#define USB_TABLET    2
#define USB_KEYBOARD  3
45

B
bellard 已提交
46 47
typedef struct USBMouseState {
    int dx, dy, dz, buttons_state;
48 49
    int x, y;
    int mouse_grabbed;
50
    QEMUPutMouseEntry *eh_entry;
B
bellard 已提交
51 52
} USBMouseState;

B
balrog 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
typedef struct USBKeyboardState {
    uint16_t modifiers;
    uint8_t leds;
    uint8_t key[16];
    int keys;
} USBKeyboardState;

typedef struct USBHIDState {
    USBDevice dev;
    union {
        USBMouseState ptr;
        USBKeyboardState kbd;
    };
    int kind;
    int protocol;
    int idle;
69
    int changed;
B
balrog 已提交
70 71
} USBHIDState;

B
bellard 已提交
72 73 74 75
/* mostly the same values as the Bochs USB Mouse device */
static const uint8_t qemu_mouse_dev_descriptor[] = {
	0x12,       /*  u8 bLength; */
	0x01,       /*  u8 bDescriptorType; Device */
76
	0x00, 0x01, /*  u16 bcdUSB; v1.0 */
B
bellard 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

	0x00,	    /*  u8  bDeviceClass; */
	0x00,	    /*  u8  bDeviceSubClass; */
	0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */
	0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */

	0x27, 0x06, /*  u16 idVendor; */
 	0x01, 0x00, /*  u16 idProduct; */
	0x00, 0x00, /*  u16 bcdDevice */

	0x03,       /*  u8  iManufacturer; */
	0x02,       /*  u8  iProduct; */
	0x01,       /*  u8  iSerialNumber; */
	0x01        /*  u8  bNumConfigurations; */
};

static const uint8_t qemu_mouse_config_descriptor[] = {
	/* one configuration */
	0x09,       /*  u8  bLength; */
	0x02,       /*  u8  bDescriptorType; Configuration */
	0x22, 0x00, /*  u16 wTotalLength; */
	0x01,       /*  u8  bNumInterfaces; (1) */
	0x01,       /*  u8  bConfigurationValue; */
	0x04,       /*  u8  iConfiguration; */
101
	0xa0,       /*  u8  bmAttributes;
B
bellard 已提交
102 103 104 105 106
				 Bit 7: must be set,
				     6: Self-powered,
				     5: Remote wakeup,
				     4..0: resvd */
	50,         /*  u8  MaxPower; */
107

B
bellard 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
	/* USB 1.1:
	 * USB 2.0, single TT organization (mandatory):
	 *	one interface, protocol 0
	 *
	 * USB 2.0, multiple TT organization (optional):
	 *	two interfaces, protocols 1 (like single TT)
	 *	and 2 (multiple TT mode) ... config is
	 *	sometimes settable
	 *	NOT IMPLEMENTED
	 */

	/* one interface */
	0x09,       /*  u8  if_bLength; */
	0x04,       /*  u8  if_bDescriptorType; Interface */
	0x00,       /*  u8  if_bInterfaceNumber; */
	0x00,       /*  u8  if_bAlternateSetting; */
	0x01,       /*  u8  if_bNumEndpoints; */
	0x03,       /*  u8  if_bInterfaceClass; */
	0x01,       /*  u8  if_bInterfaceSubClass; */
	0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
B
balrog 已提交
128
	0x07,       /*  u8  if_iInterface; */
129

130 131 132 133 134 135 136 137 138
        /* HID descriptor */
        0x09,        /*  u8  bLength; */
        0x21,        /*  u8 bDescriptorType; */
        0x01, 0x00,  /*  u16 HID_class */
        0x00,        /*  u8 country_code */
        0x01,        /*  u8 num_descriptors */
        0x22,        /*  u8 type; Report */
        50, 0,       /*  u16 len */

B
bellard 已提交
139 140 141 142 143 144 145
	/* one endpoint (status change endpoint) */
	0x07,       /*  u8  ep_bLength; */
	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
 	0x03,       /*  u8  ep_bmAttributes; Interrupt */
 	0x03, 0x00, /*  u16 ep_wMaxPacketSize; */
	0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
146 147 148 149 150 151 152 153 154
};

static const uint8_t qemu_tablet_config_descriptor[] = {
	/* one configuration */
	0x09,       /*  u8  bLength; */
	0x02,       /*  u8  bDescriptorType; Configuration */
	0x22, 0x00, /*  u16 wTotalLength; */
	0x01,       /*  u8  bNumInterfaces; (1) */
	0x01,       /*  u8  bConfigurationValue; */
B
balrog 已提交
155
	0x05,       /*  u8  iConfiguration; */
156
	0xa0,       /*  u8  bmAttributes;
157 158 159 160 161
				 Bit 7: must be set,
				     6: Self-powered,
				     5: Remote wakeup,
				     4..0: resvd */
	50,         /*  u8  MaxPower; */
162

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
	/* USB 1.1:
	 * USB 2.0, single TT organization (mandatory):
	 *	one interface, protocol 0
	 *
	 * USB 2.0, multiple TT organization (optional):
	 *	two interfaces, protocols 1 (like single TT)
	 *	and 2 (multiple TT mode) ... config is
	 *	sometimes settable
	 *	NOT IMPLEMENTED
	 */

	/* one interface */
	0x09,       /*  u8  if_bLength; */
	0x04,       /*  u8  if_bDescriptorType; Interface */
	0x00,       /*  u8  if_bInterfaceNumber; */
	0x00,       /*  u8  if_bAlternateSetting; */
	0x01,       /*  u8  if_bNumEndpoints; */
	0x03,       /*  u8  if_bInterfaceClass; */
	0x01,       /*  u8  if_bInterfaceSubClass; */
	0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
B
balrog 已提交
183
	0x07,       /*  u8  if_iInterface; */
B
bellard 已提交
184 185 186 187 188 189 190 191

        /* HID descriptor */
        0x09,        /*  u8  bLength; */
        0x21,        /*  u8 bDescriptorType; */
        0x01, 0x00,  /*  u16 HID_class */
        0x00,        /*  u8 country_code */
        0x01,        /*  u8 num_descriptors */
        0x22,        /*  u8 type; Report */
192 193 194 195 196 197 198 199
        74, 0,       /*  u16 len */

	/* one endpoint (status change endpoint) */
	0x07,       /*  u8  ep_bLength; */
	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
 	0x03,       /*  u8  ep_bmAttributes; Interrupt */
 	0x08, 0x00, /*  u16 ep_wMaxPacketSize; */
B
bellard 已提交
200
	0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
B
bellard 已提交
201 202
};

B
balrog 已提交
203 204 205 206 207 208 209 210
static const uint8_t qemu_keyboard_config_descriptor[] = {
    /* one configuration */
    0x09,		/*  u8  bLength; */
    USB_DT_CONFIG,	/*  u8  bDescriptorType; Configuration */
    0x22, 0x00,		/*  u16 wTotalLength; */
    0x01,		/*  u8  bNumInterfaces; (1) */
    0x01,		/*  u8  bConfigurationValue; */
    0x06,		/*  u8  iConfiguration; */
211
    0xa0,		/*  u8  bmAttributes;
B
balrog 已提交
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
				Bit 7: must be set,
				    6: Self-powered,
				    5: Remote wakeup,
				    4..0: resvd */
    0x32,		/*  u8  MaxPower; */

    /* USB 1.1:
     * USB 2.0, single TT organization (mandatory):
     *	one interface, protocol 0
     *
     * USB 2.0, multiple TT organization (optional):
     *	two interfaces, protocols 1 (like single TT)
     *	and 2 (multiple TT mode) ... config is
     *	sometimes settable
     *	NOT IMPLEMENTED
     */

    /* one interface */
    0x09,		/*  u8  if_bLength; */
    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; Interface */
    0x00,		/*  u8  if_bInterfaceNumber; */
    0x00,		/*  u8  if_bAlternateSetting; */
    0x01,		/*  u8  if_bNumEndpoints; */
    0x03,		/*  u8  if_bInterfaceClass; HID */
    0x01,		/*  u8  if_bInterfaceSubClass; Boot */
    0x01,		/*  u8  if_bInterfaceProtocol; Keyboard */
    0x07,		/*  u8  if_iInterface; */

    /* HID descriptor */
    0x09,		/*  u8  bLength; */
    USB_DT_HID,		/*  u8  bDescriptorType; */
    0x11, 0x01,		/*  u16 HID_class */
    0x00,		/*  u8  country_code */
    0x01,		/*  u8  num_descriptors */
    USB_DT_REPORT,	/*  u8  type; Report */
    0x3f, 0x00,		/*  u16 len */

    /* one endpoint (status change endpoint) */
    0x07,		/*  u8  ep_bLength; */
    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; Endpoint */
    USB_DIR_IN | 0x01,	/*  u8  ep_bEndpointAddress; IN Endpoint 1 */
    0x03,		/*  u8  ep_bmAttributes; Interrupt */
    0x08, 0x00,		/*  u16 ep_wMaxPacketSize; */
    0x0a,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
};

B
bellard 已提交
258
static const uint8_t qemu_mouse_hid_report_descriptor[] = {
259
    0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01,
B
bellard 已提交
260
    0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03,
261
    0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01,
B
bellard 已提交
262
    0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01,
263
    0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81,
B
bellard 已提交
264
    0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06,
265 266 267
    0x05, 0x01, 0x09, 0x38, 0x15, 0x81, 0x25, 0x7F,
    0x35, 0x00, 0x45, 0x00, 0x75, 0x08, 0x95, 0x01,
    0x81, 0x02, 0xC0, 0xC0,
B
bellard 已提交
268 269
};

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
static const uint8_t qemu_tablet_hid_report_descriptor[] = {
        0x05, 0x01, /* Usage Page Generic Desktop */
        0x09, 0x01, /* Usage Mouse */
        0xA1, 0x01, /* Collection Application */
        0x09, 0x01, /* Usage Pointer */
        0xA1, 0x00, /* Collection Physical */
        0x05, 0x09, /* Usage Page Button */
        0x19, 0x01, /* Usage Minimum Button 1 */
        0x29, 0x03, /* Usage Maximum Button 3 */
        0x15, 0x00, /* Logical Minimum 0 */
        0x25, 0x01, /* Logical Maximum 1 */
        0x95, 0x03, /* Report Count 3 */
        0x75, 0x01, /* Report Size 1 */
        0x81, 0x02, /* Input (Data, Var, Abs) */
        0x95, 0x01, /* Report Count 1 */
        0x75, 0x05, /* Report Size 5 */
        0x81, 0x01, /* Input (Cnst, Var, Abs) */
        0x05, 0x01, /* Usage Page Generic Desktop */
        0x09, 0x30, /* Usage X */
        0x09, 0x31, /* Usage Y */
        0x15, 0x00, /* Logical Minimum 0 */
        0x26, 0xFF, 0x7F, /* Logical Maximum 0x7fff */
        0x35, 0x00, /* Physical Minimum 0 */
        0x46, 0xFE, 0x7F, /* Physical Maximum 0x7fff */
        0x75, 0x10, /* Report Size 16 */
        0x95, 0x02, /* Report Count 2 */
        0x81, 0x02, /* Input (Data, Var, Abs) */
        0x05, 0x01, /* Usage Page Generic Desktop */
        0x09, 0x38, /* Usage Wheel */
        0x15, 0x81, /* Logical Minimum -127 */
        0x25, 0x7F, /* Logical Maximum 127 */
        0x35, 0x00, /* Physical Minimum 0 (same as logical) */
        0x45, 0x00, /* Physical Maximum 0 (same as logical) */
        0x75, 0x08, /* Report Size 8 */
        0x95, 0x01, /* Report Count 1 */
        0x81, 0x02, /* Input (Data, Var, Rel) */
        0xC0,       /* End Collection */
        0xC0,       /* End Collection */
};

B
balrog 已提交
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
    0x05, 0x01,		/* Usage Page (Generic Desktop) */
    0x09, 0x06,		/* Usage (Keyboard) */
    0xa1, 0x01,		/* Collection (Application) */
    0x75, 0x01,		/*   Report Size (1) */
    0x95, 0x08,		/*   Report Count (8) */
    0x05, 0x07,		/*   Usage Page (Key Codes) */
    0x19, 0xe0,		/*   Usage Minimum (224) */
    0x29, 0xe7,		/*   Usage Maximum (231) */
    0x15, 0x00,		/*   Logical Minimum (0) */
    0x25, 0x01,		/*   Logical Maximum (1) */
    0x81, 0x02,		/*   Input (Data, Variable, Absolute) */
    0x95, 0x01,		/*   Report Count (1) */
    0x75, 0x08,		/*   Report Size (8) */
    0x81, 0x01,		/*   Input (Constant) */
    0x95, 0x05,		/*   Report Count (5) */
    0x75, 0x01,		/*   Report Size (1) */
    0x05, 0x08,		/*   Usage Page (LEDs) */
    0x19, 0x01,		/*   Usage Minimum (1) */
    0x29, 0x05,		/*   Usage Maximum (5) */
    0x91, 0x02,		/*   Output (Data, Variable, Absolute) */
    0x95, 0x01,		/*   Report Count (1) */
    0x75, 0x03,		/*   Report Size (3) */
    0x91, 0x01,		/*   Output (Constant) */
    0x95, 0x06,		/*   Report Count (6) */
    0x75, 0x08,		/*   Report Size (8) */
    0x15, 0x00,		/*   Logical Minimum (0) */
    0x25, 0xff,		/*   Logical Maximum (255) */
    0x05, 0x07,		/*   Usage Page (Key Codes) */
    0x19, 0x00,		/*   Usage Minimum (0) */
    0x29, 0xff,		/*   Usage Maximum (255) */
    0x81, 0x00,		/*   Input (Data, Array) */
    0xc0,		/* End Collection */
};

#define USB_HID_USAGE_ERROR_ROLLOVER	0x01
#define USB_HID_USAGE_POSTFAIL		0x02
#define USB_HID_USAGE_ERROR_UNDEFINED	0x03

/* Indices are QEMU keycodes, values are from HID Usage Table.  Indices
 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d.  */
static const uint8_t usb_hid_usage_keys[0x100] = {
    0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
    0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
    0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
    0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
    0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
    0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
    0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
    0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
    0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
    0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
    0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
    0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
    0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,

    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
    0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
    0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
    0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

B
bellard 已提交
387 388 389
static void usb_mouse_event(void *opaque,
                            int dx1, int dy1, int dz1, int buttons_state)
{
390 391
    USBHIDState *hs = opaque;
    USBMouseState *s = &hs->ptr;
B
bellard 已提交
392 393 394 395 396

    s->dx += dx1;
    s->dy += dy1;
    s->dz += dz1;
    s->buttons_state = buttons_state;
397
    hs->changed = 1;
B
bellard 已提交
398 399
}

400 401 402
static void usb_tablet_event(void *opaque,
			     int x, int y, int dz, int buttons_state)
{
403 404
    USBHIDState *hs = opaque;
    USBMouseState *s = &hs->ptr;
405 406 407 408 409

    s->x = x;
    s->y = y;
    s->dz += dz;
    s->buttons_state = buttons_state;
410
    hs->changed = 1;
411 412
}

B
balrog 已提交
413 414
static void usb_keyboard_event(void *opaque, int keycode)
{
415 416
    USBHIDState *hs = opaque;
    USBKeyboardState *s = &hs->kbd;
B
balrog 已提交
417 418 419 420 421 422 423
    uint8_t hid_code, key;
    int i;

    key = keycode & 0x7f;
    hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
    s->modifiers &= ~(1 << 8);

424 425
    hs->changed = 1;

B
balrog 已提交
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
    switch (hid_code) {
    case 0x00:
        return;

    case 0xe0:
        if (s->modifiers & (1 << 9)) {
            s->modifiers ^= 3 << 8;
            return;
        }
    case 0xe1 ... 0xe7:
        if (keycode & (1 << 7)) {
            s->modifiers &= ~(1 << (hid_code & 0x0f));
            return;
        }
    case 0xe8 ... 0xef:
        s->modifiers |= 1 << (hid_code & 0x0f);
        return;
    }

    if (keycode & (1 << 7)) {
        for (i = s->keys - 1; i >= 0; i --)
            if (s->key[i] == hid_code) {
                s->key[i] = s->key[-- s->keys];
                s->key[s->keys] = 0x00;
                return;
            }
    } else {
        for (i = s->keys - 1; i >= 0; i --)
            if (s->key[i] == hid_code)
                return;
        if (s->keys < sizeof(s->key))
            s->key[s->keys ++] = hid_code;
    }
}

B
bellard 已提交
461 462 463 464 465 466 467 468 469 470
static inline int int_clamp(int val, int vmin, int vmax)
{
    if (val < vmin)
        return vmin;
    else if (val > vmax)
        return vmax;
    else
        return val;
}

471
static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
B
bellard 已提交
472 473
{
    int dx, dy, dz, b, l;
474
    USBMouseState *s = &hs->ptr;
B
bellard 已提交
475

476
    if (!s->mouse_grabbed) {
477
	s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, hs,
478
                                                  0, "QEMU USB Mouse");
479 480
	s->mouse_grabbed = 1;
    }
481

B
bellard 已提交
482 483 484 485 486 487 488
    dx = int_clamp(s->dx, -128, 127);
    dy = int_clamp(s->dy, -128, 127);
    dz = int_clamp(s->dz, -128, 127);

    s->dx -= dx;
    s->dy -= dy;
    s->dz -= dz;
489

B
bellard 已提交
490 491 492 493 494 495 496
    b = 0;
    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
        b |= 0x01;
    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
        b |= 0x02;
    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
        b |= 0x04;
497

B
bellard 已提交
498 499 500 501 502 503 504 505 506 507 508
    buf[0] = b;
    buf[1] = dx;
    buf[2] = dy;
    l = 3;
    if (len >= 4) {
        buf[3] = dz;
        l = 4;
    }
    return l;
}

509
static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
510 511
{
    int dz, b, l;
512
    USBMouseState *s = &hs->ptr;
513 514

    if (!s->mouse_grabbed) {
515
	s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs,
516
                                                  1, "QEMU USB Tablet");
517 518
	s->mouse_grabbed = 1;
    }
519

520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
    dz = int_clamp(s->dz, -128, 127);
    s->dz -= dz;

    /* Appears we have to invert the wheel direction */
    dz = 0 - dz;
    b = 0;
    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
        b |= 0x01;
    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
        b |= 0x02;
    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
        b |= 0x04;

    buf[0] = b;
    buf[1] = s->x & 0xff;
    buf[2] = s->x >> 8;
    buf[3] = s->y & 0xff;
    buf[4] = s->y >> 8;
    buf[5] = dz;
    l = 6;

    return l;
}

B
balrog 已提交
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
{
    if (len < 2)
        return 0;

    buf[0] = s->modifiers & 0xff;
    buf[1] = 0;
    if (s->keys > 6)
        memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
    else
        memcpy(buf + 2, s->key, MIN(8, len) - 2);

    return MIN(8, len);
}

static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
{
    if (len > 0) {
        /* 0x01: Num Lock LED
         * 0x02: Caps Lock LED
         * 0x04: Scroll Lock LED
         * 0x08: Compose LED
         * 0x10: Kana LED */
        s->leds = buf[0];
    }
    return 0;
}

B
bellard 已提交
572
static void usb_mouse_handle_reset(USBDevice *dev)
B
bellard 已提交
573
{
B
balrog 已提交
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
    USBHIDState *s = (USBHIDState *)dev;

    s->ptr.dx = 0;
    s->ptr.dy = 0;
    s->ptr.dz = 0;
    s->ptr.x = 0;
    s->ptr.y = 0;
    s->ptr.buttons_state = 0;
    s->protocol = 1;
}

static void usb_keyboard_handle_reset(USBDevice *dev)
{
    USBHIDState *s = (USBHIDState *)dev;

589
    qemu_add_kbd_event_handler(usb_keyboard_event, s);
B
balrog 已提交
590
    s->protocol = 1;
B
bellard 已提交
591 592
}

B
balrog 已提交
593
static int usb_hid_handle_control(USBDevice *dev, int request, int value,
B
bellard 已提交
594 595
                                  int index, int length, uint8_t *data)
{
B
balrog 已提交
596
    USBHIDState *s = (USBHIDState *)dev;
597
    int ret = 0;
B
bellard 已提交
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628

    switch(request) {
    case DeviceRequest | USB_REQ_GET_STATUS:
        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
        data[1] = 0x00;
        ret = 2;
        break;
    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
            dev->remote_wakeup = 0;
        } else {
            goto fail;
        }
        ret = 0;
        break;
    case DeviceOutRequest | USB_REQ_SET_FEATURE:
        if (value == USB_DEVICE_REMOTE_WAKEUP) {
            dev->remote_wakeup = 1;
        } else {
            goto fail;
        }
        ret = 0;
        break;
    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
        dev->addr = value;
        ret = 0;
        break;
    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
        switch(value >> 8) {
        case USB_DT_DEVICE:
629
            memcpy(data, qemu_mouse_dev_descriptor,
B
bellard 已提交
630 631 632 633
                   sizeof(qemu_mouse_dev_descriptor));
            ret = sizeof(qemu_mouse_dev_descriptor);
            break;
        case USB_DT_CONFIG:
634
	    if (s->kind == USB_MOUSE) {
635
		memcpy(data, qemu_mouse_config_descriptor,
636 637 638
		       sizeof(qemu_mouse_config_descriptor));
		ret = sizeof(qemu_mouse_config_descriptor);
	    } else if (s->kind == USB_TABLET) {
639
		memcpy(data, qemu_tablet_config_descriptor,
640 641
		       sizeof(qemu_tablet_config_descriptor));
		ret = sizeof(qemu_tablet_config_descriptor);
B
balrog 已提交
642
            } else if (s->kind == USB_KEYBOARD) {
643
                memcpy(data, qemu_keyboard_config_descriptor,
B
balrog 已提交
644 645 646
                       sizeof(qemu_keyboard_config_descriptor));
                ret = sizeof(qemu_keyboard_config_descriptor);
            }
B
bellard 已提交
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663
            break;
        case USB_DT_STRING:
            switch(value & 0xff) {
            case 0:
                /* language ids */
                data[0] = 4;
                data[1] = 3;
                data[2] = 0x09;
                data[3] = 0x04;
                ret = 4;
                break;
            case 1:
                /* serial number */
                ret = set_usb_string(data, "1");
                break;
            case 2:
                /* product description */
B
balrog 已提交
664
                ret = set_usb_string(data, s->dev.devname);
B
bellard 已提交
665 666 667 668 669 670 671 672 673
                break;
            case 3:
                /* vendor description */
                ret = set_usb_string(data, "QEMU " QEMU_VERSION);
                break;
            case 4:
                ret = set_usb_string(data, "HID Mouse");
                break;
            case 5:
B
balrog 已提交
674 675 676 677 678 679
                ret = set_usb_string(data, "HID Tablet");
                break;
            case 6:
                ret = set_usb_string(data, "HID Keyboard");
                break;
            case 7:
B
bellard 已提交
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
                ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
                break;
            default:
                goto fail;
            }
            break;
        default:
            goto fail;
        }
        break;
    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
        data[0] = 1;
        ret = 1;
        break;
    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
        ret = 0;
        break;
    case DeviceRequest | USB_REQ_GET_INTERFACE:
        data[0] = 0;
        ret = 1;
        break;
    case DeviceOutRequest | USB_REQ_SET_INTERFACE:
        ret = 0;
        break;
        /* hid specific requests */
    case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
        switch(value >> 8) {
        case 0x22:
708
	    if (s->kind == USB_MOUSE) {
709
		memcpy(data, qemu_mouse_hid_report_descriptor,
710 711 712
		       sizeof(qemu_mouse_hid_report_descriptor));
		ret = sizeof(qemu_mouse_hid_report_descriptor);
	    } else if (s->kind == USB_TABLET) {
713
		memcpy(data, qemu_tablet_hid_report_descriptor,
714 715
		       sizeof(qemu_tablet_hid_report_descriptor));
		ret = sizeof(qemu_tablet_hid_report_descriptor);
B
balrog 已提交
716
            } else if (s->kind == USB_KEYBOARD) {
717
                memcpy(data, qemu_keyboard_hid_report_descriptor,
B
balrog 已提交
718 719 720 721
                       sizeof(qemu_keyboard_hid_report_descriptor));
                ret = sizeof(qemu_keyboard_hid_report_descriptor);
            }
            break;
B
bellard 已提交
722 723 724 725 726
        default:
            goto fail;
        }
        break;
    case GET_REPORT:
727
	if (s->kind == USB_MOUSE)
728
            ret = usb_mouse_poll(s, data, length);
729
	else if (s->kind == USB_TABLET)
730
            ret = usb_tablet_poll(s, data, length);
B
balrog 已提交
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754
        else if (s->kind == USB_KEYBOARD)
            ret = usb_keyboard_poll(&s->kbd, data, length);
        break;
    case SET_REPORT:
        if (s->kind == USB_KEYBOARD)
            ret = usb_keyboard_write(&s->kbd, data, length);
        else
            goto fail;
        break;
    case GET_PROTOCOL:
        if (s->kind != USB_KEYBOARD)
            goto fail;
        ret = 1;
        data[0] = s->protocol;
        break;
    case SET_PROTOCOL:
        if (s->kind != USB_KEYBOARD)
            goto fail;
        ret = 0;
        s->protocol = value;
        break;
    case GET_IDLE:
        ret = 1;
        data[0] = s->idle;
B
bellard 已提交
755 756
        break;
    case SET_IDLE:
B
balrog 已提交
757
        s->idle = value;
B
bellard 已提交
758 759 760 761 762 763 764 765 766 767
        ret = 0;
        break;
    default:
    fail:
        ret = USB_RET_STALL;
        break;
    }
    return ret;
}

B
balrog 已提交
768
static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
B
bellard 已提交
769
{
B
balrog 已提交
770
    USBHIDState *s = (USBHIDState *)dev;
771
    int ret = 0;
B
bellard 已提交
772

P
pbrook 已提交
773
    switch(p->pid) {
B
bellard 已提交
774
    case USB_TOKEN_IN:
P
pbrook 已提交
775
        if (p->devep == 1) {
776 777 778 779
            /* TODO: Implement finite idle delays.  */
            if (!(s->changed || s->idle))
                return USB_RET_NAK;
            s->changed = 0;
B
balrog 已提交
780
            if (s->kind == USB_MOUSE)
781
                ret = usb_mouse_poll(s, p->data, p->len);
B
balrog 已提交
782
            else if (s->kind == USB_TABLET)
783
                ret = usb_tablet_poll(s, p->data, p->len);
B
balrog 已提交
784 785
            else if (s->kind == USB_KEYBOARD)
                ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
B
bellard 已提交
786 787 788 789 790 791 792 793 794 795 796 797 798
        } else {
            goto fail;
        }
        break;
    case USB_TOKEN_OUT:
    default:
    fail:
        ret = USB_RET_STALL;
        break;
    }
    return ret;
}

B
balrog 已提交
799
static void usb_hid_handle_destroy(USBDevice *dev)
B
bellard 已提交
800
{
B
balrog 已提交
801
    USBHIDState *s = (USBHIDState *)dev;
B
bellard 已提交
802

B
balrog 已提交
803 804 805
    if (s->kind != USB_KEYBOARD)
        qemu_remove_mouse_event_handler(s->ptr.eh_entry);
    /* TODO: else */
B
bellard 已提交
806 807 808
    qemu_free(s);
}

809 810
USBDevice *usb_tablet_init(void)
{
B
balrog 已提交
811
    USBHIDState *s;
812

B
balrog 已提交
813
    s = qemu_mallocz(sizeof(USBHIDState));
814 815 816 817 818 819
    if (!s)
        return NULL;
    s->dev.speed = USB_SPEED_FULL;
    s->dev.handle_packet = usb_generic_handle_packet;

    s->dev.handle_reset = usb_mouse_handle_reset;
B
balrog 已提交
820 821 822
    s->dev.handle_control = usb_hid_handle_control;
    s->dev.handle_data = usb_hid_handle_data;
    s->dev.handle_destroy = usb_hid_handle_destroy;
823
    s->kind = USB_TABLET;
824 825
    /* Force poll routine to be run and grab input the first time.  */
    s->changed = 1;
826

827 828
    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");

829 830 831
    return (USBDevice *)s;
}

B
bellard 已提交
832 833
USBDevice *usb_mouse_init(void)
{
B
balrog 已提交
834
    USBHIDState *s;
B
bellard 已提交
835

B
balrog 已提交
836
    s = qemu_mallocz(sizeof(USBHIDState));
B
bellard 已提交
837 838 839 840 841 842
    if (!s)
        return NULL;
    s->dev.speed = USB_SPEED_FULL;
    s->dev.handle_packet = usb_generic_handle_packet;

    s->dev.handle_reset = usb_mouse_handle_reset;
B
balrog 已提交
843 844 845
    s->dev.handle_control = usb_hid_handle_control;
    s->dev.handle_data = usb_hid_handle_data;
    s->dev.handle_destroy = usb_hid_handle_destroy;
846
    s->kind = USB_MOUSE;
847 848
    /* Force poll routine to be run and grab input the first time.  */
    s->changed = 1;
B
bellard 已提交
849

850 851
    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");

B
bellard 已提交
852 853
    return (USBDevice *)s;
}
B
balrog 已提交
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874

USBDevice *usb_keyboard_init(void)
{
    USBHIDState *s;

    s = qemu_mallocz(sizeof(USBHIDState));
    if (!s)
        return NULL;
    s->dev.speed = USB_SPEED_FULL;
    s->dev.handle_packet = usb_generic_handle_packet;

    s->dev.handle_reset = usb_keyboard_handle_reset;
    s->dev.handle_control = usb_hid_handle_control;
    s->dev.handle_data = usb_hid_handle_data;
    s->dev.handle_destroy = usb_hid_handle_destroy;
    s->kind = USB_KEYBOARD;

    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard");

    return (USBDevice *) s;
}