Revision 09b26c5e hw/usb-hid.c

b/hw/usb-hid.c
30 30
#define SET_IDLE     0x210a
31 31
#define SET_PROTOCOL 0x210b
32 32

  
33
#define USB_MOUSE  1
34
#define USB_TABLET 2
35

  
33 36
typedef struct USBMouseState {
34 37
    USBDevice dev;
35 38
    int dx, dy, dz, buttons_state;
39
    int x, y;
40
    int kind;
41
    int mouse_grabbed;
36 42
} USBMouseState;
37 43

  
38 44
/* mostly the same values as the Bochs USB Mouse device */
......
93 99
	0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
94 100
	0x05,       /*  u8  if_iInterface; */
95 101
     
102
        /* HID descriptor */
103
        0x09,        /*  u8  bLength; */
104
        0x21,        /*  u8 bDescriptorType; */
105
        0x01, 0x00,  /*  u16 HID_class */
106
        0x00,        /*  u8 country_code */
107
        0x01,        /*  u8 num_descriptors */
108
        0x22,        /*  u8 type; Report */
109
        50, 0,       /*  u16 len */
110

  
96 111
	/* one endpoint (status change endpoint) */
97 112
	0x07,       /*  u8  ep_bLength; */
98 113
	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
......
100 115
 	0x03,       /*  u8  ep_bmAttributes; Interrupt */
101 116
 	0x03, 0x00, /*  u16 ep_wMaxPacketSize; */
102 117
	0x0a,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
118
};
119

  
120
static const uint8_t qemu_tablet_config_descriptor[] = {
121
	/* one configuration */
122
	0x09,       /*  u8  bLength; */
123
	0x02,       /*  u8  bDescriptorType; Configuration */
124
	0x22, 0x00, /*  u16 wTotalLength; */
125
	0x01,       /*  u8  bNumInterfaces; (1) */
126
	0x01,       /*  u8  bConfigurationValue; */
127
	0x04,       /*  u8  iConfiguration; */
128
	0xa0,       /*  u8  bmAttributes; 
129
				 Bit 7: must be set,
130
				     6: Self-powered,
131
				     5: Remote wakeup,
132
				     4..0: resvd */
133
	50,         /*  u8  MaxPower; */
134
      
135
	/* USB 1.1:
136
	 * USB 2.0, single TT organization (mandatory):
137
	 *	one interface, protocol 0
138
	 *
139
	 * USB 2.0, multiple TT organization (optional):
140
	 *	two interfaces, protocols 1 (like single TT)
141
	 *	and 2 (multiple TT mode) ... config is
142
	 *	sometimes settable
143
	 *	NOT IMPLEMENTED
144
	 */
145

  
146
	/* one interface */
147
	0x09,       /*  u8  if_bLength; */
148
	0x04,       /*  u8  if_bDescriptorType; Interface */
149
	0x00,       /*  u8  if_bInterfaceNumber; */
150
	0x00,       /*  u8  if_bAlternateSetting; */
151
	0x01,       /*  u8  if_bNumEndpoints; */
152
	0x03,       /*  u8  if_bInterfaceClass; */
153
	0x01,       /*  u8  if_bInterfaceSubClass; */
154
	0x02,       /*  u8  if_bInterfaceProtocol; [usb1.1 or single tt] */
155
	0x05,       /*  u8  if_iInterface; */
103 156

  
104 157
        /* HID descriptor */
105 158
        0x09,        /*  u8  bLength; */
......
108 161
        0x00,        /*  u8 country_code */
109 162
        0x01,        /*  u8 num_descriptors */
110 163
        0x22,        /*  u8 type; Report */
111
        50, 0,       /*  u16 len */
164
        74, 0,       /*  u16 len */
165

  
166
	/* one endpoint (status change endpoint) */
167
	0x07,       /*  u8  ep_bLength; */
168
	0x05,       /*  u8  ep_bDescriptorType; Endpoint */
169
	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */
170
 	0x03,       /*  u8  ep_bmAttributes; Interrupt */
171
 	0x08, 0x00, /*  u16 ep_wMaxPacketSize; */
172
	0x03,       /*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
112 173
};
113 174

  
114 175
static const uint8_t qemu_mouse_hid_report_descriptor[] = {
......
121 182
    0xC0, 0xC0,
122 183
};
123 184

  
185
static const uint8_t qemu_tablet_hid_report_descriptor[] = {
186
        0x05, 0x01, /* Usage Page Generic Desktop */
187
        0x09, 0x01, /* Usage Mouse */
188
        0xA1, 0x01, /* Collection Application */
189
        0x09, 0x01, /* Usage Pointer */
190
        0xA1, 0x00, /* Collection Physical */
191
        0x05, 0x09, /* Usage Page Button */
192
        0x19, 0x01, /* Usage Minimum Button 1 */
193
        0x29, 0x03, /* Usage Maximum Button 3 */
194
        0x15, 0x00, /* Logical Minimum 0 */
195
        0x25, 0x01, /* Logical Maximum 1 */
196
        0x95, 0x03, /* Report Count 3 */
197
        0x75, 0x01, /* Report Size 1 */
198
        0x81, 0x02, /* Input (Data, Var, Abs) */
199
        0x95, 0x01, /* Report Count 1 */
200
        0x75, 0x05, /* Report Size 5 */
201
        0x81, 0x01, /* Input (Cnst, Var, Abs) */
202
        0x05, 0x01, /* Usage Page Generic Desktop */
203
        0x09, 0x30, /* Usage X */
204
        0x09, 0x31, /* Usage Y */
205
        0x15, 0x00, /* Logical Minimum 0 */
206
        0x26, 0xFF, 0x7F, /* Logical Maximum 0x7fff */
207
        0x35, 0x00, /* Physical Minimum 0 */
208
        0x46, 0xFE, 0x7F, /* Physical Maximum 0x7fff */
209
        0x75, 0x10, /* Report Size 16 */
210
        0x95, 0x02, /* Report Count 2 */
211
        0x81, 0x02, /* Input (Data, Var, Abs) */
212
        0x05, 0x01, /* Usage Page Generic Desktop */
213
        0x09, 0x38, /* Usage Wheel */
214
        0x15, 0x81, /* Logical Minimum -127 */
215
        0x25, 0x7F, /* Logical Maximum 127 */
216
        0x35, 0x00, /* Physical Minimum 0 (same as logical) */
217
        0x45, 0x00, /* Physical Maximum 0 (same as logical) */
218
        0x75, 0x08, /* Report Size 8 */
219
        0x95, 0x01, /* Report Count 1 */
220
        0x81, 0x02, /* Input (Data, Var, Rel) */
221
        0xC0,       /* End Collection */
222
        0xC0,       /* End Collection */
223
};
224

  
124 225
static void usb_mouse_event(void *opaque,
125 226
                            int dx1, int dy1, int dz1, int buttons_state)
126 227
{
......
132 233
    s->buttons_state = buttons_state;
133 234
}
134 235

  
236
static void usb_tablet_event(void *opaque,
237
			     int x, int y, int dz, int buttons_state)
238
{
239
    USBMouseState *s = opaque;
240

  
241
    s->x = x;
242
    s->y = y;
243
    s->dz += dz;
244
    s->buttons_state = buttons_state;
245
}
246

  
135 247
static inline int int_clamp(int val, int vmin, int vmax)
136 248
{
137 249
    if (val < vmin)
......
146 258
{
147 259
    int dx, dy, dz, b, l;
148 260

  
261
    if (!s->mouse_grabbed) {
262
	qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
263
	s->mouse_grabbed = 1;
264
    }
265
    
149 266
    dx = int_clamp(s->dx, -128, 127);
150 267
    dy = int_clamp(s->dy, -128, 127);
151 268
    dz = int_clamp(s->dz, -128, 127);
......
173 290
    return l;
174 291
}
175 292

  
293
static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
294
{
295
    int dz, b, l;
296

  
297
    if (!s->mouse_grabbed) {
298
	qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
299
	s->mouse_grabbed = 1;
300
    }
301
    
302
    dz = int_clamp(s->dz, -128, 127);
303
    s->dz -= dz;
304

  
305
    /* Appears we have to invert the wheel direction */
306
    dz = 0 - dz;
307
    b = 0;
308
    if (s->buttons_state & MOUSE_EVENT_LBUTTON)
309
        b |= 0x01;
310
    if (s->buttons_state & MOUSE_EVENT_RBUTTON)
311
        b |= 0x02;
312
    if (s->buttons_state & MOUSE_EVENT_MBUTTON)
313
        b |= 0x04;
314

  
315
    buf[0] = b;
316
    buf[1] = s->x & 0xff;
317
    buf[2] = s->x >> 8;
318
    buf[3] = s->y & 0xff;
319
    buf[4] = s->y >> 8;
320
    buf[5] = dz;
321
    l = 6;
322

  
323
    return l;
324
}
325

  
176 326
static void usb_mouse_handle_reset(USBDevice *dev)
177 327
{
178 328
    USBMouseState *s = (USBMouseState *)dev;
......
180 330
    s->dx = 0;
181 331
    s->dy = 0;
182 332
    s->dz = 0;
333
    s->x = 0;
334
    s->y = 0;
183 335
    s->buttons_state = 0;
184 336
}
185 337

  
......
187 339
                                  int index, int length, uint8_t *data)
188 340
{
189 341
    USBMouseState *s = (USBMouseState *)dev;
190
    int ret;
342
    int ret = 0;
191 343

  
192 344
    switch(request) {
193 345
    case DeviceRequest | USB_REQ_GET_STATUS:
......
224 376
            ret = sizeof(qemu_mouse_dev_descriptor);
225 377
            break;
226 378
        case USB_DT_CONFIG:
227
            memcpy(data, qemu_mouse_config_descriptor, 
228
                   sizeof(qemu_mouse_config_descriptor));
229
            ret = sizeof(qemu_mouse_config_descriptor);
379
	    if (s->kind == USB_MOUSE) {
380
		memcpy(data, qemu_mouse_config_descriptor, 
381
		       sizeof(qemu_mouse_config_descriptor));
382
		ret = sizeof(qemu_mouse_config_descriptor);
383
	    } else if (s->kind == USB_TABLET) {
384
		memcpy(data, qemu_tablet_config_descriptor, 
385
		       sizeof(qemu_tablet_config_descriptor));
386
		ret = sizeof(qemu_tablet_config_descriptor);
387
	    }		
230 388
            break;
231 389
        case USB_DT_STRING:
232 390
            switch(value & 0xff) {
......
244 402
                break;
245 403
            case 2:
246 404
                /* product description */
247
                ret = set_usb_string(data, "QEMU USB Mouse");
405
		if (s->kind == USB_MOUSE)
406
		    ret = set_usb_string(data, "QEMU USB Mouse");
407
		else if (s->kind == USB_TABLET)
408
		    ret = set_usb_string(data, "QEMU USB Tablet");
248 409
                break;
249 410
            case 3:
250 411
                /* vendor description */
......
282 443
    case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
283 444
        switch(value >> 8) {
284 445
        case 0x22:
285
            memcpy(data, qemu_mouse_hid_report_descriptor, 
286
                   sizeof(qemu_mouse_hid_report_descriptor));
287
            ret = sizeof(qemu_mouse_hid_report_descriptor);
288
            break;
446
	    if (s->kind == USB_MOUSE) {
447
		memcpy(data, qemu_mouse_hid_report_descriptor, 
448
		       sizeof(qemu_mouse_hid_report_descriptor));
449
		ret = sizeof(qemu_mouse_hid_report_descriptor);
450
	    } else if (s->kind == USB_TABLET) {
451
		memcpy(data, qemu_tablet_hid_report_descriptor, 
452
		       sizeof(qemu_tablet_hid_report_descriptor));
453
		ret = sizeof(qemu_tablet_hid_report_descriptor);
454
	    }
455
	    break;
289 456
        default:
290 457
            goto fail;
291 458
        }
292 459
        break;
293 460
    case GET_REPORT:
294
        ret = usb_mouse_poll(s, data, length);
461
	if (s->kind == USB_MOUSE)
462
	    ret = usb_mouse_poll(s, data, length);
463
	else if (s->kind == USB_TABLET)
464
	    ret = usb_tablet_poll(s, data, length);
295 465
        break;
296 466
    case SET_IDLE:
297 467
        ret = 0;
......
308 478
                                 uint8_t devep, uint8_t *data, int len)
309 479
{
310 480
    USBMouseState *s = (USBMouseState *)dev;
311
    int ret;
481
    int ret = 0;
312 482

  
313 483
    switch(pid) {
314 484
    case USB_TOKEN_IN:
315 485
        if (devep == 1) {
316
            ret = usb_mouse_poll(s, data, len);
486
	    if (s->kind == USB_MOUSE)
487
		ret = usb_mouse_poll(s, data, len);
488
	    else if (s->kind == USB_TABLET)
489
		ret = usb_tablet_poll(s, data, len);
317 490
        } else {
318 491
            goto fail;
319 492
        }
......
327 500
    return ret;
328 501
}
329 502

  
503
USBDevice *usb_tablet_init(void)
504
{
505
    USBMouseState *s;
506

  
507
    s = qemu_mallocz(sizeof(USBMouseState));
508
    if (!s)
509
        return NULL;
510
    s->dev.speed = USB_SPEED_FULL;
511
    s->dev.handle_packet = usb_generic_handle_packet;
512

  
513
    s->dev.handle_reset = usb_mouse_handle_reset;
514
    s->dev.handle_control = usb_mouse_handle_control;
515
    s->dev.handle_data = usb_mouse_handle_data;
516
    s->kind = USB_TABLET;
517

  
518
    return (USBDevice *)s;
519
}
520

  
330 521
USBDevice *usb_mouse_init(void)
331 522
{
332 523
    USBMouseState *s;
......
340 531
    s->dev.handle_reset = usb_mouse_handle_reset;
341 532
    s->dev.handle_control = usb_mouse_handle_control;
342 533
    s->dev.handle_data = usb_mouse_handle_data;
534
    s->kind = USB_MOUSE;
343 535

  
344
    qemu_add_mouse_event_handler(usb_mouse_event, s);
345
    
346 536
    return (USBDevice *)s;
347 537
}

Also available in: Unified diff