Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ 0d878eec

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