Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ a1f0cce2

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