Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ 46115ac4

History | View | Annotate | Download (31.3 kB)

1 59ae540c bellard
/*
2 59ae540c bellard
 * QEMU USB HID devices
3 5fafdf24 ths
 *
4 59ae540c bellard
 * Copyright (c) 2005 Fabrice Bellard
5 47b2d338 balrog
 * Copyright (c) 2007 OpenMoko, Inc.  (andrew@openedhand.com)
6 5fafdf24 ths
 *
7 59ae540c bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 59ae540c bellard
 * of this software and associated documentation files (the "Software"), to deal
9 59ae540c bellard
 * in the Software without restriction, including without limitation the rights
10 59ae540c bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 59ae540c bellard
 * copies of the Software, and to permit persons to whom the Software is
12 59ae540c bellard
 * furnished to do so, subject to the following conditions:
13 59ae540c bellard
 *
14 59ae540c bellard
 * The above copyright notice and this permission notice shall be included in
15 59ae540c bellard
 * all copies or substantial portions of the Software.
16 59ae540c bellard
 *
17 59ae540c bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 59ae540c bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 59ae540c bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 59ae540c bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 59ae540c bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 59ae540c bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 59ae540c bellard
 * THE SOFTWARE.
24 59ae540c bellard
 */
25 87ecb68b pbrook
#include "hw.h"
26 87ecb68b pbrook
#include "console.h"
27 87ecb68b pbrook
#include "usb.h"
28 0e4e9695 Gerd Hoffmann
#include "usb-desc.h"
29 d8dfad9c Blue Swirl
#include "qemu-timer.h"
30 59ae540c bellard
31 59ae540c bellard
/* HID interface requests */
32 59ae540c bellard
#define GET_REPORT   0xa101
33 59ae540c bellard
#define GET_IDLE     0xa102
34 59ae540c bellard
#define GET_PROTOCOL 0xa103
35 47b2d338 balrog
#define SET_REPORT   0x2109
36 59ae540c bellard
#define SET_IDLE     0x210a
37 59ae540c bellard
#define SET_PROTOCOL 0x210b
38 59ae540c bellard
39 47b2d338 balrog
/* HID descriptor types */
40 47b2d338 balrog
#define USB_DT_HID    0x21
41 47b2d338 balrog
#define USB_DT_REPORT 0x22
42 47b2d338 balrog
#define USB_DT_PHY    0x23
43 47b2d338 balrog
44 47b2d338 balrog
#define USB_MOUSE     1
45 47b2d338 balrog
#define USB_TABLET    2
46 47b2d338 balrog
#define USB_KEYBOARD  3
47 09b26c5e bellard
48 13f8b97a Paolo Bonzini
typedef struct USBPointerEvent {
49 13f8b97a Paolo Bonzini
    int32_t xdx, ydy; /* relative iff it's a mouse, otherwise absolute */
50 13f8b97a Paolo Bonzini
    int32_t dz, buttons_state;
51 13f8b97a Paolo Bonzini
} USBPointerEvent;
52 13f8b97a Paolo Bonzini
53 13f8b97a Paolo Bonzini
#define QUEUE_LENGTH    16 /* should be enough for a triple-click */
54 13f8b97a Paolo Bonzini
#define QUEUE_MASK      (QUEUE_LENGTH-1u)
55 13f8b97a Paolo Bonzini
#define QUEUE_INCR(v)   ((v)++, (v) &= QUEUE_MASK)
56 13f8b97a Paolo Bonzini
57 59ae540c bellard
typedef struct USBMouseState {
58 13f8b97a Paolo Bonzini
    USBPointerEvent queue[QUEUE_LENGTH];
59 09b26c5e bellard
    int mouse_grabbed;
60 455204eb ths
    QEMUPutMouseEntry *eh_entry;
61 59ae540c bellard
} USBMouseState;
62 59ae540c bellard
63 47b2d338 balrog
typedef struct USBKeyboardState {
64 5fae51a9 Gerd Hoffmann
    uint32_t keycodes[QUEUE_LENGTH];
65 47b2d338 balrog
    uint16_t modifiers;
66 47b2d338 balrog
    uint8_t leds;
67 47b2d338 balrog
    uint8_t key[16];
68 ee59e6b3 Gerd Hoffmann
    int32_t keys;
69 47b2d338 balrog
} USBKeyboardState;
70 47b2d338 balrog
71 47b2d338 balrog
typedef struct USBHIDState {
72 47b2d338 balrog
    USBDevice dev;
73 47b2d338 balrog
    union {
74 47b2d338 balrog
        USBMouseState ptr;
75 47b2d338 balrog
        USBKeyboardState kbd;
76 47b2d338 balrog
    };
77 42292d4e Gerd Hoffmann
    uint32_t head; /* index into circular queue */
78 42292d4e Gerd Hoffmann
    uint32_t n;
79 47b2d338 balrog
    int kind;
80 ee59e6b3 Gerd Hoffmann
    int32_t protocol;
81 181a29c5 aliguori
    uint8_t idle;
82 68735b6c Kevin O'Connor
    int64_t next_idle_clock;
83 117b3ae6 pbrook
    int changed;
84 47e699dc balrog
    void *datain_opaque;
85 47e699dc balrog
    void (*datain)(void *);
86 47b2d338 balrog
} USBHIDState;
87 47b2d338 balrog
88 0e4e9695 Gerd Hoffmann
enum {
89 0e4e9695 Gerd Hoffmann
    STR_MANUFACTURER = 1,
90 0e4e9695 Gerd Hoffmann
    STR_PRODUCT_MOUSE,
91 0e4e9695 Gerd Hoffmann
    STR_PRODUCT_TABLET,
92 0e4e9695 Gerd Hoffmann
    STR_PRODUCT_KEYBOARD,
93 0e4e9695 Gerd Hoffmann
    STR_SERIALNUMBER,
94 0e4e9695 Gerd Hoffmann
    STR_CONFIG_MOUSE,
95 0e4e9695 Gerd Hoffmann
    STR_CONFIG_TABLET,
96 0e4e9695 Gerd Hoffmann
    STR_CONFIG_KEYBOARD,
97 59ae540c bellard
};
98 59ae540c bellard
99 0e4e9695 Gerd Hoffmann
static const USBDescStrings desc_strings = {
100 0e4e9695 Gerd Hoffmann
    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
101 0e4e9695 Gerd Hoffmann
    [STR_PRODUCT_MOUSE]    = "QEMU USB Mouse",
102 0e4e9695 Gerd Hoffmann
    [STR_PRODUCT_TABLET]   = "QEMU USB Tablet",
103 0e4e9695 Gerd Hoffmann
    [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
104 7b074a22 Gerd Hoffmann
    [STR_SERIALNUMBER]     = "42", /* == remote wakeup works */
105 0e4e9695 Gerd Hoffmann
    [STR_CONFIG_MOUSE]     = "HID Mouse",
106 0e4e9695 Gerd Hoffmann
    [STR_CONFIG_TABLET]    = "HID Tablet",
107 0e4e9695 Gerd Hoffmann
    [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
108 09b26c5e bellard
};
109 09b26c5e bellard
110 0e4e9695 Gerd Hoffmann
static const USBDescIface desc_iface_mouse = {
111 0e4e9695 Gerd Hoffmann
    .bInterfaceNumber              = 0,
112 0e4e9695 Gerd Hoffmann
    .bNumEndpoints                 = 1,
113 0e4e9695 Gerd Hoffmann
    .bInterfaceClass               = USB_CLASS_HID,
114 0e4e9695 Gerd Hoffmann
    .bInterfaceSubClass            = 0x01, /* boot */
115 0e4e9695 Gerd Hoffmann
    .bInterfaceProtocol            = 0x02,
116 0e4e9695 Gerd Hoffmann
    .ndesc                         = 1,
117 0e4e9695 Gerd Hoffmann
    .descs = (USBDescOther[]) {
118 0e4e9695 Gerd Hoffmann
        {
119 0e4e9695 Gerd Hoffmann
            /* HID descriptor */
120 0e4e9695 Gerd Hoffmann
            .data = (uint8_t[]) {
121 0e4e9695 Gerd Hoffmann
                0x09,          /*  u8  bLength */
122 0e4e9695 Gerd Hoffmann
                USB_DT_HID,    /*  u8  bDescriptorType */
123 0e4e9695 Gerd Hoffmann
                0x01, 0x00,    /*  u16 HID_class */
124 0e4e9695 Gerd Hoffmann
                0x00,          /*  u8  country_code */
125 0e4e9695 Gerd Hoffmann
                0x01,          /*  u8  num_descriptors */
126 0e4e9695 Gerd Hoffmann
                USB_DT_REPORT, /*  u8  type: Report */
127 0e4e9695 Gerd Hoffmann
                52, 0,         /*  u16 len */
128 0e4e9695 Gerd Hoffmann
            },
129 0e4e9695 Gerd Hoffmann
        },
130 0e4e9695 Gerd Hoffmann
    },
131 0e4e9695 Gerd Hoffmann
    .eps = (USBDescEndpoint[]) {
132 0e4e9695 Gerd Hoffmann
        {
133 0e4e9695 Gerd Hoffmann
            .bEndpointAddress      = USB_DIR_IN | 0x01,
134 0e4e9695 Gerd Hoffmann
            .bmAttributes          = USB_ENDPOINT_XFER_INT,
135 0e4e9695 Gerd Hoffmann
            .wMaxPacketSize        = 4,
136 0e4e9695 Gerd Hoffmann
            .bInterval             = 0x0a,
137 0e4e9695 Gerd Hoffmann
        },
138 0e4e9695 Gerd Hoffmann
    },
139 59ae540c bellard
};
140 59ae540c bellard
141 0e4e9695 Gerd Hoffmann
static const USBDescIface desc_iface_tablet = {
142 0e4e9695 Gerd Hoffmann
    .bInterfaceNumber              = 0,
143 0e4e9695 Gerd Hoffmann
    .bNumEndpoints                 = 1,
144 0e4e9695 Gerd Hoffmann
    .bInterfaceClass               = USB_CLASS_HID,
145 0e4e9695 Gerd Hoffmann
    .bInterfaceSubClass            = 0x01, /* boot */
146 0e4e9695 Gerd Hoffmann
    .bInterfaceProtocol            = 0x02,
147 0e4e9695 Gerd Hoffmann
    .ndesc                         = 1,
148 0e4e9695 Gerd Hoffmann
    .descs = (USBDescOther[]) {
149 0e4e9695 Gerd Hoffmann
        {
150 0e4e9695 Gerd Hoffmann
            /* HID descriptor */
151 0e4e9695 Gerd Hoffmann
            .data = (uint8_t[]) {
152 0e4e9695 Gerd Hoffmann
                0x09,          /*  u8  bLength */
153 0e4e9695 Gerd Hoffmann
                USB_DT_HID,    /*  u8  bDescriptorType */
154 0e4e9695 Gerd Hoffmann
                0x01, 0x00,    /*  u16 HID_class */
155 0e4e9695 Gerd Hoffmann
                0x00,          /*  u8  country_code */
156 0e4e9695 Gerd Hoffmann
                0x01,          /*  u8  num_descriptors */
157 0e4e9695 Gerd Hoffmann
                USB_DT_REPORT, /*  u8  type: Report */
158 0e4e9695 Gerd Hoffmann
                74, 0,         /*  u16 len */
159 0e4e9695 Gerd Hoffmann
            },
160 0e4e9695 Gerd Hoffmann
        },
161 0e4e9695 Gerd Hoffmann
    },
162 0e4e9695 Gerd Hoffmann
    .eps = (USBDescEndpoint[]) {
163 0e4e9695 Gerd Hoffmann
        {
164 0e4e9695 Gerd Hoffmann
            .bEndpointAddress      = USB_DIR_IN | 0x01,
165 0e4e9695 Gerd Hoffmann
            .bmAttributes          = USB_ENDPOINT_XFER_INT,
166 0e4e9695 Gerd Hoffmann
            .wMaxPacketSize        = 8,
167 0e4e9695 Gerd Hoffmann
            .bInterval             = 0x0a,
168 0e4e9695 Gerd Hoffmann
        },
169 0e4e9695 Gerd Hoffmann
    },
170 0e4e9695 Gerd Hoffmann
};
171 0e4e9695 Gerd Hoffmann
172 0e4e9695 Gerd Hoffmann
static const USBDescIface desc_iface_keyboard = {
173 0e4e9695 Gerd Hoffmann
    .bInterfaceNumber              = 0,
174 0e4e9695 Gerd Hoffmann
    .bNumEndpoints                 = 1,
175 0e4e9695 Gerd Hoffmann
    .bInterfaceClass               = USB_CLASS_HID,
176 0e4e9695 Gerd Hoffmann
    .bInterfaceSubClass            = 0x01, /* boot */
177 0e4e9695 Gerd Hoffmann
    .bInterfaceProtocol            = 0x01, /* keyboard */
178 0e4e9695 Gerd Hoffmann
    .ndesc                         = 1,
179 0e4e9695 Gerd Hoffmann
    .descs = (USBDescOther[]) {
180 0e4e9695 Gerd Hoffmann
        {
181 0e4e9695 Gerd Hoffmann
            /* HID descriptor */
182 0e4e9695 Gerd Hoffmann
            .data = (uint8_t[]) {
183 0e4e9695 Gerd Hoffmann
                0x09,          /*  u8  bLength */
184 0e4e9695 Gerd Hoffmann
                USB_DT_HID,    /*  u8  bDescriptorType */
185 0e4e9695 Gerd Hoffmann
                0x11, 0x01,    /*  u16 HID_class */
186 0e4e9695 Gerd Hoffmann
                0x00,          /*  u8  country_code */
187 0e4e9695 Gerd Hoffmann
                0x01,          /*  u8  num_descriptors */
188 0e4e9695 Gerd Hoffmann
                USB_DT_REPORT, /*  u8  type: Report */
189 0e4e9695 Gerd Hoffmann
                0x3f, 0,       /*  u16 len */
190 0e4e9695 Gerd Hoffmann
            },
191 0e4e9695 Gerd Hoffmann
        },
192 0e4e9695 Gerd Hoffmann
    },
193 0e4e9695 Gerd Hoffmann
    .eps = (USBDescEndpoint[]) {
194 0e4e9695 Gerd Hoffmann
        {
195 0e4e9695 Gerd Hoffmann
            .bEndpointAddress      = USB_DIR_IN | 0x01,
196 0e4e9695 Gerd Hoffmann
            .bmAttributes          = USB_ENDPOINT_XFER_INT,
197 0e4e9695 Gerd Hoffmann
            .wMaxPacketSize        = 8,
198 0e4e9695 Gerd Hoffmann
            .bInterval             = 0x0a,
199 0e4e9695 Gerd Hoffmann
        },
200 0e4e9695 Gerd Hoffmann
    },
201 0e4e9695 Gerd Hoffmann
};
202 0e4e9695 Gerd Hoffmann
203 0e4e9695 Gerd Hoffmann
static const USBDescDevice desc_device_mouse = {
204 0e4e9695 Gerd Hoffmann
    .bcdUSB                        = 0x0100,
205 0e4e9695 Gerd Hoffmann
    .bMaxPacketSize0               = 8,
206 0e4e9695 Gerd Hoffmann
    .bNumConfigurations            = 1,
207 0e4e9695 Gerd Hoffmann
    .confs = (USBDescConfig[]) {
208 0e4e9695 Gerd Hoffmann
        {
209 0e4e9695 Gerd Hoffmann
            .bNumInterfaces        = 1,
210 0e4e9695 Gerd Hoffmann
            .bConfigurationValue   = 1,
211 0e4e9695 Gerd Hoffmann
            .iConfiguration        = STR_CONFIG_MOUSE,
212 0e4e9695 Gerd Hoffmann
            .bmAttributes          = 0xa0,
213 0e4e9695 Gerd Hoffmann
            .bMaxPower             = 50,
214 add75088 Brad Hards
            .nif = 1,
215 0e4e9695 Gerd Hoffmann
            .ifs = &desc_iface_mouse,
216 0e4e9695 Gerd Hoffmann
        },
217 0e4e9695 Gerd Hoffmann
    },
218 0e4e9695 Gerd Hoffmann
};
219 0e4e9695 Gerd Hoffmann
220 0e4e9695 Gerd Hoffmann
static const USBDescDevice desc_device_tablet = {
221 0e4e9695 Gerd Hoffmann
    .bcdUSB                        = 0x0100,
222 0e4e9695 Gerd Hoffmann
    .bMaxPacketSize0               = 8,
223 0e4e9695 Gerd Hoffmann
    .bNumConfigurations            = 1,
224 0e4e9695 Gerd Hoffmann
    .confs = (USBDescConfig[]) {
225 0e4e9695 Gerd Hoffmann
        {
226 0e4e9695 Gerd Hoffmann
            .bNumInterfaces        = 1,
227 0e4e9695 Gerd Hoffmann
            .bConfigurationValue   = 1,
228 0e4e9695 Gerd Hoffmann
            .iConfiguration        = STR_CONFIG_TABLET,
229 0e4e9695 Gerd Hoffmann
            .bmAttributes          = 0xa0,
230 0e4e9695 Gerd Hoffmann
            .bMaxPower             = 50,
231 add75088 Brad Hards
            .nif = 1,
232 0e4e9695 Gerd Hoffmann
            .ifs = &desc_iface_tablet,
233 0e4e9695 Gerd Hoffmann
        },
234 0e4e9695 Gerd Hoffmann
    },
235 0e4e9695 Gerd Hoffmann
};
236 0e4e9695 Gerd Hoffmann
237 0e4e9695 Gerd Hoffmann
static const USBDescDevice desc_device_keyboard = {
238 0e4e9695 Gerd Hoffmann
    .bcdUSB                        = 0x0100,
239 0e4e9695 Gerd Hoffmann
    .bMaxPacketSize0               = 8,
240 0e4e9695 Gerd Hoffmann
    .bNumConfigurations            = 1,
241 0e4e9695 Gerd Hoffmann
    .confs = (USBDescConfig[]) {
242 0e4e9695 Gerd Hoffmann
        {
243 0e4e9695 Gerd Hoffmann
            .bNumInterfaces        = 1,
244 0e4e9695 Gerd Hoffmann
            .bConfigurationValue   = 1,
245 0e4e9695 Gerd Hoffmann
            .iConfiguration        = STR_CONFIG_KEYBOARD,
246 0e4e9695 Gerd Hoffmann
            .bmAttributes          = 0xa0,
247 0e4e9695 Gerd Hoffmann
            .bMaxPower             = 50,
248 add75088 Brad Hards
            .nif = 1,
249 0e4e9695 Gerd Hoffmann
            .ifs = &desc_iface_keyboard,
250 0e4e9695 Gerd Hoffmann
        },
251 0e4e9695 Gerd Hoffmann
    },
252 0e4e9695 Gerd Hoffmann
};
253 0e4e9695 Gerd Hoffmann
254 0e4e9695 Gerd Hoffmann
static const USBDesc desc_mouse = {
255 0e4e9695 Gerd Hoffmann
    .id = {
256 0e4e9695 Gerd Hoffmann
        .idVendor          = 0x0627,
257 0e4e9695 Gerd Hoffmann
        .idProduct         = 0x0001,
258 0e4e9695 Gerd Hoffmann
        .bcdDevice         = 0,
259 0e4e9695 Gerd Hoffmann
        .iManufacturer     = STR_MANUFACTURER,
260 0e4e9695 Gerd Hoffmann
        .iProduct          = STR_PRODUCT_MOUSE,
261 0e4e9695 Gerd Hoffmann
        .iSerialNumber     = STR_SERIALNUMBER,
262 0e4e9695 Gerd Hoffmann
    },
263 0e4e9695 Gerd Hoffmann
    .full = &desc_device_mouse,
264 0e4e9695 Gerd Hoffmann
    .str  = desc_strings,
265 0e4e9695 Gerd Hoffmann
};
266 0e4e9695 Gerd Hoffmann
267 0e4e9695 Gerd Hoffmann
static const USBDesc desc_tablet = {
268 0e4e9695 Gerd Hoffmann
    .id = {
269 0e4e9695 Gerd Hoffmann
        .idVendor          = 0x0627,
270 0e4e9695 Gerd Hoffmann
        .idProduct         = 0x0001,
271 0e4e9695 Gerd Hoffmann
        .bcdDevice         = 0,
272 0e4e9695 Gerd Hoffmann
        .iManufacturer     = STR_MANUFACTURER,
273 0e4e9695 Gerd Hoffmann
        .iProduct          = STR_PRODUCT_TABLET,
274 0e4e9695 Gerd Hoffmann
        .iSerialNumber     = STR_SERIALNUMBER,
275 0e4e9695 Gerd Hoffmann
    },
276 0e4e9695 Gerd Hoffmann
    .full = &desc_device_tablet,
277 0e4e9695 Gerd Hoffmann
    .str  = desc_strings,
278 0e4e9695 Gerd Hoffmann
};
279 0e4e9695 Gerd Hoffmann
280 0e4e9695 Gerd Hoffmann
static const USBDesc desc_keyboard = {
281 0e4e9695 Gerd Hoffmann
    .id = {
282 0e4e9695 Gerd Hoffmann
        .idVendor          = 0x0627,
283 0e4e9695 Gerd Hoffmann
        .idProduct         = 0x0001,
284 0e4e9695 Gerd Hoffmann
        .bcdDevice         = 0,
285 0e4e9695 Gerd Hoffmann
        .iManufacturer     = STR_MANUFACTURER,
286 0e4e9695 Gerd Hoffmann
        .iProduct          = STR_PRODUCT_KEYBOARD,
287 0e4e9695 Gerd Hoffmann
        .iSerialNumber     = STR_SERIALNUMBER,
288 0e4e9695 Gerd Hoffmann
    },
289 0e4e9695 Gerd Hoffmann
    .full = &desc_device_keyboard,
290 0e4e9695 Gerd Hoffmann
    .str  = desc_strings,
291 47b2d338 balrog
};
292 47b2d338 balrog
293 59ae540c bellard
static const uint8_t qemu_mouse_hid_report_descriptor[] = {
294 976f8eef balrog
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
295 976f8eef balrog
    0x09, 0x02,                /* Usage (Mouse) */
296 976f8eef balrog
    0xa1, 0x01,                /* Collection (Application) */
297 976f8eef balrog
    0x09, 0x01,                /*   Usage (Pointer) */
298 976f8eef balrog
    0xa1, 0x00,                /*   Collection (Physical) */
299 976f8eef balrog
    0x05, 0x09,                /*     Usage Page (Button) */
300 976f8eef balrog
    0x19, 0x01,                /*     Usage Minimum (1) */
301 976f8eef balrog
    0x29, 0x03,                /*     Usage Maximum (3) */
302 976f8eef balrog
    0x15, 0x00,                /*     Logical Minimum (0) */
303 976f8eef balrog
    0x25, 0x01,                /*     Logical Maximum (1) */
304 976f8eef balrog
    0x95, 0x03,                /*     Report Count (3) */
305 976f8eef balrog
    0x75, 0x01,                /*     Report Size (1) */
306 976f8eef balrog
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
307 976f8eef balrog
    0x95, 0x01,                /*     Report Count (1) */
308 976f8eef balrog
    0x75, 0x05,                /*     Report Size (5) */
309 976f8eef balrog
    0x81, 0x01,                /*     Input (Constant) */
310 976f8eef balrog
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
311 976f8eef balrog
    0x09, 0x30,                /*     Usage (X) */
312 976f8eef balrog
    0x09, 0x31,                /*     Usage (Y) */
313 976f8eef balrog
    0x09, 0x38,                /*     Usage (Wheel) */
314 976f8eef balrog
    0x15, 0x81,                /*     Logical Minimum (-0x7f) */
315 976f8eef balrog
    0x25, 0x7f,                /*     Logical Maximum (0x7f) */
316 976f8eef balrog
    0x75, 0x08,                /*     Report Size (8) */
317 976f8eef balrog
    0x95, 0x03,                /*     Report Count (3) */
318 976f8eef balrog
    0x81, 0x06,                /*     Input (Data, Variable, Relative) */
319 976f8eef balrog
    0xc0,                /*   End Collection */
320 976f8eef balrog
    0xc0,                /* End Collection */
321 59ae540c bellard
};
322 59ae540c bellard
323 09b26c5e bellard
static const uint8_t qemu_tablet_hid_report_descriptor[] = {
324 976f8eef balrog
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
325 976f8eef balrog
    0x09, 0x01,                /* Usage (Pointer) */
326 976f8eef balrog
    0xa1, 0x01,                /* Collection (Application) */
327 976f8eef balrog
    0x09, 0x01,                /*   Usage (Pointer) */
328 976f8eef balrog
    0xa1, 0x00,                /*   Collection (Physical) */
329 976f8eef balrog
    0x05, 0x09,                /*     Usage Page (Button) */
330 976f8eef balrog
    0x19, 0x01,                /*     Usage Minimum (1) */
331 976f8eef balrog
    0x29, 0x03,                /*     Usage Maximum (3) */
332 976f8eef balrog
    0x15, 0x00,                /*     Logical Minimum (0) */
333 976f8eef balrog
    0x25, 0x01,                /*     Logical Maximum (1) */
334 976f8eef balrog
    0x95, 0x03,                /*     Report Count (3) */
335 976f8eef balrog
    0x75, 0x01,                /*     Report Size (1) */
336 976f8eef balrog
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
337 976f8eef balrog
    0x95, 0x01,                /*     Report Count (1) */
338 976f8eef balrog
    0x75, 0x05,                /*     Report Size (5) */
339 976f8eef balrog
    0x81, 0x01,                /*     Input (Constant) */
340 976f8eef balrog
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
341 976f8eef balrog
    0x09, 0x30,                /*     Usage (X) */
342 976f8eef balrog
    0x09, 0x31,                /*     Usage (Y) */
343 976f8eef balrog
    0x15, 0x00,                /*     Logical Minimum (0) */
344 de5c2d0a balrog
    0x26, 0xff, 0x7f,        /*     Logical Maximum (0x7fff) */
345 976f8eef balrog
    0x35, 0x00,                /*     Physical Minimum (0) */
346 de5c2d0a balrog
    0x46, 0xff, 0x7f,        /*     Physical Maximum (0x7fff) */
347 976f8eef balrog
    0x75, 0x10,                /*     Report Size (16) */
348 976f8eef balrog
    0x95, 0x02,                /*     Report Count (2) */
349 976f8eef balrog
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
350 976f8eef balrog
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
351 976f8eef balrog
    0x09, 0x38,                /*     Usage (Wheel) */
352 976f8eef balrog
    0x15, 0x81,                /*     Logical Minimum (-0x7f) */
353 976f8eef balrog
    0x25, 0x7f,                /*     Logical Maximum (0x7f) */
354 976f8eef balrog
    0x35, 0x00,                /*     Physical Minimum (same as logical) */
355 976f8eef balrog
    0x45, 0x00,                /*     Physical Maximum (same as logical) */
356 976f8eef balrog
    0x75, 0x08,                /*     Report Size (8) */
357 976f8eef balrog
    0x95, 0x01,                /*     Report Count (1) */
358 976f8eef balrog
    0x81, 0x06,                /*     Input (Data, Variable, Relative) */
359 976f8eef balrog
    0xc0,                /*   End Collection */
360 976f8eef balrog
    0xc0,                /* End Collection */
361 09b26c5e bellard
};
362 09b26c5e bellard
363 47b2d338 balrog
static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
364 47b2d338 balrog
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
365 47b2d338 balrog
    0x09, 0x06,                /* Usage (Keyboard) */
366 47b2d338 balrog
    0xa1, 0x01,                /* Collection (Application) */
367 47b2d338 balrog
    0x75, 0x01,                /*   Report Size (1) */
368 47b2d338 balrog
    0x95, 0x08,                /*   Report Count (8) */
369 47b2d338 balrog
    0x05, 0x07,                /*   Usage Page (Key Codes) */
370 47b2d338 balrog
    0x19, 0xe0,                /*   Usage Minimum (224) */
371 47b2d338 balrog
    0x29, 0xe7,                /*   Usage Maximum (231) */
372 47b2d338 balrog
    0x15, 0x00,                /*   Logical Minimum (0) */
373 47b2d338 balrog
    0x25, 0x01,                /*   Logical Maximum (1) */
374 47b2d338 balrog
    0x81, 0x02,                /*   Input (Data, Variable, Absolute) */
375 47b2d338 balrog
    0x95, 0x01,                /*   Report Count (1) */
376 47b2d338 balrog
    0x75, 0x08,                /*   Report Size (8) */
377 47b2d338 balrog
    0x81, 0x01,                /*   Input (Constant) */
378 47b2d338 balrog
    0x95, 0x05,                /*   Report Count (5) */
379 47b2d338 balrog
    0x75, 0x01,                /*   Report Size (1) */
380 47b2d338 balrog
    0x05, 0x08,                /*   Usage Page (LEDs) */
381 47b2d338 balrog
    0x19, 0x01,                /*   Usage Minimum (1) */
382 47b2d338 balrog
    0x29, 0x05,                /*   Usage Maximum (5) */
383 47b2d338 balrog
    0x91, 0x02,                /*   Output (Data, Variable, Absolute) */
384 47b2d338 balrog
    0x95, 0x01,                /*   Report Count (1) */
385 47b2d338 balrog
    0x75, 0x03,                /*   Report Size (3) */
386 47b2d338 balrog
    0x91, 0x01,                /*   Output (Constant) */
387 47b2d338 balrog
    0x95, 0x06,                /*   Report Count (6) */
388 47b2d338 balrog
    0x75, 0x08,                /*   Report Size (8) */
389 47b2d338 balrog
    0x15, 0x00,                /*   Logical Minimum (0) */
390 47b2d338 balrog
    0x25, 0xff,                /*   Logical Maximum (255) */
391 47b2d338 balrog
    0x05, 0x07,                /*   Usage Page (Key Codes) */
392 47b2d338 balrog
    0x19, 0x00,                /*   Usage Minimum (0) */
393 47b2d338 balrog
    0x29, 0xff,                /*   Usage Maximum (255) */
394 47b2d338 balrog
    0x81, 0x00,                /*   Input (Data, Array) */
395 47b2d338 balrog
    0xc0,                /* End Collection */
396 47b2d338 balrog
};
397 47b2d338 balrog
398 47b2d338 balrog
#define USB_HID_USAGE_ERROR_ROLLOVER        0x01
399 47b2d338 balrog
#define USB_HID_USAGE_POSTFAIL                0x02
400 47b2d338 balrog
#define USB_HID_USAGE_ERROR_UNDEFINED        0x03
401 47b2d338 balrog
402 47b2d338 balrog
/* Indices are QEMU keycodes, values are from HID Usage Table.  Indices
403 47b2d338 balrog
 * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d.  */
404 47b2d338 balrog
static const uint8_t usb_hid_usage_keys[0x100] = {
405 47b2d338 balrog
    0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
406 47b2d338 balrog
    0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b,
407 47b2d338 balrog
    0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c,
408 47b2d338 balrog
    0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16,
409 47b2d338 balrog
    0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33,
410 47b2d338 balrog
    0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19,
411 47b2d338 balrog
    0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55,
412 47b2d338 balrog
    0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
413 47b2d338 balrog
    0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f,
414 47b2d338 balrog
    0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59,
415 47b2d338 balrog
    0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44,
416 47b2d338 balrog
    0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
417 47b2d338 balrog
    0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
418 47b2d338 balrog
    0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
419 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
421 47b2d338 balrog
422 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
423 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
424 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
425 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00,
426 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
427 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46,
429 47b2d338 balrog
    0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
431 47b2d338 balrog
    0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
432 47b2d338 balrog
    0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
433 a8fb7ff3 Michael Tokarev
    0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
434 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 47b2d338 balrog
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438 47b2d338 balrog
};
439 47b2d338 balrog
440 47e699dc balrog
static void usb_hid_changed(USBHIDState *hs)
441 47e699dc balrog
{
442 47e699dc balrog
    hs->changed = 1;
443 47e699dc balrog
444 47e699dc balrog
    if (hs->datain)
445 47e699dc balrog
        hs->datain(hs->datain_opaque);
446 ac57bbb6 Gerd Hoffmann
447 ac57bbb6 Gerd Hoffmann
    usb_wakeup(&hs->dev);
448 47e699dc balrog
}
449 47e699dc balrog
450 13f8b97a Paolo Bonzini
static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
451 13f8b97a Paolo Bonzini
    e->xdx = e->ydy = e->dz = 0;
452 13f8b97a Paolo Bonzini
    e->buttons_state = buttons;
453 13f8b97a Paolo Bonzini
}
454 47e699dc balrog
455 13f8b97a Paolo Bonzini
static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,
456 13f8b97a Paolo Bonzini
                                      int x1, int y1, int z1) {
457 13f8b97a Paolo Bonzini
    if (xyrel) {
458 13f8b97a Paolo Bonzini
        e->xdx += x1;
459 13f8b97a Paolo Bonzini
        e->ydy += y1;
460 13f8b97a Paolo Bonzini
    } else {
461 13f8b97a Paolo Bonzini
        e->xdx = x1;
462 13f8b97a Paolo Bonzini
        e->ydy = y1;
463 13f8b97a Paolo Bonzini
    }
464 13f8b97a Paolo Bonzini
    e->dz += z1;
465 59ae540c bellard
}
466 59ae540c bellard
467 13f8b97a Paolo Bonzini
static void usb_pointer_event(void *opaque,
468 13f8b97a Paolo Bonzini
                              int x1, int y1, int z1, int buttons_state)
469 09b26c5e bellard
{
470 117b3ae6 pbrook
    USBHIDState *hs = opaque;
471 117b3ae6 pbrook
    USBMouseState *s = &hs->ptr;
472 42292d4e Gerd Hoffmann
    unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
473 13f8b97a Paolo Bonzini
    unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
474 13f8b97a Paolo Bonzini
475 13f8b97a Paolo Bonzini
    /* We combine events where feasible to keep the queue small.  We shouldn't
476 13f8b97a Paolo Bonzini
     * combine anything with the first event of a particular button state, as
477 13f8b97a Paolo Bonzini
     * that would change the location of the button state change.  When the
478 13f8b97a Paolo Bonzini
     * queue is empty, a second event is needed because we don't know if
479 13f8b97a Paolo Bonzini
     * the first event changed the button state.  */
480 42292d4e Gerd Hoffmann
    if (hs->n == QUEUE_LENGTH) {
481 13f8b97a Paolo Bonzini
        /* Queue full.  Discard old button state, combine motion normally.  */
482 13f8b97a Paolo Bonzini
        s->queue[use_slot].buttons_state = buttons_state;
483 42292d4e Gerd Hoffmann
    } else if (hs->n < 2 ||
484 13f8b97a Paolo Bonzini
               s->queue[use_slot].buttons_state != buttons_state ||
485 13f8b97a Paolo Bonzini
               s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
486 13f8b97a Paolo Bonzini
        /* Cannot or should not combine, so add an empty item to the queue.  */
487 13f8b97a Paolo Bonzini
        QUEUE_INCR(use_slot);
488 42292d4e Gerd Hoffmann
        hs->n++;
489 13f8b97a Paolo Bonzini
        usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
490 13f8b97a Paolo Bonzini
    }
491 13f8b97a Paolo Bonzini
    usb_pointer_event_combine(&s->queue[use_slot],
492 13f8b97a Paolo Bonzini
                              hs->kind == USB_MOUSE,
493 13f8b97a Paolo Bonzini
                              x1, y1, z1);
494 47e699dc balrog
    usb_hid_changed(hs);
495 09b26c5e bellard
}
496 09b26c5e bellard
497 47b2d338 balrog
static void usb_keyboard_event(void *opaque, int keycode)
498 47b2d338 balrog
{
499 117b3ae6 pbrook
    USBHIDState *hs = opaque;
500 117b3ae6 pbrook
    USBKeyboardState *s = &hs->kbd;
501 5fae51a9 Gerd Hoffmann
    int slot;
502 5fae51a9 Gerd Hoffmann
503 42292d4e Gerd Hoffmann
    if (hs->n == QUEUE_LENGTH) {
504 5fae51a9 Gerd Hoffmann
        fprintf(stderr, "usb-kbd: warning: key event queue full\n");
505 5fae51a9 Gerd Hoffmann
        return;
506 5fae51a9 Gerd Hoffmann
    }
507 42292d4e Gerd Hoffmann
    slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
508 5fae51a9 Gerd Hoffmann
    s->keycodes[slot] = keycode;
509 5fae51a9 Gerd Hoffmann
    usb_hid_changed(hs);
510 5fae51a9 Gerd Hoffmann
}
511 5fae51a9 Gerd Hoffmann
512 42292d4e Gerd Hoffmann
static void usb_keyboard_process_keycode(USBHIDState *hs)
513 5fae51a9 Gerd Hoffmann
{
514 42292d4e Gerd Hoffmann
    USBKeyboardState *s = &hs->kbd;
515 47b2d338 balrog
    uint8_t hid_code, key;
516 5fae51a9 Gerd Hoffmann
    int i, keycode, slot;
517 5fae51a9 Gerd Hoffmann
518 42292d4e Gerd Hoffmann
    if (hs->n == 0) {
519 5fae51a9 Gerd Hoffmann
        return;
520 5fae51a9 Gerd Hoffmann
    }
521 42292d4e Gerd Hoffmann
    slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
522 5fae51a9 Gerd Hoffmann
    keycode = s->keycodes[slot];
523 47b2d338 balrog
524 47b2d338 balrog
    key = keycode & 0x7f;
525 47b2d338 balrog
    hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
526 47b2d338 balrog
    s->modifiers &= ~(1 << 8);
527 47b2d338 balrog
528 47b2d338 balrog
    switch (hid_code) {
529 47b2d338 balrog
    case 0x00:
530 47b2d338 balrog
        return;
531 47b2d338 balrog
532 47b2d338 balrog
    case 0xe0:
533 47b2d338 balrog
        if (s->modifiers & (1 << 9)) {
534 47b2d338 balrog
            s->modifiers ^= 3 << 8;
535 373dfc44 Aurelien Jarno
            usb_hid_changed(hs);
536 47b2d338 balrog
            return;
537 47b2d338 balrog
        }
538 47b2d338 balrog
    case 0xe1 ... 0xe7:
539 47b2d338 balrog
        if (keycode & (1 << 7)) {
540 47b2d338 balrog
            s->modifiers &= ~(1 << (hid_code & 0x0f));
541 373dfc44 Aurelien Jarno
            usb_hid_changed(hs);
542 47b2d338 balrog
            return;
543 47b2d338 balrog
        }
544 47b2d338 balrog
    case 0xe8 ... 0xef:
545 47b2d338 balrog
        s->modifiers |= 1 << (hid_code & 0x0f);
546 373dfc44 Aurelien Jarno
        usb_hid_changed(hs);
547 47b2d338 balrog
        return;
548 47b2d338 balrog
    }
549 47b2d338 balrog
550 47b2d338 balrog
    if (keycode & (1 << 7)) {
551 47b2d338 balrog
        for (i = s->keys - 1; i >= 0; i --)
552 47b2d338 balrog
            if (s->key[i] == hid_code) {
553 47b2d338 balrog
                s->key[i] = s->key[-- s->keys];
554 47b2d338 balrog
                s->key[s->keys] = 0x00;
555 47e699dc balrog
                break;
556 47b2d338 balrog
            }
557 47e699dc balrog
        if (i < 0)
558 47e699dc balrog
            return;
559 47b2d338 balrog
    } else {
560 47b2d338 balrog
        for (i = s->keys - 1; i >= 0; i --)
561 47b2d338 balrog
            if (s->key[i] == hid_code)
562 47e699dc balrog
                break;
563 47e699dc balrog
        if (i < 0) {
564 47e699dc balrog
            if (s->keys < sizeof(s->key))
565 47e699dc balrog
                s->key[s->keys ++] = hid_code;
566 47e699dc balrog
        } else
567 47e699dc balrog
            return;
568 47b2d338 balrog
    }
569 47b2d338 balrog
}
570 47b2d338 balrog
571 59ae540c bellard
static inline int int_clamp(int val, int vmin, int vmax)
572 59ae540c bellard
{
573 59ae540c bellard
    if (val < vmin)
574 59ae540c bellard
        return vmin;
575 59ae540c bellard
    else if (val > vmax)
576 59ae540c bellard
        return vmax;
577 59ae540c bellard
    else
578 59ae540c bellard
        return val;
579 59ae540c bellard
}
580 59ae540c bellard
581 13f8b97a Paolo Bonzini
static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
582 59ae540c bellard
{
583 59ae540c bellard
    int dx, dy, dz, b, l;
584 13f8b97a Paolo Bonzini
    int index;
585 117b3ae6 pbrook
    USBMouseState *s = &hs->ptr;
586 13f8b97a Paolo Bonzini
    USBPointerEvent *e;
587 59ae540c bellard
588 09b26c5e bellard
    if (!s->mouse_grabbed) {
589 6fef28ee Anthony Liguori
        qemu_activate_mouse_event_handler(s->eh_entry);
590 13f8b97a Paolo Bonzini
        s->mouse_grabbed = 1;
591 09b26c5e bellard
    }
592 3b46e624 ths
593 13f8b97a Paolo Bonzini
    /* When the buffer is empty, return the last event.  Relative
594 13f8b97a Paolo Bonzini
       movements will all be zero.  */
595 42292d4e Gerd Hoffmann
    index = (hs->n ? hs->head : hs->head - 1);
596 13f8b97a Paolo Bonzini
    e = &s->queue[index & QUEUE_MASK];
597 3b46e624 ths
598 13f8b97a Paolo Bonzini
    if (hs->kind == USB_MOUSE) {
599 13f8b97a Paolo Bonzini
        dx = int_clamp(e->xdx, -127, 127);
600 13f8b97a Paolo Bonzini
        dy = int_clamp(e->ydy, -127, 127);
601 13f8b97a Paolo Bonzini
        e->xdx -= dx;
602 13f8b97a Paolo Bonzini
        e->ydy -= dy;
603 13f8b97a Paolo Bonzini
    } else {
604 13f8b97a Paolo Bonzini
        dx = e->xdx;
605 13f8b97a Paolo Bonzini
        dy = e->ydy;
606 13f8b97a Paolo Bonzini
    }
607 13f8b97a Paolo Bonzini
    dz = int_clamp(e->dz, -127, 127);
608 13f8b97a Paolo Bonzini
    e->dz -= dz;
609 976f8eef balrog
610 59ae540c bellard
    b = 0;
611 13f8b97a Paolo Bonzini
    if (e->buttons_state & MOUSE_EVENT_LBUTTON)
612 59ae540c bellard
        b |= 0x01;
613 13f8b97a Paolo Bonzini
    if (e->buttons_state & MOUSE_EVENT_RBUTTON)
614 59ae540c bellard
        b |= 0x02;
615 13f8b97a Paolo Bonzini
    if (e->buttons_state & MOUSE_EVENT_MBUTTON)
616 59ae540c bellard
        b |= 0x04;
617 3b46e624 ths
618 42292d4e Gerd Hoffmann
    if (hs->n &&
619 13f8b97a Paolo Bonzini
        !e->dz &&
620 13f8b97a Paolo Bonzini
        (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
621 13f8b97a Paolo Bonzini
        /* that deals with this event */
622 42292d4e Gerd Hoffmann
        QUEUE_INCR(hs->head);
623 42292d4e Gerd Hoffmann
        hs->n--;
624 09b26c5e bellard
    }
625 3b46e624 ths
626 09b26c5e bellard
    /* Appears we have to invert the wheel direction */
627 09b26c5e bellard
    dz = 0 - dz;
628 13f8b97a Paolo Bonzini
    l = 0;
629 13f8b97a Paolo Bonzini
    switch (hs->kind) {
630 13f8b97a Paolo Bonzini
    case USB_MOUSE:
631 13f8b97a Paolo Bonzini
        if (len > l)
632 13f8b97a Paolo Bonzini
            buf[l++] = b;
633 13f8b97a Paolo Bonzini
        if (len > l)
634 13f8b97a Paolo Bonzini
            buf[l++] = dx;
635 13f8b97a Paolo Bonzini
        if (len > l)
636 13f8b97a Paolo Bonzini
            buf[l++] = dy;
637 13f8b97a Paolo Bonzini
        if (len > l)
638 13f8b97a Paolo Bonzini
            buf[l++] = dz;
639 13f8b97a Paolo Bonzini
        break;
640 09b26c5e bellard
641 13f8b97a Paolo Bonzini
    case USB_TABLET:
642 13f8b97a Paolo Bonzini
        if (len > l)
643 13f8b97a Paolo Bonzini
            buf[l++] = b;
644 13f8b97a Paolo Bonzini
        if (len > l)
645 13f8b97a Paolo Bonzini
            buf[l++] = dx & 0xff;
646 13f8b97a Paolo Bonzini
        if (len > l)
647 13f8b97a Paolo Bonzini
            buf[l++] = dx >> 8;
648 13f8b97a Paolo Bonzini
        if (len > l)
649 13f8b97a Paolo Bonzini
            buf[l++] = dy & 0xff;
650 13f8b97a Paolo Bonzini
        if (len > l)
651 13f8b97a Paolo Bonzini
            buf[l++] = dy >> 8;
652 13f8b97a Paolo Bonzini
        if (len > l)
653 13f8b97a Paolo Bonzini
            buf[l++] = dz;
654 13f8b97a Paolo Bonzini
        break;
655 13f8b97a Paolo Bonzini
656 13f8b97a Paolo Bonzini
    default:
657 13f8b97a Paolo Bonzini
        abort();
658 13f8b97a Paolo Bonzini
    }
659 09b26c5e bellard
660 09b26c5e bellard
    return l;
661 09b26c5e bellard
}
662 09b26c5e bellard
663 13f8b97a Paolo Bonzini
static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
664 47b2d338 balrog
{
665 13f8b97a Paolo Bonzini
    USBKeyboardState *s = &hs->kbd;
666 47b2d338 balrog
    if (len < 2)
667 47b2d338 balrog
        return 0;
668 47b2d338 balrog
669 42292d4e Gerd Hoffmann
    usb_keyboard_process_keycode(hs);
670 5fae51a9 Gerd Hoffmann
671 47b2d338 balrog
    buf[0] = s->modifiers & 0xff;
672 47b2d338 balrog
    buf[1] = 0;
673 47b2d338 balrog
    if (s->keys > 6)
674 47b2d338 balrog
        memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2);
675 47b2d338 balrog
    else
676 47b2d338 balrog
        memcpy(buf + 2, s->key, MIN(8, len) - 2);
677 47b2d338 balrog
678 47b2d338 balrog
    return MIN(8, len);
679 47b2d338 balrog
}
680 47b2d338 balrog
681 47b2d338 balrog
static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len)
682 47b2d338 balrog
{
683 47b2d338 balrog
    if (len > 0) {
684 bd87813e Gerd Hoffmann
        int ledstate = 0;
685 47b2d338 balrog
        /* 0x01: Num Lock LED
686 47b2d338 balrog
         * 0x02: Caps Lock LED
687 47b2d338 balrog
         * 0x04: Scroll Lock LED
688 47b2d338 balrog
         * 0x08: Compose LED
689 47b2d338 balrog
         * 0x10: Kana LED */
690 47b2d338 balrog
        s->leds = buf[0];
691 bd87813e Gerd Hoffmann
        if (s->leds & 0x04)
692 bd87813e Gerd Hoffmann
            ledstate |= QEMU_SCROLL_LOCK_LED;
693 bd87813e Gerd Hoffmann
        if (s->leds & 0x01)
694 bd87813e Gerd Hoffmann
            ledstate |= QEMU_NUM_LOCK_LED;
695 bd87813e Gerd Hoffmann
        if (s->leds & 0x02)
696 bd87813e Gerd Hoffmann
            ledstate |= QEMU_CAPS_LOCK_LED;
697 bd87813e Gerd Hoffmann
        kbd_put_ledstate(ledstate);
698 47b2d338 balrog
    }
699 47b2d338 balrog
    return 0;
700 47b2d338 balrog
}
701 47b2d338 balrog
702 059809e4 bellard
static void usb_mouse_handle_reset(USBDevice *dev)
703 59ae540c bellard
{
704 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
705 47b2d338 balrog
706 5fae51a9 Gerd Hoffmann
    memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
707 42292d4e Gerd Hoffmann
    s->head = 0;
708 42292d4e Gerd Hoffmann
    s->n = 0;
709 47b2d338 balrog
    s->protocol = 1;
710 47b2d338 balrog
}
711 47b2d338 balrog
712 47b2d338 balrog
static void usb_keyboard_handle_reset(USBDevice *dev)
713 47b2d338 balrog
{
714 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
715 47b2d338 balrog
716 926acf8f balrog
    qemu_add_kbd_event_handler(usb_keyboard_event, s);
717 5fae51a9 Gerd Hoffmann
    memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
718 42292d4e Gerd Hoffmann
    s->head = 0;
719 42292d4e Gerd Hoffmann
    s->n = 0;
720 5fae51a9 Gerd Hoffmann
    memset(s->kbd.key, 0, sizeof (s->kbd.key));
721 5fae51a9 Gerd Hoffmann
    s->kbd.keys = 0;
722 47b2d338 balrog
    s->protocol = 1;
723 59ae540c bellard
}
724 59ae540c bellard
725 68735b6c Kevin O'Connor
static void usb_hid_set_next_idle(USBHIDState *s, int64_t curtime)
726 68735b6c Kevin O'Connor
{
727 68735b6c Kevin O'Connor
    s->next_idle_clock = curtime + (get_ticks_per_sec() * s->idle * 4) / 1000;
728 68735b6c Kevin O'Connor
}
729 68735b6c Kevin O'Connor
730 007fd62f Hans de Goede
static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
731 007fd62f Hans de Goede
               int request, int value, int index, int length, uint8_t *data)
732 59ae540c bellard
{
733 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
734 0e4e9695 Gerd Hoffmann
    int ret;
735 59ae540c bellard
736 007fd62f Hans de Goede
    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
737 0e4e9695 Gerd Hoffmann
    if (ret >= 0) {
738 0e4e9695 Gerd Hoffmann
        return ret;
739 0e4e9695 Gerd Hoffmann
    }
740 59ae540c bellard
741 0e4e9695 Gerd Hoffmann
    ret = 0;
742 59ae540c bellard
    switch(request) {
743 59ae540c bellard
    case DeviceRequest | USB_REQ_GET_INTERFACE:
744 59ae540c bellard
        data[0] = 0;
745 59ae540c bellard
        ret = 1;
746 59ae540c bellard
        break;
747 59ae540c bellard
    case DeviceOutRequest | USB_REQ_SET_INTERFACE:
748 59ae540c bellard
        ret = 0;
749 59ae540c bellard
        break;
750 59ae540c bellard
        /* hid specific requests */
751 59ae540c bellard
    case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
752 59ae540c bellard
        switch(value >> 8) {
753 59ae540c bellard
        case 0x22:
754 09b26c5e bellard
            if (s->kind == USB_MOUSE) {
755 5fafdf24 ths
                memcpy(data, qemu_mouse_hid_report_descriptor,
756 09b26c5e bellard
                       sizeof(qemu_mouse_hid_report_descriptor));
757 09b26c5e bellard
                ret = sizeof(qemu_mouse_hid_report_descriptor);
758 09b26c5e bellard
            } else if (s->kind == USB_TABLET) {
759 5fafdf24 ths
                memcpy(data, qemu_tablet_hid_report_descriptor,
760 09b26c5e bellard
                       sizeof(qemu_tablet_hid_report_descriptor));
761 09b26c5e bellard
                ret = sizeof(qemu_tablet_hid_report_descriptor);
762 47b2d338 balrog
            } else if (s->kind == USB_KEYBOARD) {
763 5fafdf24 ths
                memcpy(data, qemu_keyboard_hid_report_descriptor,
764 47b2d338 balrog
                       sizeof(qemu_keyboard_hid_report_descriptor));
765 47b2d338 balrog
                ret = sizeof(qemu_keyboard_hid_report_descriptor);
766 47b2d338 balrog
            }
767 47b2d338 balrog
            break;
768 59ae540c bellard
        default:
769 59ae540c bellard
            goto fail;
770 59ae540c bellard
        }
771 59ae540c bellard
        break;
772 59ae540c bellard
    case GET_REPORT:
773 13f8b97a Paolo Bonzini
        if (s->kind == USB_MOUSE || s->kind == USB_TABLET)
774 13f8b97a Paolo Bonzini
            ret = usb_pointer_poll(s, data, length);
775 47b2d338 balrog
        else if (s->kind == USB_KEYBOARD)
776 13f8b97a Paolo Bonzini
            ret = usb_keyboard_poll(s, data, length);
777 47b2d338 balrog
        break;
778 47b2d338 balrog
    case SET_REPORT:
779 47b2d338 balrog
        if (s->kind == USB_KEYBOARD)
780 47b2d338 balrog
            ret = usb_keyboard_write(&s->kbd, data, length);
781 47b2d338 balrog
        else
782 47b2d338 balrog
            goto fail;
783 47b2d338 balrog
        break;
784 47b2d338 balrog
    case GET_PROTOCOL:
785 46115ac4 Kevin O'Connor
        if (s->kind != USB_KEYBOARD && s->kind != USB_MOUSE)
786 47b2d338 balrog
            goto fail;
787 47b2d338 balrog
        ret = 1;
788 47b2d338 balrog
        data[0] = s->protocol;
789 47b2d338 balrog
        break;
790 47b2d338 balrog
    case SET_PROTOCOL:
791 46115ac4 Kevin O'Connor
        if (s->kind != USB_KEYBOARD && s->kind != USB_MOUSE)
792 47b2d338 balrog
            goto fail;
793 47b2d338 balrog
        ret = 0;
794 47b2d338 balrog
        s->protocol = value;
795 47b2d338 balrog
        break;
796 47b2d338 balrog
    case GET_IDLE:
797 47b2d338 balrog
        ret = 1;
798 47b2d338 balrog
        data[0] = s->idle;
799 59ae540c bellard
        break;
800 59ae540c bellard
    case SET_IDLE:
801 181a29c5 aliguori
        s->idle = (uint8_t) (value >> 8);
802 74475455 Paolo Bonzini
        usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
803 59ae540c bellard
        ret = 0;
804 59ae540c bellard
        break;
805 59ae540c bellard
    default:
806 59ae540c bellard
    fail:
807 59ae540c bellard
        ret = USB_RET_STALL;
808 59ae540c bellard
        break;
809 59ae540c bellard
    }
810 59ae540c bellard
    return ret;
811 59ae540c bellard
}
812 59ae540c bellard
813 47b2d338 balrog
static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
814 59ae540c bellard
{
815 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
816 09b26c5e bellard
    int ret = 0;
817 59ae540c bellard
818 4d611c9a pbrook
    switch(p->pid) {
819 59ae540c bellard
    case USB_TOKEN_IN:
820 4d611c9a pbrook
        if (p->devep == 1) {
821 74475455 Paolo Bonzini
            int64_t curtime = qemu_get_clock_ns(vm_clock);
822 68735b6c Kevin O'Connor
            if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
823 117b3ae6 pbrook
                return USB_RET_NAK;
824 68735b6c Kevin O'Connor
            usb_hid_set_next_idle(s, curtime);
825 13f8b97a Paolo Bonzini
            if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
826 13f8b97a Paolo Bonzini
                ret = usb_pointer_poll(s, p->data, p->len);
827 13f8b97a Paolo Bonzini
            }
828 13f8b97a Paolo Bonzini
            else if (s->kind == USB_KEYBOARD) {
829 13f8b97a Paolo Bonzini
                ret = usb_keyboard_poll(s, p->data, p->len);
830 13f8b97a Paolo Bonzini
            }
831 42292d4e Gerd Hoffmann
            s->changed = s->n > 0;
832 59ae540c bellard
        } else {
833 59ae540c bellard
            goto fail;
834 59ae540c bellard
        }
835 59ae540c bellard
        break;
836 59ae540c bellard
    case USB_TOKEN_OUT:
837 59ae540c bellard
    default:
838 59ae540c bellard
    fail:
839 59ae540c bellard
        ret = USB_RET_STALL;
840 59ae540c bellard
        break;
841 59ae540c bellard
    }
842 59ae540c bellard
    return ret;
843 59ae540c bellard
}
844 59ae540c bellard
845 47b2d338 balrog
static void usb_hid_handle_destroy(USBDevice *dev)
846 059809e4 bellard
{
847 47b2d338 balrog
    USBHIDState *s = (USBHIDState *)dev;
848 059809e4 bellard
849 46aaebff Jes Sorensen
    switch(s->kind) {
850 46aaebff Jes Sorensen
    case USB_KEYBOARD:
851 46aaebff Jes Sorensen
        qemu_remove_kbd_event_handler();
852 46aaebff Jes Sorensen
        break;
853 46aaebff Jes Sorensen
    default:
854 47b2d338 balrog
        qemu_remove_mouse_event_handler(s->ptr.eh_entry);
855 46aaebff Jes Sorensen
    }
856 059809e4 bellard
}
857 059809e4 bellard
858 806b6024 Gerd Hoffmann
static int usb_hid_initfn(USBDevice *dev, int kind)
859 09b26c5e bellard
{
860 806b6024 Gerd Hoffmann
    USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
861 a980a065 Gerd Hoffmann
862 a980a065 Gerd Hoffmann
    usb_desc_init(dev);
863 806b6024 Gerd Hoffmann
    s->kind = kind;
864 6fef28ee Anthony Liguori
865 6fef28ee Anthony Liguori
    if (s->kind == USB_MOUSE) {
866 13f8b97a Paolo Bonzini
        s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
867 6fef28ee Anthony Liguori
                                                       0, "QEMU USB Mouse");
868 6fef28ee Anthony Liguori
    } else if (s->kind == USB_TABLET) {
869 13f8b97a Paolo Bonzini
        s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
870 6fef28ee Anthony Liguori
                                                       1, "QEMU USB Tablet");
871 6fef28ee Anthony Liguori
    }
872 13f8b97a Paolo Bonzini
873 117b3ae6 pbrook
    /* Force poll routine to be run and grab input the first time.  */
874 117b3ae6 pbrook
    s->changed = 1;
875 806b6024 Gerd Hoffmann
    return 0;
876 09b26c5e bellard
}
877 09b26c5e bellard
878 806b6024 Gerd Hoffmann
static int usb_tablet_initfn(USBDevice *dev)
879 59ae540c bellard
{
880 806b6024 Gerd Hoffmann
    return usb_hid_initfn(dev, USB_TABLET);
881 806b6024 Gerd Hoffmann
}
882 59ae540c bellard
883 806b6024 Gerd Hoffmann
static int usb_mouse_initfn(USBDevice *dev)
884 806b6024 Gerd Hoffmann
{
885 806b6024 Gerd Hoffmann
    return usb_hid_initfn(dev, USB_MOUSE);
886 806b6024 Gerd Hoffmann
}
887 59ae540c bellard
888 806b6024 Gerd Hoffmann
static int usb_keyboard_initfn(USBDevice *dev)
889 806b6024 Gerd Hoffmann
{
890 806b6024 Gerd Hoffmann
    return usb_hid_initfn(dev, USB_KEYBOARD);
891 806b6024 Gerd Hoffmann
}
892 59ae540c bellard
893 47e699dc balrog
void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
894 47e699dc balrog
{
895 47e699dc balrog
    USBHIDState *s = (USBHIDState *)dev;
896 47e699dc balrog
897 47e699dc balrog
    s->datain_opaque = opaque;
898 47e699dc balrog
    s->datain = datain;
899 47e699dc balrog
}
900 806b6024 Gerd Hoffmann
901 ee59e6b3 Gerd Hoffmann
static int usb_hid_post_load(void *opaque, int version_id)
902 ee59e6b3 Gerd Hoffmann
{
903 ee59e6b3 Gerd Hoffmann
    USBHIDState *s = opaque;
904 ee59e6b3 Gerd Hoffmann
905 ee59e6b3 Gerd Hoffmann
    if (s->idle) {
906 74475455 Paolo Bonzini
        usb_hid_set_next_idle(s, qemu_get_clock_ns(vm_clock));
907 ee59e6b3 Gerd Hoffmann
    }
908 ee59e6b3 Gerd Hoffmann
    return 0;
909 ee59e6b3 Gerd Hoffmann
}
910 ee59e6b3 Gerd Hoffmann
911 ee59e6b3 Gerd Hoffmann
static const VMStateDescription vmstate_usb_ptr_queue = {
912 ee59e6b3 Gerd Hoffmann
    .name = "usb-ptr-queue",
913 ee59e6b3 Gerd Hoffmann
    .version_id = 1,
914 ee59e6b3 Gerd Hoffmann
    .minimum_version_id = 1,
915 ee59e6b3 Gerd Hoffmann
    .fields = (VMStateField []) {
916 ee59e6b3 Gerd Hoffmann
        VMSTATE_INT32(xdx, USBPointerEvent),
917 ee59e6b3 Gerd Hoffmann
        VMSTATE_INT32(ydy, USBPointerEvent),
918 ee59e6b3 Gerd Hoffmann
        VMSTATE_INT32(dz, USBPointerEvent),
919 ee59e6b3 Gerd Hoffmann
        VMSTATE_INT32(buttons_state, USBPointerEvent),
920 ee59e6b3 Gerd Hoffmann
        VMSTATE_END_OF_LIST()
921 ee59e6b3 Gerd Hoffmann
    }
922 ee59e6b3 Gerd Hoffmann
};
923 ee59e6b3 Gerd Hoffmann
static const VMStateDescription vmstate_usb_ptr = {
924 ee59e6b3 Gerd Hoffmann
    .name = "usb-ptr",
925 ee59e6b3 Gerd Hoffmann
    .version_id = 1,
926 ee59e6b3 Gerd Hoffmann
    .minimum_version_id = 1,
927 ee59e6b3 Gerd Hoffmann
    .post_load = usb_hid_post_load,
928 ee59e6b3 Gerd Hoffmann
    .fields = (VMStateField []) {
929 ee59e6b3 Gerd Hoffmann
        VMSTATE_USB_DEVICE(dev, USBHIDState),
930 ee59e6b3 Gerd Hoffmann
        VMSTATE_STRUCT_ARRAY(ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
931 ee59e6b3 Gerd Hoffmann
                             vmstate_usb_ptr_queue, USBPointerEvent),
932 ee59e6b3 Gerd Hoffmann
        VMSTATE_UINT32(head, USBHIDState),
933 ee59e6b3 Gerd Hoffmann
        VMSTATE_UINT32(n, USBHIDState),
934 ee59e6b3 Gerd Hoffmann
        VMSTATE_INT32(protocol, USBHIDState),
935 ee59e6b3 Gerd Hoffmann
        VMSTATE_UINT8(idle, USBHIDState),
936 ee59e6b3 Gerd Hoffmann
        VMSTATE_END_OF_LIST()
937 ee59e6b3 Gerd Hoffmann
    }
938 ee59e6b3 Gerd Hoffmann
};
939 ee59e6b3 Gerd Hoffmann
940 ee59e6b3 Gerd Hoffmann
static const VMStateDescription vmstate_usb_kbd = {
941 ee59e6b3 Gerd Hoffmann
    .name = "usb-kbd",
942 ee59e6b3 Gerd Hoffmann
    .version_id = 1,
943 ee59e6b3 Gerd Hoffmann
    .minimum_version_id = 1,
944 ee59e6b3 Gerd Hoffmann
    .post_load = usb_hid_post_load,
945 ee59e6b3 Gerd Hoffmann
    .fields = (VMStateField []) {
946 ee59e6b3 Gerd Hoffmann
        VMSTATE_USB_DEVICE(dev, USBHIDState),
947 ee59e6b3 Gerd Hoffmann
        VMSTATE_UINT32_ARRAY(kbd.keycodes, USBHIDState, QUEUE_LENGTH),
948 ee59e6b3 Gerd Hoffmann
        VMSTATE_UINT32(head, USBHIDState),
949 ee59e6b3 Gerd Hoffmann
        VMSTATE_UINT32(n, USBHIDState),
950 ee59e6b3 Gerd Hoffmann
        VMSTATE_UINT16(kbd.modifiers, USBHIDState),
951 ee59e6b3 Gerd Hoffmann
        VMSTATE_UINT8(kbd.leds, USBHIDState),
952 ee59e6b3 Gerd Hoffmann
        VMSTATE_UINT8_ARRAY(kbd.key, USBHIDState, 16),
953 ee59e6b3 Gerd Hoffmann
        VMSTATE_INT32(kbd.keys, USBHIDState),
954 ee59e6b3 Gerd Hoffmann
        VMSTATE_INT32(protocol, USBHIDState),
955 ee59e6b3 Gerd Hoffmann
        VMSTATE_UINT8(idle, USBHIDState),
956 ee59e6b3 Gerd Hoffmann
        VMSTATE_END_OF_LIST()
957 ee59e6b3 Gerd Hoffmann
    }
958 ee59e6b3 Gerd Hoffmann
};
959 ee59e6b3 Gerd Hoffmann
960 806b6024 Gerd Hoffmann
static struct USBDeviceInfo hid_info[] = {
961 806b6024 Gerd Hoffmann
    {
962 06384698 Markus Armbruster
        .product_desc   = "QEMU USB Tablet",
963 556cd098 Markus Armbruster
        .qdev.name      = "usb-tablet",
964 fa7c70c3 Gerd Hoffmann
        .usbdevice_name = "tablet",
965 806b6024 Gerd Hoffmann
        .qdev.size      = sizeof(USBHIDState),
966 ee59e6b3 Gerd Hoffmann
        .qdev.vmsd      = &vmstate_usb_ptr,
967 0e4e9695 Gerd Hoffmann
        .usb_desc       = &desc_tablet,
968 806b6024 Gerd Hoffmann
        .init           = usb_tablet_initfn,
969 806b6024 Gerd Hoffmann
        .handle_packet  = usb_generic_handle_packet,
970 806b6024 Gerd Hoffmann
        .handle_reset   = usb_mouse_handle_reset,
971 806b6024 Gerd Hoffmann
        .handle_control = usb_hid_handle_control,
972 806b6024 Gerd Hoffmann
        .handle_data    = usb_hid_handle_data,
973 806b6024 Gerd Hoffmann
        .handle_destroy = usb_hid_handle_destroy,
974 806b6024 Gerd Hoffmann
    },{
975 06384698 Markus Armbruster
        .product_desc   = "QEMU USB Mouse",
976 556cd098 Markus Armbruster
        .qdev.name      = "usb-mouse",
977 fa7c70c3 Gerd Hoffmann
        .usbdevice_name = "mouse",
978 806b6024 Gerd Hoffmann
        .qdev.size      = sizeof(USBHIDState),
979 ee59e6b3 Gerd Hoffmann
        .qdev.vmsd      = &vmstate_usb_ptr,
980 0e4e9695 Gerd Hoffmann
        .usb_desc       = &desc_mouse,
981 806b6024 Gerd Hoffmann
        .init           = usb_mouse_initfn,
982 806b6024 Gerd Hoffmann
        .handle_packet  = usb_generic_handle_packet,
983 806b6024 Gerd Hoffmann
        .handle_reset   = usb_mouse_handle_reset,
984 806b6024 Gerd Hoffmann
        .handle_control = usb_hid_handle_control,
985 806b6024 Gerd Hoffmann
        .handle_data    = usb_hid_handle_data,
986 806b6024 Gerd Hoffmann
        .handle_destroy = usb_hid_handle_destroy,
987 806b6024 Gerd Hoffmann
    },{
988 06384698 Markus Armbruster
        .product_desc   = "QEMU USB Keyboard",
989 556cd098 Markus Armbruster
        .qdev.name      = "usb-kbd",
990 fa7c70c3 Gerd Hoffmann
        .usbdevice_name = "keyboard",
991 806b6024 Gerd Hoffmann
        .qdev.size      = sizeof(USBHIDState),
992 ee59e6b3 Gerd Hoffmann
        .qdev.vmsd      = &vmstate_usb_kbd,
993 0e4e9695 Gerd Hoffmann
        .usb_desc       = &desc_keyboard,
994 806b6024 Gerd Hoffmann
        .init           = usb_keyboard_initfn,
995 806b6024 Gerd Hoffmann
        .handle_packet  = usb_generic_handle_packet,
996 806b6024 Gerd Hoffmann
        .handle_reset   = usb_keyboard_handle_reset,
997 806b6024 Gerd Hoffmann
        .handle_control = usb_hid_handle_control,
998 806b6024 Gerd Hoffmann
        .handle_data    = usb_hid_handle_data,
999 806b6024 Gerd Hoffmann
        .handle_destroy = usb_hid_handle_destroy,
1000 806b6024 Gerd Hoffmann
    },{
1001 806b6024 Gerd Hoffmann
        /* end of list */
1002 806b6024 Gerd Hoffmann
    }
1003 806b6024 Gerd Hoffmann
};
1004 806b6024 Gerd Hoffmann
1005 806b6024 Gerd Hoffmann
static void usb_hid_register_devices(void)
1006 806b6024 Gerd Hoffmann
{
1007 806b6024 Gerd Hoffmann
    usb_qdev_register_many(hid_info);
1008 806b6024 Gerd Hoffmann
}
1009 806b6024 Gerd Hoffmann
device_init(usb_hid_register_devices)