Statistics
| Branch: | Revision:

root / hw / usb / dev-hid.c @ 3bd88451

History | View | Annotate | Download (22.7 kB)

1
/*
2
 * QEMU USB HID devices
3
 *
4
 * Copyright (c) 2005 Fabrice Bellard
5
 * Copyright (c) 2007 OpenMoko, Inc.  (andrew@openedhand.com)
6
 *
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
 */
25
#include "hw/hw.h"
26
#include "ui/console.h"
27
#include "hw/usb.h"
28
#include "hw/usb/desc.h"
29
#include "qemu/timer.h"
30
#include "hw/input/hid.h"
31

    
32
/* HID interface requests */
33
#define GET_REPORT   0xa101
34
#define GET_IDLE     0xa102
35
#define GET_PROTOCOL 0xa103
36
#define SET_REPORT   0x2109
37
#define SET_IDLE     0x210a
38
#define SET_PROTOCOL 0x210b
39

    
40
/* HID descriptor types */
41
#define USB_DT_HID    0x21
42
#define USB_DT_REPORT 0x22
43
#define USB_DT_PHY    0x23
44

    
45
typedef struct USBHIDState {
46
    USBDevice dev;
47
    USBEndpoint *intr;
48
    HIDState hid;
49
    uint32_t usb_version;
50
} USBHIDState;
51

    
52
enum {
53
    STR_MANUFACTURER = 1,
54
    STR_PRODUCT_MOUSE,
55
    STR_PRODUCT_TABLET,
56
    STR_PRODUCT_KEYBOARD,
57
    STR_SERIALNUMBER,
58
    STR_CONFIG_MOUSE,
59
    STR_CONFIG_TABLET,
60
    STR_CONFIG_KEYBOARD,
61
};
62

    
63
static const USBDescStrings desc_strings = {
64
    [STR_MANUFACTURER]     = "QEMU",
65
    [STR_PRODUCT_MOUSE]    = "QEMU USB Mouse",
66
    [STR_PRODUCT_TABLET]   = "QEMU USB Tablet",
67
    [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
68
    [STR_SERIALNUMBER]     = "42", /* == remote wakeup works */
69
    [STR_CONFIG_MOUSE]     = "HID Mouse",
70
    [STR_CONFIG_TABLET]    = "HID Tablet",
71
    [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
72
};
73

    
74
static const USBDescIface desc_iface_mouse = {
75
    .bInterfaceNumber              = 0,
76
    .bNumEndpoints                 = 1,
77
    .bInterfaceClass               = USB_CLASS_HID,
78
    .bInterfaceSubClass            = 0x01, /* boot */
79
    .bInterfaceProtocol            = 0x02,
80
    .ndesc                         = 1,
81
    .descs = (USBDescOther[]) {
82
        {
83
            /* HID descriptor */
84
            .data = (uint8_t[]) {
85
                0x09,          /*  u8  bLength */
86
                USB_DT_HID,    /*  u8  bDescriptorType */
87
                0x01, 0x00,    /*  u16 HID_class */
88
                0x00,          /*  u8  country_code */
89
                0x01,          /*  u8  num_descriptors */
90
                USB_DT_REPORT, /*  u8  type: Report */
91
                52, 0,         /*  u16 len */
92
            },
93
        },
94
    },
95
    .eps = (USBDescEndpoint[]) {
96
        {
97
            .bEndpointAddress      = USB_DIR_IN | 0x01,
98
            .bmAttributes          = USB_ENDPOINT_XFER_INT,
99
            .wMaxPacketSize        = 4,
100
            .bInterval             = 0x0a,
101
        },
102
    },
103
};
104

    
105
static const USBDescIface desc_iface_tablet = {
106
    .bInterfaceNumber              = 0,
107
    .bNumEndpoints                 = 1,
108
    .bInterfaceClass               = USB_CLASS_HID,
109
    .bInterfaceProtocol            = 0x02,
110
    .ndesc                         = 1,
111
    .descs = (USBDescOther[]) {
112
        {
113
            /* HID descriptor */
114
            .data = (uint8_t[]) {
115
                0x09,          /*  u8  bLength */
116
                USB_DT_HID,    /*  u8  bDescriptorType */
117
                0x01, 0x00,    /*  u16 HID_class */
118
                0x00,          /*  u8  country_code */
119
                0x01,          /*  u8  num_descriptors */
120
                USB_DT_REPORT, /*  u8  type: Report */
121
                74, 0,         /*  u16 len */
122
            },
123
        },
124
    },
125
    .eps = (USBDescEndpoint[]) {
126
        {
127
            .bEndpointAddress      = USB_DIR_IN | 0x01,
128
            .bmAttributes          = USB_ENDPOINT_XFER_INT,
129
            .wMaxPacketSize        = 8,
130
            .bInterval             = 0x0a,
131
        },
132
    },
133
};
134

    
135
static const USBDescIface desc_iface_tablet2 = {
136
    .bInterfaceNumber              = 0,
137
    .bNumEndpoints                 = 1,
138
    .bInterfaceClass               = USB_CLASS_HID,
139
    .bInterfaceProtocol            = 0x02,
140
    .ndesc                         = 1,
141
    .descs = (USBDescOther[]) {
142
        {
143
            /* HID descriptor */
144
            .data = (uint8_t[]) {
145
                0x09,          /*  u8  bLength */
146
                USB_DT_HID,    /*  u8  bDescriptorType */
147
                0x01, 0x00,    /*  u16 HID_class */
148
                0x00,          /*  u8  country_code */
149
                0x01,          /*  u8  num_descriptors */
150
                USB_DT_REPORT, /*  u8  type: Report */
151
                74, 0,         /*  u16 len */
152
            },
153
        },
154
    },
155
    .eps = (USBDescEndpoint[]) {
156
        {
157
            .bEndpointAddress      = USB_DIR_IN | 0x01,
158
            .bmAttributes          = USB_ENDPOINT_XFER_INT,
159
            .wMaxPacketSize        = 8,
160
            .bInterval             = 4, /* 2 ^ (4-1) * 125 usecs = 1 ms */
161
        },
162
    },
163
};
164

    
165
static const USBDescIface desc_iface_keyboard = {
166
    .bInterfaceNumber              = 0,
167
    .bNumEndpoints                 = 1,
168
    .bInterfaceClass               = USB_CLASS_HID,
169
    .bInterfaceSubClass            = 0x01, /* boot */
170
    .bInterfaceProtocol            = 0x01, /* keyboard */
171
    .ndesc                         = 1,
172
    .descs = (USBDescOther[]) {
173
        {
174
            /* HID descriptor */
175
            .data = (uint8_t[]) {
176
                0x09,          /*  u8  bLength */
177
                USB_DT_HID,    /*  u8  bDescriptorType */
178
                0x11, 0x01,    /*  u16 HID_class */
179
                0x00,          /*  u8  country_code */
180
                0x01,          /*  u8  num_descriptors */
181
                USB_DT_REPORT, /*  u8  type: Report */
182
                0x3f, 0,       /*  u16 len */
183
            },
184
        },
185
    },
186
    .eps = (USBDescEndpoint[]) {
187
        {
188
            .bEndpointAddress      = USB_DIR_IN | 0x01,
189
            .bmAttributes          = USB_ENDPOINT_XFER_INT,
190
            .wMaxPacketSize        = 8,
191
            .bInterval             = 0x0a,
192
        },
193
    },
194
};
195

    
196
static const USBDescDevice desc_device_mouse = {
197
    .bcdUSB                        = 0x0100,
198
    .bMaxPacketSize0               = 8,
199
    .bNumConfigurations            = 1,
200
    .confs = (USBDescConfig[]) {
201
        {
202
            .bNumInterfaces        = 1,
203
            .bConfigurationValue   = 1,
204
            .iConfiguration        = STR_CONFIG_MOUSE,
205
            .bmAttributes          = 0xa0,
206
            .bMaxPower             = 50,
207
            .nif = 1,
208
            .ifs = &desc_iface_mouse,
209
        },
210
    },
211
};
212

    
213
static const USBDescDevice desc_device_tablet = {
214
    .bcdUSB                        = 0x0100,
215
    .bMaxPacketSize0               = 8,
216
    .bNumConfigurations            = 1,
217
    .confs = (USBDescConfig[]) {
218
        {
219
            .bNumInterfaces        = 1,
220
            .bConfigurationValue   = 1,
221
            .iConfiguration        = STR_CONFIG_TABLET,
222
            .bmAttributes          = 0xa0,
223
            .bMaxPower             = 50,
224
            .nif = 1,
225
            .ifs = &desc_iface_tablet,
226
        },
227
    },
228
};
229

    
230
static const USBDescDevice desc_device_tablet2 = {
231
    .bcdUSB                        = 0x0200,
232
    .bMaxPacketSize0               = 64,
233
    .bNumConfigurations            = 1,
234
    .confs = (USBDescConfig[]) {
235
        {
236
            .bNumInterfaces        = 1,
237
            .bConfigurationValue   = 1,
238
            .iConfiguration        = STR_CONFIG_TABLET,
239
            .bmAttributes          = 0xa0,
240
            .bMaxPower             = 50,
241
            .nif = 1,
242
            .ifs = &desc_iface_tablet2,
243
        },
244
    },
245
};
246

    
247
static const USBDescDevice desc_device_keyboard = {
248
    .bcdUSB                        = 0x0100,
249
    .bMaxPacketSize0               = 8,
250
    .bNumConfigurations            = 1,
251
    .confs = (USBDescConfig[]) {
252
        {
253
            .bNumInterfaces        = 1,
254
            .bConfigurationValue   = 1,
255
            .iConfiguration        = STR_CONFIG_KEYBOARD,
256
            .bmAttributes          = 0xa0,
257
            .bMaxPower             = 50,
258
            .nif = 1,
259
            .ifs = &desc_iface_keyboard,
260
        },
261
    },
262
};
263

    
264
static const USBDesc desc_mouse = {
265
    .id = {
266
        .idVendor          = 0x0627,
267
        .idProduct         = 0x0001,
268
        .bcdDevice         = 0,
269
        .iManufacturer     = STR_MANUFACTURER,
270
        .iProduct          = STR_PRODUCT_MOUSE,
271
        .iSerialNumber     = STR_SERIALNUMBER,
272
    },
273
    .full = &desc_device_mouse,
274
    .str  = desc_strings,
275
};
276

    
277
static const USBDesc desc_tablet = {
278
    .id = {
279
        .idVendor          = 0x0627,
280
        .idProduct         = 0x0001,
281
        .bcdDevice         = 0,
282
        .iManufacturer     = STR_MANUFACTURER,
283
        .iProduct          = STR_PRODUCT_TABLET,
284
        .iSerialNumber     = STR_SERIALNUMBER,
285
    },
286
    .full = &desc_device_tablet,
287
    .str  = desc_strings,
288
};
289

    
290
static const USBDesc desc_tablet2 = {
291
    .id = {
292
        .idVendor          = 0x0627,
293
        .idProduct         = 0x0001,
294
        .bcdDevice         = 0,
295
        .iManufacturer     = STR_MANUFACTURER,
296
        .iProduct          = STR_PRODUCT_TABLET,
297
        .iSerialNumber     = STR_SERIALNUMBER,
298
    },
299
    .full = &desc_device_tablet,
300
    .high = &desc_device_tablet2,
301
    .str  = desc_strings,
302
};
303

    
304
static const USBDesc desc_keyboard = {
305
    .id = {
306
        .idVendor          = 0x0627,
307
        .idProduct         = 0x0001,
308
        .bcdDevice         = 0,
309
        .iManufacturer     = STR_MANUFACTURER,
310
        .iProduct          = STR_PRODUCT_KEYBOARD,
311
        .iSerialNumber     = STR_SERIALNUMBER,
312
    },
313
    .full = &desc_device_keyboard,
314
    .str  = desc_strings,
315
};
316

    
317
static const uint8_t qemu_mouse_hid_report_descriptor[] = {
318
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
319
    0x09, 0x02,                /* Usage (Mouse) */
320
    0xa1, 0x01,                /* Collection (Application) */
321
    0x09, 0x01,                /*   Usage (Pointer) */
322
    0xa1, 0x00,                /*   Collection (Physical) */
323
    0x05, 0x09,                /*     Usage Page (Button) */
324
    0x19, 0x01,                /*     Usage Minimum (1) */
325
    0x29, 0x03,                /*     Usage Maximum (3) */
326
    0x15, 0x00,                /*     Logical Minimum (0) */
327
    0x25, 0x01,                /*     Logical Maximum (1) */
328
    0x95, 0x03,                /*     Report Count (3) */
329
    0x75, 0x01,                /*     Report Size (1) */
330
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
331
    0x95, 0x01,                /*     Report Count (1) */
332
    0x75, 0x05,                /*     Report Size (5) */
333
    0x81, 0x01,                /*     Input (Constant) */
334
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
335
    0x09, 0x30,                /*     Usage (X) */
336
    0x09, 0x31,                /*     Usage (Y) */
337
    0x09, 0x38,                /*     Usage (Wheel) */
338
    0x15, 0x81,                /*     Logical Minimum (-0x7f) */
339
    0x25, 0x7f,                /*     Logical Maximum (0x7f) */
340
    0x75, 0x08,                /*     Report Size (8) */
341
    0x95, 0x03,                /*     Report Count (3) */
342
    0x81, 0x06,                /*     Input (Data, Variable, Relative) */
343
    0xc0,                /*   End Collection */
344
    0xc0,                /* End Collection */
345
};
346

    
347
static const uint8_t qemu_tablet_hid_report_descriptor[] = {
348
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
349
    0x09, 0x01,                /* Usage (Pointer) */
350
    0xa1, 0x01,                /* Collection (Application) */
351
    0x09, 0x01,                /*   Usage (Pointer) */
352
    0xa1, 0x00,                /*   Collection (Physical) */
353
    0x05, 0x09,                /*     Usage Page (Button) */
354
    0x19, 0x01,                /*     Usage Minimum (1) */
355
    0x29, 0x03,                /*     Usage Maximum (3) */
356
    0x15, 0x00,                /*     Logical Minimum (0) */
357
    0x25, 0x01,                /*     Logical Maximum (1) */
358
    0x95, 0x03,                /*     Report Count (3) */
359
    0x75, 0x01,                /*     Report Size (1) */
360
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
361
    0x95, 0x01,                /*     Report Count (1) */
362
    0x75, 0x05,                /*     Report Size (5) */
363
    0x81, 0x01,                /*     Input (Constant) */
364
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
365
    0x09, 0x30,                /*     Usage (X) */
366
    0x09, 0x31,                /*     Usage (Y) */
367
    0x15, 0x00,                /*     Logical Minimum (0) */
368
    0x26, 0xff, 0x7f,        /*     Logical Maximum (0x7fff) */
369
    0x35, 0x00,                /*     Physical Minimum (0) */
370
    0x46, 0xff, 0x7f,        /*     Physical Maximum (0x7fff) */
371
    0x75, 0x10,                /*     Report Size (16) */
372
    0x95, 0x02,                /*     Report Count (2) */
373
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
374
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
375
    0x09, 0x38,                /*     Usage (Wheel) */
376
    0x15, 0x81,                /*     Logical Minimum (-0x7f) */
377
    0x25, 0x7f,                /*     Logical Maximum (0x7f) */
378
    0x35, 0x00,                /*     Physical Minimum (same as logical) */
379
    0x45, 0x00,                /*     Physical Maximum (same as logical) */
380
    0x75, 0x08,                /*     Report Size (8) */
381
    0x95, 0x01,                /*     Report Count (1) */
382
    0x81, 0x06,                /*     Input (Data, Variable, Relative) */
383
    0xc0,                /*   End Collection */
384
    0xc0,                /* End Collection */
385
};
386

    
387
static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
388
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
389
    0x09, 0x06,                /* Usage (Keyboard) */
390
    0xa1, 0x01,                /* Collection (Application) */
391
    0x75, 0x01,                /*   Report Size (1) */
392
    0x95, 0x08,                /*   Report Count (8) */
393
    0x05, 0x07,                /*   Usage Page (Key Codes) */
394
    0x19, 0xe0,                /*   Usage Minimum (224) */
395
    0x29, 0xe7,                /*   Usage Maximum (231) */
396
    0x15, 0x00,                /*   Logical Minimum (0) */
397
    0x25, 0x01,                /*   Logical Maximum (1) */
398
    0x81, 0x02,                /*   Input (Data, Variable, Absolute) */
399
    0x95, 0x01,                /*   Report Count (1) */
400
    0x75, 0x08,                /*   Report Size (8) */
401
    0x81, 0x01,                /*   Input (Constant) */
402
    0x95, 0x05,                /*   Report Count (5) */
403
    0x75, 0x01,                /*   Report Size (1) */
404
    0x05, 0x08,                /*   Usage Page (LEDs) */
405
    0x19, 0x01,                /*   Usage Minimum (1) */
406
    0x29, 0x05,                /*   Usage Maximum (5) */
407
    0x91, 0x02,                /*   Output (Data, Variable, Absolute) */
408
    0x95, 0x01,                /*   Report Count (1) */
409
    0x75, 0x03,                /*   Report Size (3) */
410
    0x91, 0x01,                /*   Output (Constant) */
411
    0x95, 0x06,                /*   Report Count (6) */
412
    0x75, 0x08,                /*   Report Size (8) */
413
    0x15, 0x00,                /*   Logical Minimum (0) */
414
    0x25, 0xff,                /*   Logical Maximum (255) */
415
    0x05, 0x07,                /*   Usage Page (Key Codes) */
416
    0x19, 0x00,                /*   Usage Minimum (0) */
417
    0x29, 0xff,                /*   Usage Maximum (255) */
418
    0x81, 0x00,                /*   Input (Data, Array) */
419
    0xc0,                /* End Collection */
420
};
421

    
422
static void usb_hid_changed(HIDState *hs)
423
{
424
    USBHIDState *us = container_of(hs, USBHIDState, hid);
425

    
426
    usb_wakeup(us->intr, 0);
427
}
428

    
429
static void usb_hid_handle_reset(USBDevice *dev)
430
{
431
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
432

    
433
    hid_reset(&us->hid);
434
}
435

    
436
static void usb_hid_handle_control(USBDevice *dev, USBPacket *p,
437
               int request, int value, int index, int length, uint8_t *data)
438
{
439
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
440
    HIDState *hs = &us->hid;
441
    int ret;
442

    
443
    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
444
    if (ret >= 0) {
445
        return;
446
    }
447

    
448
    switch (request) {
449
        /* hid specific requests */
450
    case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
451
        switch (value >> 8) {
452
        case 0x22:
453
            if (hs->kind == HID_MOUSE) {
454
                memcpy(data, qemu_mouse_hid_report_descriptor,
455
                       sizeof(qemu_mouse_hid_report_descriptor));
456
                p->actual_length = sizeof(qemu_mouse_hid_report_descriptor);
457
            } else if (hs->kind == HID_TABLET) {
458
                memcpy(data, qemu_tablet_hid_report_descriptor,
459
                       sizeof(qemu_tablet_hid_report_descriptor));
460
                p->actual_length = sizeof(qemu_tablet_hid_report_descriptor);
461
            } else if (hs->kind == HID_KEYBOARD) {
462
                memcpy(data, qemu_keyboard_hid_report_descriptor,
463
                       sizeof(qemu_keyboard_hid_report_descriptor));
464
                p->actual_length = sizeof(qemu_keyboard_hid_report_descriptor);
465
            }
466
            break;
467
        default:
468
            goto fail;
469
        }
470
        break;
471
    case GET_REPORT:
472
        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
473
            p->actual_length = hid_pointer_poll(hs, data, length);
474
        } else if (hs->kind == HID_KEYBOARD) {
475
            p->actual_length = hid_keyboard_poll(hs, data, length);
476
        }
477
        break;
478
    case SET_REPORT:
479
        if (hs->kind == HID_KEYBOARD) {
480
            p->actual_length = hid_keyboard_write(hs, data, length);
481
        } else {
482
            goto fail;
483
        }
484
        break;
485
    case GET_PROTOCOL:
486
        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
487
            goto fail;
488
        }
489
        data[0] = hs->protocol;
490
        p->actual_length = 1;
491
        break;
492
    case SET_PROTOCOL:
493
        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
494
            goto fail;
495
        }
496
        hs->protocol = value;
497
        break;
498
    case GET_IDLE:
499
        data[0] = hs->idle;
500
        p->actual_length = 1;
501
        break;
502
    case SET_IDLE:
503
        hs->idle = (uint8_t) (value >> 8);
504
        hid_set_next_idle(hs);
505
        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
506
            hid_pointer_activate(hs);
507
        }
508
        break;
509
    default:
510
    fail:
511
        p->status = USB_RET_STALL;
512
        break;
513
    }
514
}
515

    
516
static void usb_hid_handle_data(USBDevice *dev, USBPacket *p)
517
{
518
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
519
    HIDState *hs = &us->hid;
520
    uint8_t buf[p->iov.size];
521
    int len = 0;
522

    
523
    switch (p->pid) {
524
    case USB_TOKEN_IN:
525
        if (p->ep->nr == 1) {
526
            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
527
                hid_pointer_activate(hs);
528
            }
529
            if (!hid_has_events(hs)) {
530
                p->status = USB_RET_NAK;
531
                return;
532
            }
533
            hid_set_next_idle(hs);
534
            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
535
                len = hid_pointer_poll(hs, buf, p->iov.size);
536
            } else if (hs->kind == HID_KEYBOARD) {
537
                len = hid_keyboard_poll(hs, buf, p->iov.size);
538
            }
539
            usb_packet_copy(p, buf, len);
540
        } else {
541
            goto fail;
542
        }
543
        break;
544
    case USB_TOKEN_OUT:
545
    default:
546
    fail:
547
        p->status = USB_RET_STALL;
548
        break;
549
    }
550
}
551

    
552
static void usb_hid_handle_destroy(USBDevice *dev)
553
{
554
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
555

    
556
    hid_free(&us->hid);
557
}
558

    
559
static int usb_hid_initfn(USBDevice *dev, int kind)
560
{
561
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
562

    
563
    usb_desc_init(dev);
564
    us->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
565
    hid_init(&us->hid, kind, usb_hid_changed);
566
    return 0;
567
}
568

    
569
static int usb_tablet_initfn(USBDevice *dev)
570
{
571
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
572

    
573
    switch (us->usb_version) {
574
    case 1:
575
        dev->usb_desc = &desc_tablet;
576
        break;
577
    case 2:
578
        dev->usb_desc = &desc_tablet2;
579
        break;
580
    default:
581
        error_report("Invalid usb version %d for usb-tabler (must be 1 or 2)",
582
                     us->usb_version);
583
        return -1;
584
    }
585

    
586
    return usb_hid_initfn(dev, HID_TABLET);
587
}
588

    
589
static int usb_mouse_initfn(USBDevice *dev)
590
{
591
    return usb_hid_initfn(dev, HID_MOUSE);
592
}
593

    
594
static int usb_keyboard_initfn(USBDevice *dev)
595
{
596
    return usb_hid_initfn(dev, HID_KEYBOARD);
597
}
598

    
599
static int usb_ptr_post_load(void *opaque, int version_id)
600
{
601
    USBHIDState *s = opaque;
602

    
603
    if (s->dev.remote_wakeup) {
604
        hid_pointer_activate(&s->hid);
605
    }
606
    return 0;
607
}
608

    
609
static const VMStateDescription vmstate_usb_ptr = {
610
    .name = "usb-ptr",
611
    .version_id = 1,
612
    .minimum_version_id = 1,
613
    .post_load = usb_ptr_post_load,
614
    .fields = (VMStateField []) {
615
        VMSTATE_USB_DEVICE(dev, USBHIDState),
616
        VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
617
        VMSTATE_END_OF_LIST()
618
    }
619
};
620

    
621
static const VMStateDescription vmstate_usb_kbd = {
622
    .name = "usb-kbd",
623
    .version_id = 1,
624
    .minimum_version_id = 1,
625
    .fields = (VMStateField []) {
626
        VMSTATE_USB_DEVICE(dev, USBHIDState),
627
        VMSTATE_HID_KEYBOARD_DEVICE(hid, USBHIDState),
628
        VMSTATE_END_OF_LIST()
629
    }
630
};
631

    
632
static void usb_hid_class_initfn(ObjectClass *klass, void *data)
633
{
634
    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
635

    
636
    uc->handle_reset   = usb_hid_handle_reset;
637
    uc->handle_control = usb_hid_handle_control;
638
    uc->handle_data    = usb_hid_handle_data;
639
    uc->handle_destroy = usb_hid_handle_destroy;
640
    uc->handle_attach  = usb_desc_attach;
641
}
642

    
643
static Property usb_tablet_properties[] = {
644
        DEFINE_PROP_UINT32("usb_version", USBHIDState, usb_version, 2),
645
        DEFINE_PROP_END_OF_LIST(),
646
};
647

    
648
static void usb_tablet_class_initfn(ObjectClass *klass, void *data)
649
{
650
    DeviceClass *dc = DEVICE_CLASS(klass);
651
    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
652

    
653
    usb_hid_class_initfn(klass, data);
654
    uc->init           = usb_tablet_initfn;
655
    uc->product_desc   = "QEMU USB Tablet";
656
    dc->vmsd = &vmstate_usb_ptr;
657
    dc->props = usb_tablet_properties;
658
}
659

    
660
static const TypeInfo usb_tablet_info = {
661
    .name          = "usb-tablet",
662
    .parent        = TYPE_USB_DEVICE,
663
    .instance_size = sizeof(USBHIDState),
664
    .class_init    = usb_tablet_class_initfn,
665
};
666

    
667
static void usb_mouse_class_initfn(ObjectClass *klass, void *data)
668
{
669
    DeviceClass *dc = DEVICE_CLASS(klass);
670
    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
671

    
672
    usb_hid_class_initfn(klass, data);
673
    uc->init           = usb_mouse_initfn;
674
    uc->product_desc   = "QEMU USB Mouse";
675
    uc->usb_desc       = &desc_mouse;
676
    dc->vmsd = &vmstate_usb_ptr;
677
}
678

    
679
static const TypeInfo usb_mouse_info = {
680
    .name          = "usb-mouse",
681
    .parent        = TYPE_USB_DEVICE,
682
    .instance_size = sizeof(USBHIDState),
683
    .class_init    = usb_mouse_class_initfn,
684
};
685

    
686
static void usb_keyboard_class_initfn(ObjectClass *klass, void *data)
687
{
688
    DeviceClass *dc = DEVICE_CLASS(klass);
689
    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
690

    
691
    usb_hid_class_initfn(klass, data);
692
    uc->init           = usb_keyboard_initfn;
693
    uc->product_desc   = "QEMU USB Keyboard";
694
    uc->usb_desc       = &desc_keyboard;
695
    dc->vmsd = &vmstate_usb_kbd;
696
}
697

    
698
static const TypeInfo usb_keyboard_info = {
699
    .name          = "usb-kbd",
700
    .parent        = TYPE_USB_DEVICE,
701
    .instance_size = sizeof(USBHIDState),
702
    .class_init    = usb_keyboard_class_initfn,
703
};
704

    
705
static void usb_hid_register_types(void)
706
{
707
    type_register_static(&usb_tablet_info);
708
    usb_legacy_register("usb-tablet", "tablet", NULL);
709
    type_register_static(&usb_mouse_info);
710
    usb_legacy_register("usb-mouse", "mouse", NULL);
711
    type_register_static(&usb_keyboard_info);
712
    usb_legacy_register("usb-kbd", "keyboard", NULL);
713
}
714

    
715
type_init(usb_hid_register_types)