Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ 69bf405b

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