Statistics
| Branch: | Revision:

root / hw / usb-hid.c @ c9c3c80a

History | View | Annotate | Download (19.5 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 dcfda673 Gerd Hoffmann
#include "hid.h"
31 59ae540c bellard
32 59ae540c bellard
/* HID interface requests */
33 59ae540c bellard
#define GET_REPORT   0xa101
34 59ae540c bellard
#define GET_IDLE     0xa102
35 59ae540c bellard
#define GET_PROTOCOL 0xa103
36 47b2d338 balrog
#define SET_REPORT   0x2109
37 59ae540c bellard
#define SET_IDLE     0x210a
38 59ae540c bellard
#define SET_PROTOCOL 0x210b
39 59ae540c bellard
40 47b2d338 balrog
/* HID descriptor types */
41 47b2d338 balrog
#define USB_DT_HID    0x21
42 47b2d338 balrog
#define USB_DT_REPORT 0x22
43 47b2d338 balrog
#define USB_DT_PHY    0x23
44 47b2d338 balrog
45 0d878eec Gerd Hoffmann
typedef struct USBHIDState {
46 0d878eec Gerd Hoffmann
    USBDevice dev;
47 0d878eec Gerd Hoffmann
    HIDState hid;
48 47b2d338 balrog
} USBHIDState;
49 47b2d338 balrog
50 0e4e9695 Gerd Hoffmann
enum {
51 0e4e9695 Gerd Hoffmann
    STR_MANUFACTURER = 1,
52 0e4e9695 Gerd Hoffmann
    STR_PRODUCT_MOUSE,
53 0e4e9695 Gerd Hoffmann
    STR_PRODUCT_TABLET,
54 0e4e9695 Gerd Hoffmann
    STR_PRODUCT_KEYBOARD,
55 0e4e9695 Gerd Hoffmann
    STR_SERIALNUMBER,
56 0e4e9695 Gerd Hoffmann
    STR_CONFIG_MOUSE,
57 0e4e9695 Gerd Hoffmann
    STR_CONFIG_TABLET,
58 0e4e9695 Gerd Hoffmann
    STR_CONFIG_KEYBOARD,
59 59ae540c bellard
};
60 59ae540c bellard
61 0e4e9695 Gerd Hoffmann
static const USBDescStrings desc_strings = {
62 0e4e9695 Gerd Hoffmann
    [STR_MANUFACTURER]     = "QEMU " QEMU_VERSION,
63 0e4e9695 Gerd Hoffmann
    [STR_PRODUCT_MOUSE]    = "QEMU USB Mouse",
64 0e4e9695 Gerd Hoffmann
    [STR_PRODUCT_TABLET]   = "QEMU USB Tablet",
65 0e4e9695 Gerd Hoffmann
    [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
66 7b074a22 Gerd Hoffmann
    [STR_SERIALNUMBER]     = "42", /* == remote wakeup works */
67 0e4e9695 Gerd Hoffmann
    [STR_CONFIG_MOUSE]     = "HID Mouse",
68 0e4e9695 Gerd Hoffmann
    [STR_CONFIG_TABLET]    = "HID Tablet",
69 0e4e9695 Gerd Hoffmann
    [STR_CONFIG_KEYBOARD]  = "HID Keyboard",
70 09b26c5e bellard
};
71 09b26c5e bellard
72 0e4e9695 Gerd Hoffmann
static const USBDescIface desc_iface_mouse = {
73 0e4e9695 Gerd Hoffmann
    .bInterfaceNumber              = 0,
74 0e4e9695 Gerd Hoffmann
    .bNumEndpoints                 = 1,
75 0e4e9695 Gerd Hoffmann
    .bInterfaceClass               = USB_CLASS_HID,
76 0e4e9695 Gerd Hoffmann
    .bInterfaceSubClass            = 0x01, /* boot */
77 0e4e9695 Gerd Hoffmann
    .bInterfaceProtocol            = 0x02,
78 0e4e9695 Gerd Hoffmann
    .ndesc                         = 1,
79 0e4e9695 Gerd Hoffmann
    .descs = (USBDescOther[]) {
80 0e4e9695 Gerd Hoffmann
        {
81 0e4e9695 Gerd Hoffmann
            /* HID descriptor */
82 0e4e9695 Gerd Hoffmann
            .data = (uint8_t[]) {
83 0e4e9695 Gerd Hoffmann
                0x09,          /*  u8  bLength */
84 0e4e9695 Gerd Hoffmann
                USB_DT_HID,    /*  u8  bDescriptorType */
85 0e4e9695 Gerd Hoffmann
                0x01, 0x00,    /*  u16 HID_class */
86 0e4e9695 Gerd Hoffmann
                0x00,          /*  u8  country_code */
87 0e4e9695 Gerd Hoffmann
                0x01,          /*  u8  num_descriptors */
88 0e4e9695 Gerd Hoffmann
                USB_DT_REPORT, /*  u8  type: Report */
89 0e4e9695 Gerd Hoffmann
                52, 0,         /*  u16 len */
90 0e4e9695 Gerd Hoffmann
            },
91 0e4e9695 Gerd Hoffmann
        },
92 0e4e9695 Gerd Hoffmann
    },
93 0e4e9695 Gerd Hoffmann
    .eps = (USBDescEndpoint[]) {
94 0e4e9695 Gerd Hoffmann
        {
95 0e4e9695 Gerd Hoffmann
            .bEndpointAddress      = USB_DIR_IN | 0x01,
96 0e4e9695 Gerd Hoffmann
            .bmAttributes          = USB_ENDPOINT_XFER_INT,
97 0e4e9695 Gerd Hoffmann
            .wMaxPacketSize        = 4,
98 0e4e9695 Gerd Hoffmann
            .bInterval             = 0x0a,
99 0e4e9695 Gerd Hoffmann
        },
100 0e4e9695 Gerd Hoffmann
    },
101 59ae540c bellard
};
102 59ae540c bellard
103 0e4e9695 Gerd Hoffmann
static const USBDescIface desc_iface_tablet = {
104 0e4e9695 Gerd Hoffmann
    .bInterfaceNumber              = 0,
105 0e4e9695 Gerd Hoffmann
    .bNumEndpoints                 = 1,
106 0e4e9695 Gerd Hoffmann
    .bInterfaceClass               = USB_CLASS_HID,
107 0e4e9695 Gerd Hoffmann
    .bInterfaceProtocol            = 0x02,
108 0e4e9695 Gerd Hoffmann
    .ndesc                         = 1,
109 0e4e9695 Gerd Hoffmann
    .descs = (USBDescOther[]) {
110 0e4e9695 Gerd Hoffmann
        {
111 0e4e9695 Gerd Hoffmann
            /* HID descriptor */
112 0e4e9695 Gerd Hoffmann
            .data = (uint8_t[]) {
113 0e4e9695 Gerd Hoffmann
                0x09,          /*  u8  bLength */
114 0e4e9695 Gerd Hoffmann
                USB_DT_HID,    /*  u8  bDescriptorType */
115 0e4e9695 Gerd Hoffmann
                0x01, 0x00,    /*  u16 HID_class */
116 0e4e9695 Gerd Hoffmann
                0x00,          /*  u8  country_code */
117 0e4e9695 Gerd Hoffmann
                0x01,          /*  u8  num_descriptors */
118 0e4e9695 Gerd Hoffmann
                USB_DT_REPORT, /*  u8  type: Report */
119 0e4e9695 Gerd Hoffmann
                74, 0,         /*  u16 len */
120 0e4e9695 Gerd Hoffmann
            },
121 0e4e9695 Gerd Hoffmann
        },
122 0e4e9695 Gerd Hoffmann
    },
123 0e4e9695 Gerd Hoffmann
    .eps = (USBDescEndpoint[]) {
124 0e4e9695 Gerd Hoffmann
        {
125 0e4e9695 Gerd Hoffmann
            .bEndpointAddress      = USB_DIR_IN | 0x01,
126 0e4e9695 Gerd Hoffmann
            .bmAttributes          = USB_ENDPOINT_XFER_INT,
127 0e4e9695 Gerd Hoffmann
            .wMaxPacketSize        = 8,
128 0e4e9695 Gerd Hoffmann
            .bInterval             = 0x0a,
129 0e4e9695 Gerd Hoffmann
        },
130 0e4e9695 Gerd Hoffmann
    },
131 0e4e9695 Gerd Hoffmann
};
132 0e4e9695 Gerd Hoffmann
133 0e4e9695 Gerd Hoffmann
static const USBDescIface desc_iface_keyboard = {
134 0e4e9695 Gerd Hoffmann
    .bInterfaceNumber              = 0,
135 0e4e9695 Gerd Hoffmann
    .bNumEndpoints                 = 1,
136 0e4e9695 Gerd Hoffmann
    .bInterfaceClass               = USB_CLASS_HID,
137 0e4e9695 Gerd Hoffmann
    .bInterfaceSubClass            = 0x01, /* boot */
138 0e4e9695 Gerd Hoffmann
    .bInterfaceProtocol            = 0x01, /* keyboard */
139 0e4e9695 Gerd Hoffmann
    .ndesc                         = 1,
140 0e4e9695 Gerd Hoffmann
    .descs = (USBDescOther[]) {
141 0e4e9695 Gerd Hoffmann
        {
142 0e4e9695 Gerd Hoffmann
            /* HID descriptor */
143 0e4e9695 Gerd Hoffmann
            .data = (uint8_t[]) {
144 0e4e9695 Gerd Hoffmann
                0x09,          /*  u8  bLength */
145 0e4e9695 Gerd Hoffmann
                USB_DT_HID,    /*  u8  bDescriptorType */
146 0e4e9695 Gerd Hoffmann
                0x11, 0x01,    /*  u16 HID_class */
147 0e4e9695 Gerd Hoffmann
                0x00,          /*  u8  country_code */
148 0e4e9695 Gerd Hoffmann
                0x01,          /*  u8  num_descriptors */
149 0e4e9695 Gerd Hoffmann
                USB_DT_REPORT, /*  u8  type: Report */
150 0e4e9695 Gerd Hoffmann
                0x3f, 0,       /*  u16 len */
151 0e4e9695 Gerd Hoffmann
            },
152 0e4e9695 Gerd Hoffmann
        },
153 0e4e9695 Gerd Hoffmann
    },
154 0e4e9695 Gerd Hoffmann
    .eps = (USBDescEndpoint[]) {
155 0e4e9695 Gerd Hoffmann
        {
156 0e4e9695 Gerd Hoffmann
            .bEndpointAddress      = USB_DIR_IN | 0x01,
157 0e4e9695 Gerd Hoffmann
            .bmAttributes          = USB_ENDPOINT_XFER_INT,
158 0e4e9695 Gerd Hoffmann
            .wMaxPacketSize        = 8,
159 0e4e9695 Gerd Hoffmann
            .bInterval             = 0x0a,
160 0e4e9695 Gerd Hoffmann
        },
161 0e4e9695 Gerd Hoffmann
    },
162 0e4e9695 Gerd Hoffmann
};
163 0e4e9695 Gerd Hoffmann
164 0e4e9695 Gerd Hoffmann
static const USBDescDevice desc_device_mouse = {
165 0e4e9695 Gerd Hoffmann
    .bcdUSB                        = 0x0100,
166 0e4e9695 Gerd Hoffmann
    .bMaxPacketSize0               = 8,
167 0e4e9695 Gerd Hoffmann
    .bNumConfigurations            = 1,
168 0e4e9695 Gerd Hoffmann
    .confs = (USBDescConfig[]) {
169 0e4e9695 Gerd Hoffmann
        {
170 0e4e9695 Gerd Hoffmann
            .bNumInterfaces        = 1,
171 0e4e9695 Gerd Hoffmann
            .bConfigurationValue   = 1,
172 0e4e9695 Gerd Hoffmann
            .iConfiguration        = STR_CONFIG_MOUSE,
173 0e4e9695 Gerd Hoffmann
            .bmAttributes          = 0xa0,
174 0e4e9695 Gerd Hoffmann
            .bMaxPower             = 50,
175 add75088 Brad Hards
            .nif = 1,
176 0e4e9695 Gerd Hoffmann
            .ifs = &desc_iface_mouse,
177 0e4e9695 Gerd Hoffmann
        },
178 0e4e9695 Gerd Hoffmann
    },
179 0e4e9695 Gerd Hoffmann
};
180 0e4e9695 Gerd Hoffmann
181 0e4e9695 Gerd Hoffmann
static const USBDescDevice desc_device_tablet = {
182 0e4e9695 Gerd Hoffmann
    .bcdUSB                        = 0x0100,
183 0e4e9695 Gerd Hoffmann
    .bMaxPacketSize0               = 8,
184 0e4e9695 Gerd Hoffmann
    .bNumConfigurations            = 1,
185 0e4e9695 Gerd Hoffmann
    .confs = (USBDescConfig[]) {
186 0e4e9695 Gerd Hoffmann
        {
187 0e4e9695 Gerd Hoffmann
            .bNumInterfaces        = 1,
188 0e4e9695 Gerd Hoffmann
            .bConfigurationValue   = 1,
189 0e4e9695 Gerd Hoffmann
            .iConfiguration        = STR_CONFIG_TABLET,
190 0e4e9695 Gerd Hoffmann
            .bmAttributes          = 0xa0,
191 0e4e9695 Gerd Hoffmann
            .bMaxPower             = 50,
192 add75088 Brad Hards
            .nif = 1,
193 0e4e9695 Gerd Hoffmann
            .ifs = &desc_iface_tablet,
194 0e4e9695 Gerd Hoffmann
        },
195 0e4e9695 Gerd Hoffmann
    },
196 0e4e9695 Gerd Hoffmann
};
197 0e4e9695 Gerd Hoffmann
198 0e4e9695 Gerd Hoffmann
static const USBDescDevice desc_device_keyboard = {
199 0e4e9695 Gerd Hoffmann
    .bcdUSB                        = 0x0100,
200 0e4e9695 Gerd Hoffmann
    .bMaxPacketSize0               = 8,
201 0e4e9695 Gerd Hoffmann
    .bNumConfigurations            = 1,
202 0e4e9695 Gerd Hoffmann
    .confs = (USBDescConfig[]) {
203 0e4e9695 Gerd Hoffmann
        {
204 0e4e9695 Gerd Hoffmann
            .bNumInterfaces        = 1,
205 0e4e9695 Gerd Hoffmann
            .bConfigurationValue   = 1,
206 0e4e9695 Gerd Hoffmann
            .iConfiguration        = STR_CONFIG_KEYBOARD,
207 0e4e9695 Gerd Hoffmann
            .bmAttributes          = 0xa0,
208 0e4e9695 Gerd Hoffmann
            .bMaxPower             = 50,
209 add75088 Brad Hards
            .nif = 1,
210 0e4e9695 Gerd Hoffmann
            .ifs = &desc_iface_keyboard,
211 0e4e9695 Gerd Hoffmann
        },
212 0e4e9695 Gerd Hoffmann
    },
213 0e4e9695 Gerd Hoffmann
};
214 0e4e9695 Gerd Hoffmann
215 0e4e9695 Gerd Hoffmann
static const USBDesc desc_mouse = {
216 0e4e9695 Gerd Hoffmann
    .id = {
217 0e4e9695 Gerd Hoffmann
        .idVendor          = 0x0627,
218 0e4e9695 Gerd Hoffmann
        .idProduct         = 0x0001,
219 0e4e9695 Gerd Hoffmann
        .bcdDevice         = 0,
220 0e4e9695 Gerd Hoffmann
        .iManufacturer     = STR_MANUFACTURER,
221 0e4e9695 Gerd Hoffmann
        .iProduct          = STR_PRODUCT_MOUSE,
222 0e4e9695 Gerd Hoffmann
        .iSerialNumber     = STR_SERIALNUMBER,
223 0e4e9695 Gerd Hoffmann
    },
224 0e4e9695 Gerd Hoffmann
    .full = &desc_device_mouse,
225 0e4e9695 Gerd Hoffmann
    .str  = desc_strings,
226 0e4e9695 Gerd Hoffmann
};
227 0e4e9695 Gerd Hoffmann
228 0e4e9695 Gerd Hoffmann
static const USBDesc desc_tablet = {
229 0e4e9695 Gerd Hoffmann
    .id = {
230 0e4e9695 Gerd Hoffmann
        .idVendor          = 0x0627,
231 0e4e9695 Gerd Hoffmann
        .idProduct         = 0x0001,
232 0e4e9695 Gerd Hoffmann
        .bcdDevice         = 0,
233 0e4e9695 Gerd Hoffmann
        .iManufacturer     = STR_MANUFACTURER,
234 0e4e9695 Gerd Hoffmann
        .iProduct          = STR_PRODUCT_TABLET,
235 0e4e9695 Gerd Hoffmann
        .iSerialNumber     = STR_SERIALNUMBER,
236 0e4e9695 Gerd Hoffmann
    },
237 0e4e9695 Gerd Hoffmann
    .full = &desc_device_tablet,
238 0e4e9695 Gerd Hoffmann
    .str  = desc_strings,
239 0e4e9695 Gerd Hoffmann
};
240 0e4e9695 Gerd Hoffmann
241 0e4e9695 Gerd Hoffmann
static const USBDesc desc_keyboard = {
242 0e4e9695 Gerd Hoffmann
    .id = {
243 0e4e9695 Gerd Hoffmann
        .idVendor          = 0x0627,
244 0e4e9695 Gerd Hoffmann
        .idProduct         = 0x0001,
245 0e4e9695 Gerd Hoffmann
        .bcdDevice         = 0,
246 0e4e9695 Gerd Hoffmann
        .iManufacturer     = STR_MANUFACTURER,
247 0e4e9695 Gerd Hoffmann
        .iProduct          = STR_PRODUCT_KEYBOARD,
248 0e4e9695 Gerd Hoffmann
        .iSerialNumber     = STR_SERIALNUMBER,
249 0e4e9695 Gerd Hoffmann
    },
250 0e4e9695 Gerd Hoffmann
    .full = &desc_device_keyboard,
251 0e4e9695 Gerd Hoffmann
    .str  = desc_strings,
252 47b2d338 balrog
};
253 47b2d338 balrog
254 59ae540c bellard
static const uint8_t qemu_mouse_hid_report_descriptor[] = {
255 976f8eef balrog
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
256 976f8eef balrog
    0x09, 0x02,                /* Usage (Mouse) */
257 976f8eef balrog
    0xa1, 0x01,                /* Collection (Application) */
258 976f8eef balrog
    0x09, 0x01,                /*   Usage (Pointer) */
259 976f8eef balrog
    0xa1, 0x00,                /*   Collection (Physical) */
260 976f8eef balrog
    0x05, 0x09,                /*     Usage Page (Button) */
261 976f8eef balrog
    0x19, 0x01,                /*     Usage Minimum (1) */
262 976f8eef balrog
    0x29, 0x03,                /*     Usage Maximum (3) */
263 976f8eef balrog
    0x15, 0x00,                /*     Logical Minimum (0) */
264 976f8eef balrog
    0x25, 0x01,                /*     Logical Maximum (1) */
265 976f8eef balrog
    0x95, 0x03,                /*     Report Count (3) */
266 976f8eef balrog
    0x75, 0x01,                /*     Report Size (1) */
267 976f8eef balrog
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
268 976f8eef balrog
    0x95, 0x01,                /*     Report Count (1) */
269 976f8eef balrog
    0x75, 0x05,                /*     Report Size (5) */
270 976f8eef balrog
    0x81, 0x01,                /*     Input (Constant) */
271 976f8eef balrog
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
272 976f8eef balrog
    0x09, 0x30,                /*     Usage (X) */
273 976f8eef balrog
    0x09, 0x31,                /*     Usage (Y) */
274 976f8eef balrog
    0x09, 0x38,                /*     Usage (Wheel) */
275 976f8eef balrog
    0x15, 0x81,                /*     Logical Minimum (-0x7f) */
276 976f8eef balrog
    0x25, 0x7f,                /*     Logical Maximum (0x7f) */
277 976f8eef balrog
    0x75, 0x08,                /*     Report Size (8) */
278 976f8eef balrog
    0x95, 0x03,                /*     Report Count (3) */
279 976f8eef balrog
    0x81, 0x06,                /*     Input (Data, Variable, Relative) */
280 976f8eef balrog
    0xc0,                /*   End Collection */
281 976f8eef balrog
    0xc0,                /* End Collection */
282 59ae540c bellard
};
283 59ae540c bellard
284 09b26c5e bellard
static const uint8_t qemu_tablet_hid_report_descriptor[] = {
285 976f8eef balrog
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
286 976f8eef balrog
    0x09, 0x01,                /* Usage (Pointer) */
287 976f8eef balrog
    0xa1, 0x01,                /* Collection (Application) */
288 976f8eef balrog
    0x09, 0x01,                /*   Usage (Pointer) */
289 976f8eef balrog
    0xa1, 0x00,                /*   Collection (Physical) */
290 976f8eef balrog
    0x05, 0x09,                /*     Usage Page (Button) */
291 976f8eef balrog
    0x19, 0x01,                /*     Usage Minimum (1) */
292 976f8eef balrog
    0x29, 0x03,                /*     Usage Maximum (3) */
293 976f8eef balrog
    0x15, 0x00,                /*     Logical Minimum (0) */
294 976f8eef balrog
    0x25, 0x01,                /*     Logical Maximum (1) */
295 976f8eef balrog
    0x95, 0x03,                /*     Report Count (3) */
296 976f8eef balrog
    0x75, 0x01,                /*     Report Size (1) */
297 976f8eef balrog
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
298 976f8eef balrog
    0x95, 0x01,                /*     Report Count (1) */
299 976f8eef balrog
    0x75, 0x05,                /*     Report Size (5) */
300 976f8eef balrog
    0x81, 0x01,                /*     Input (Constant) */
301 976f8eef balrog
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
302 976f8eef balrog
    0x09, 0x30,                /*     Usage (X) */
303 976f8eef balrog
    0x09, 0x31,                /*     Usage (Y) */
304 976f8eef balrog
    0x15, 0x00,                /*     Logical Minimum (0) */
305 de5c2d0a balrog
    0x26, 0xff, 0x7f,        /*     Logical Maximum (0x7fff) */
306 976f8eef balrog
    0x35, 0x00,                /*     Physical Minimum (0) */
307 de5c2d0a balrog
    0x46, 0xff, 0x7f,        /*     Physical Maximum (0x7fff) */
308 976f8eef balrog
    0x75, 0x10,                /*     Report Size (16) */
309 976f8eef balrog
    0x95, 0x02,                /*     Report Count (2) */
310 976f8eef balrog
    0x81, 0x02,                /*     Input (Data, Variable, Absolute) */
311 976f8eef balrog
    0x05, 0x01,                /*     Usage Page (Generic Desktop) */
312 976f8eef balrog
    0x09, 0x38,                /*     Usage (Wheel) */
313 976f8eef balrog
    0x15, 0x81,                /*     Logical Minimum (-0x7f) */
314 976f8eef balrog
    0x25, 0x7f,                /*     Logical Maximum (0x7f) */
315 976f8eef balrog
    0x35, 0x00,                /*     Physical Minimum (same as logical) */
316 976f8eef balrog
    0x45, 0x00,                /*     Physical Maximum (same as logical) */
317 976f8eef balrog
    0x75, 0x08,                /*     Report Size (8) */
318 976f8eef balrog
    0x95, 0x01,                /*     Report Count (1) */
319 976f8eef balrog
    0x81, 0x06,                /*     Input (Data, Variable, Relative) */
320 976f8eef balrog
    0xc0,                /*   End Collection */
321 976f8eef balrog
    0xc0,                /* End Collection */
322 09b26c5e bellard
};
323 09b26c5e bellard
324 47b2d338 balrog
static const uint8_t qemu_keyboard_hid_report_descriptor[] = {
325 47b2d338 balrog
    0x05, 0x01,                /* Usage Page (Generic Desktop) */
326 47b2d338 balrog
    0x09, 0x06,                /* Usage (Keyboard) */
327 47b2d338 balrog
    0xa1, 0x01,                /* Collection (Application) */
328 47b2d338 balrog
    0x75, 0x01,                /*   Report Size (1) */
329 47b2d338 balrog
    0x95, 0x08,                /*   Report Count (8) */
330 47b2d338 balrog
    0x05, 0x07,                /*   Usage Page (Key Codes) */
331 47b2d338 balrog
    0x19, 0xe0,                /*   Usage Minimum (224) */
332 47b2d338 balrog
    0x29, 0xe7,                /*   Usage Maximum (231) */
333 47b2d338 balrog
    0x15, 0x00,                /*   Logical Minimum (0) */
334 47b2d338 balrog
    0x25, 0x01,                /*   Logical Maximum (1) */
335 47b2d338 balrog
    0x81, 0x02,                /*   Input (Data, Variable, Absolute) */
336 47b2d338 balrog
    0x95, 0x01,                /*   Report Count (1) */
337 47b2d338 balrog
    0x75, 0x08,                /*   Report Size (8) */
338 47b2d338 balrog
    0x81, 0x01,                /*   Input (Constant) */
339 47b2d338 balrog
    0x95, 0x05,                /*   Report Count (5) */
340 47b2d338 balrog
    0x75, 0x01,                /*   Report Size (1) */
341 47b2d338 balrog
    0x05, 0x08,                /*   Usage Page (LEDs) */
342 47b2d338 balrog
    0x19, 0x01,                /*   Usage Minimum (1) */
343 47b2d338 balrog
    0x29, 0x05,                /*   Usage Maximum (5) */
344 47b2d338 balrog
    0x91, 0x02,                /*   Output (Data, Variable, Absolute) */
345 47b2d338 balrog
    0x95, 0x01,                /*   Report Count (1) */
346 47b2d338 balrog
    0x75, 0x03,                /*   Report Size (3) */
347 47b2d338 balrog
    0x91, 0x01,                /*   Output (Constant) */
348 47b2d338 balrog
    0x95, 0x06,                /*   Report Count (6) */
349 47b2d338 balrog
    0x75, 0x08,                /*   Report Size (8) */
350 47b2d338 balrog
    0x15, 0x00,                /*   Logical Minimum (0) */
351 47b2d338 balrog
    0x25, 0xff,                /*   Logical Maximum (255) */
352 47b2d338 balrog
    0x05, 0x07,                /*   Usage Page (Key Codes) */
353 47b2d338 balrog
    0x19, 0x00,                /*   Usage Minimum (0) */
354 47b2d338 balrog
    0x29, 0xff,                /*   Usage Maximum (255) */
355 47b2d338 balrog
    0x81, 0x00,                /*   Input (Data, Array) */
356 47b2d338 balrog
    0xc0,                /* End Collection */
357 47b2d338 balrog
};
358 47b2d338 balrog
359 8bde6805 Gerd Hoffmann
static void usb_hid_changed(HIDState *hs)
360 47e699dc balrog
{
361 8bde6805 Gerd Hoffmann
    USBHIDState *us = container_of(hs, USBHIDState, hid);
362 47e699dc balrog
363 8bde6805 Gerd Hoffmann
    usb_wakeup(&us->dev);
364 47e699dc balrog
}
365 47e699dc balrog
366 8bde6805 Gerd Hoffmann
static void usb_hid_handle_reset(USBDevice *dev)
367 47b2d338 balrog
{
368 0d878eec Gerd Hoffmann
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
369 0d878eec Gerd Hoffmann
370 dcfda673 Gerd Hoffmann
    hid_reset(&us->hid);
371 68735b6c Kevin O'Connor
}
372 68735b6c Kevin O'Connor
373 007fd62f Hans de Goede
static int usb_hid_handle_control(USBDevice *dev, USBPacket *p,
374 007fd62f Hans de Goede
               int request, int value, int index, int length, uint8_t *data)
375 59ae540c bellard
{
376 0d878eec Gerd Hoffmann
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
377 0d878eec Gerd Hoffmann
    HIDState *hs = &us->hid;
378 0e4e9695 Gerd Hoffmann
    int ret;
379 59ae540c bellard
380 007fd62f Hans de Goede
    ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
381 0e4e9695 Gerd Hoffmann
    if (ret >= 0) {
382 0e4e9695 Gerd Hoffmann
        return ret;
383 0e4e9695 Gerd Hoffmann
    }
384 59ae540c bellard
385 0e4e9695 Gerd Hoffmann
    ret = 0;
386 0d878eec Gerd Hoffmann
    switch (request) {
387 59ae540c bellard
        /* hid specific requests */
388 59ae540c bellard
    case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
389 0d878eec Gerd Hoffmann
        switch (value >> 8) {
390 59ae540c bellard
        case 0x22:
391 0d878eec Gerd Hoffmann
            if (hs->kind == HID_MOUSE) {
392 5fafdf24 ths
                memcpy(data, qemu_mouse_hid_report_descriptor,
393 09b26c5e bellard
                       sizeof(qemu_mouse_hid_report_descriptor));
394 09b26c5e bellard
                ret = sizeof(qemu_mouse_hid_report_descriptor);
395 0d878eec Gerd Hoffmann
            } else if (hs->kind == HID_TABLET) {
396 0d878eec Gerd Hoffmann
                memcpy(data, qemu_tablet_hid_report_descriptor,
397 09b26c5e bellard
                       sizeof(qemu_tablet_hid_report_descriptor));
398 09b26c5e bellard
                ret = sizeof(qemu_tablet_hid_report_descriptor);
399 0d878eec Gerd Hoffmann
            } else if (hs->kind == HID_KEYBOARD) {
400 5fafdf24 ths
                memcpy(data, qemu_keyboard_hid_report_descriptor,
401 47b2d338 balrog
                       sizeof(qemu_keyboard_hid_report_descriptor));
402 47b2d338 balrog
                ret = sizeof(qemu_keyboard_hid_report_descriptor);
403 47b2d338 balrog
            }
404 47b2d338 balrog
            break;
405 59ae540c bellard
        default:
406 59ae540c bellard
            goto fail;
407 59ae540c bellard
        }
408 59ae540c bellard
        break;
409 59ae540c bellard
    case GET_REPORT:
410 0d878eec Gerd Hoffmann
        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
411 0d878eec Gerd Hoffmann
            ret = hid_pointer_poll(hs, data, length);
412 0d878eec Gerd Hoffmann
        } else if (hs->kind == HID_KEYBOARD) {
413 0d878eec Gerd Hoffmann
            ret = hid_keyboard_poll(hs, data, length);
414 e7e73892 Gerd Hoffmann
        }
415 47b2d338 balrog
        break;
416 47b2d338 balrog
    case SET_REPORT:
417 0d878eec Gerd Hoffmann
        if (hs->kind == HID_KEYBOARD) {
418 0d878eec Gerd Hoffmann
            ret = hid_keyboard_write(hs, data, length);
419 0d878eec Gerd Hoffmann
        } else {
420 47b2d338 balrog
            goto fail;
421 0d878eec Gerd Hoffmann
        }
422 47b2d338 balrog
        break;
423 47b2d338 balrog
    case GET_PROTOCOL:
424 0d878eec Gerd Hoffmann
        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
425 47b2d338 balrog
            goto fail;
426 0d878eec Gerd Hoffmann
        }
427 47b2d338 balrog
        ret = 1;
428 b069d348 Gerd Hoffmann
        data[0] = hs->protocol;
429 47b2d338 balrog
        break;
430 47b2d338 balrog
    case SET_PROTOCOL:
431 0d878eec Gerd Hoffmann
        if (hs->kind != HID_KEYBOARD && hs->kind != HID_MOUSE) {
432 47b2d338 balrog
            goto fail;
433 0d878eec Gerd Hoffmann
        }
434 47b2d338 balrog
        ret = 0;
435 b069d348 Gerd Hoffmann
        hs->protocol = value;
436 47b2d338 balrog
        break;
437 47b2d338 balrog
    case GET_IDLE:
438 47b2d338 balrog
        ret = 1;
439 b069d348 Gerd Hoffmann
        data[0] = hs->idle;
440 59ae540c bellard
        break;
441 59ae540c bellard
    case SET_IDLE:
442 b069d348 Gerd Hoffmann
        hs->idle = (uint8_t) (value >> 8);
443 b069d348 Gerd Hoffmann
        hid_set_next_idle(hs, qemu_get_clock_ns(vm_clock));
444 21635e12 Gerd Hoffmann
        if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
445 21635e12 Gerd Hoffmann
            hid_pointer_activate(hs);
446 21635e12 Gerd Hoffmann
        }
447 59ae540c bellard
        ret = 0;
448 59ae540c bellard
        break;
449 59ae540c bellard
    default:
450 59ae540c bellard
    fail:
451 59ae540c bellard
        ret = USB_RET_STALL;
452 59ae540c bellard
        break;
453 59ae540c bellard
    }
454 59ae540c bellard
    return ret;
455 59ae540c bellard
}
456 59ae540c bellard
457 47b2d338 balrog
static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
458 59ae540c bellard
{
459 0d878eec Gerd Hoffmann
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
460 0d878eec Gerd Hoffmann
    HIDState *hs = &us->hid;
461 4f4321c1 Gerd Hoffmann
    uint8_t buf[p->iov.size];
462 09b26c5e bellard
    int ret = 0;
463 59ae540c bellard
464 0d878eec Gerd Hoffmann
    switch (p->pid) {
465 59ae540c bellard
    case USB_TOKEN_IN:
466 4d611c9a pbrook
        if (p->devep == 1) {
467 74475455 Paolo Bonzini
            int64_t curtime = qemu_get_clock_ns(vm_clock);
468 38931fa8 Gerd Hoffmann
            if (!hid_has_events(hs) &&
469 b069d348 Gerd Hoffmann
                (!hs->idle || hs->next_idle_clock - curtime > 0)) {
470 117b3ae6 pbrook
                return USB_RET_NAK;
471 13f8b97a Paolo Bonzini
            }
472 b069d348 Gerd Hoffmann
            hid_set_next_idle(hs, curtime);
473 0d878eec Gerd Hoffmann
            if (hs->kind == HID_MOUSE || hs->kind == HID_TABLET) {
474 0d878eec Gerd Hoffmann
                ret = hid_pointer_poll(hs, buf, p->iov.size);
475 0d878eec Gerd Hoffmann
            } else if (hs->kind == HID_KEYBOARD) {
476 0d878eec Gerd Hoffmann
                ret = hid_keyboard_poll(hs, buf, p->iov.size);
477 13f8b97a Paolo Bonzini
            }
478 4f4321c1 Gerd Hoffmann
            usb_packet_copy(p, buf, ret);
479 59ae540c bellard
        } else {
480 59ae540c bellard
            goto fail;
481 59ae540c bellard
        }
482 59ae540c bellard
        break;
483 59ae540c bellard
    case USB_TOKEN_OUT:
484 59ae540c bellard
    default:
485 59ae540c bellard
    fail:
486 59ae540c bellard
        ret = USB_RET_STALL;
487 59ae540c bellard
        break;
488 59ae540c bellard
    }
489 59ae540c bellard
    return ret;
490 59ae540c bellard
}
491 59ae540c bellard
492 8bde6805 Gerd Hoffmann
static void usb_hid_handle_destroy(USBDevice *dev)
493 09b26c5e bellard
{
494 0d878eec Gerd Hoffmann
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
495 a980a065 Gerd Hoffmann
496 8bde6805 Gerd Hoffmann
    hid_free(&us->hid);
497 8bde6805 Gerd Hoffmann
}
498 8bde6805 Gerd Hoffmann
499 8bde6805 Gerd Hoffmann
static int usb_hid_initfn(USBDevice *dev, int kind)
500 8bde6805 Gerd Hoffmann
{
501 8bde6805 Gerd Hoffmann
    USBHIDState *us = DO_UPCAST(USBHIDState, dev, dev);
502 8bde6805 Gerd Hoffmann
503 8bde6805 Gerd Hoffmann
    usb_desc_init(dev);
504 8bde6805 Gerd Hoffmann
    hid_init(&us->hid, kind, usb_hid_changed);
505 806b6024 Gerd Hoffmann
    return 0;
506 09b26c5e bellard
}
507 09b26c5e bellard
508 806b6024 Gerd Hoffmann
static int usb_tablet_initfn(USBDevice *dev)
509 59ae540c bellard
{
510 0d878eec Gerd Hoffmann
    return usb_hid_initfn(dev, HID_TABLET);
511 806b6024 Gerd Hoffmann
}
512 59ae540c bellard
513 806b6024 Gerd Hoffmann
static int usb_mouse_initfn(USBDevice *dev)
514 806b6024 Gerd Hoffmann
{
515 0d878eec Gerd Hoffmann
    return usb_hid_initfn(dev, HID_MOUSE);
516 806b6024 Gerd Hoffmann
}
517 59ae540c bellard
518 806b6024 Gerd Hoffmann
static int usb_keyboard_initfn(USBDevice *dev)
519 806b6024 Gerd Hoffmann
{
520 0d878eec Gerd Hoffmann
    return usb_hid_initfn(dev, HID_KEYBOARD);
521 806b6024 Gerd Hoffmann
}
522 59ae540c bellard
523 3a3286bf Gerd Hoffmann
static int usb_ptr_post_load(void *opaque, int version_id)
524 3a3286bf Gerd Hoffmann
{
525 3a3286bf Gerd Hoffmann
    USBHIDState *s = opaque;
526 3a3286bf Gerd Hoffmann
527 3a3286bf Gerd Hoffmann
    if (s->dev.remote_wakeup) {
528 3a3286bf Gerd Hoffmann
        hid_pointer_activate(&s->hid);
529 3a3286bf Gerd Hoffmann
    }
530 3a3286bf Gerd Hoffmann
    return 0;
531 3a3286bf Gerd Hoffmann
}
532 3a3286bf Gerd Hoffmann
533 ee59e6b3 Gerd Hoffmann
static const VMStateDescription vmstate_usb_ptr = {
534 ee59e6b3 Gerd Hoffmann
    .name = "usb-ptr",
535 ee59e6b3 Gerd Hoffmann
    .version_id = 1,
536 ee59e6b3 Gerd Hoffmann
    .minimum_version_id = 1,
537 3a3286bf Gerd Hoffmann
    .post_load = usb_ptr_post_load,
538 ee59e6b3 Gerd Hoffmann
    .fields = (VMStateField []) {
539 ee59e6b3 Gerd Hoffmann
        VMSTATE_USB_DEVICE(dev, USBHIDState),
540 1f42d222 Michael Walle
        VMSTATE_HID_POINTER_DEVICE(hid, USBHIDState),
541 ee59e6b3 Gerd Hoffmann
        VMSTATE_END_OF_LIST()
542 ee59e6b3 Gerd Hoffmann
    }
543 ee59e6b3 Gerd Hoffmann
};
544 ee59e6b3 Gerd Hoffmann
545 ee59e6b3 Gerd Hoffmann
static const VMStateDescription vmstate_usb_kbd = {
546 ee59e6b3 Gerd Hoffmann
    .name = "usb-kbd",
547 ee59e6b3 Gerd Hoffmann
    .version_id = 1,
548 ee59e6b3 Gerd Hoffmann
    .minimum_version_id = 1,
549 ee59e6b3 Gerd Hoffmann
    .fields = (VMStateField []) {
550 ee59e6b3 Gerd Hoffmann
        VMSTATE_USB_DEVICE(dev, USBHIDState),
551 1f42d222 Michael Walle
        VMSTATE_HID_KEYBOARD_DEVICE(hid, USBHIDState),
552 ee59e6b3 Gerd Hoffmann
        VMSTATE_END_OF_LIST()
553 ee59e6b3 Gerd Hoffmann
    }
554 ee59e6b3 Gerd Hoffmann
};
555 ee59e6b3 Gerd Hoffmann
556 806b6024 Gerd Hoffmann
static struct USBDeviceInfo hid_info[] = {
557 806b6024 Gerd Hoffmann
    {
558 06384698 Markus Armbruster
        .product_desc   = "QEMU USB Tablet",
559 556cd098 Markus Armbruster
        .qdev.name      = "usb-tablet",
560 fa7c70c3 Gerd Hoffmann
        .usbdevice_name = "tablet",
561 806b6024 Gerd Hoffmann
        .qdev.size      = sizeof(USBHIDState),
562 ee59e6b3 Gerd Hoffmann
        .qdev.vmsd      = &vmstate_usb_ptr,
563 0e4e9695 Gerd Hoffmann
        .usb_desc       = &desc_tablet,
564 806b6024 Gerd Hoffmann
        .init           = usb_tablet_initfn,
565 806b6024 Gerd Hoffmann
        .handle_packet  = usb_generic_handle_packet,
566 8bde6805 Gerd Hoffmann
        .handle_reset   = usb_hid_handle_reset,
567 806b6024 Gerd Hoffmann
        .handle_control = usb_hid_handle_control,
568 806b6024 Gerd Hoffmann
        .handle_data    = usb_hid_handle_data,
569 806b6024 Gerd Hoffmann
        .handle_destroy = usb_hid_handle_destroy,
570 806b6024 Gerd Hoffmann
    },{
571 06384698 Markus Armbruster
        .product_desc   = "QEMU USB Mouse",
572 556cd098 Markus Armbruster
        .qdev.name      = "usb-mouse",
573 fa7c70c3 Gerd Hoffmann
        .usbdevice_name = "mouse",
574 806b6024 Gerd Hoffmann
        .qdev.size      = sizeof(USBHIDState),
575 ee59e6b3 Gerd Hoffmann
        .qdev.vmsd      = &vmstate_usb_ptr,
576 0e4e9695 Gerd Hoffmann
        .usb_desc       = &desc_mouse,
577 806b6024 Gerd Hoffmann
        .init           = usb_mouse_initfn,
578 806b6024 Gerd Hoffmann
        .handle_packet  = usb_generic_handle_packet,
579 8bde6805 Gerd Hoffmann
        .handle_reset   = usb_hid_handle_reset,
580 806b6024 Gerd Hoffmann
        .handle_control = usb_hid_handle_control,
581 806b6024 Gerd Hoffmann
        .handle_data    = usb_hid_handle_data,
582 806b6024 Gerd Hoffmann
        .handle_destroy = usb_hid_handle_destroy,
583 806b6024 Gerd Hoffmann
    },{
584 06384698 Markus Armbruster
        .product_desc   = "QEMU USB Keyboard",
585 556cd098 Markus Armbruster
        .qdev.name      = "usb-kbd",
586 fa7c70c3 Gerd Hoffmann
        .usbdevice_name = "keyboard",
587 806b6024 Gerd Hoffmann
        .qdev.size      = sizeof(USBHIDState),
588 ee59e6b3 Gerd Hoffmann
        .qdev.vmsd      = &vmstate_usb_kbd,
589 0e4e9695 Gerd Hoffmann
        .usb_desc       = &desc_keyboard,
590 806b6024 Gerd Hoffmann
        .init           = usb_keyboard_initfn,
591 806b6024 Gerd Hoffmann
        .handle_packet  = usb_generic_handle_packet,
592 8bde6805 Gerd Hoffmann
        .handle_reset   = usb_hid_handle_reset,
593 806b6024 Gerd Hoffmann
        .handle_control = usb_hid_handle_control,
594 806b6024 Gerd Hoffmann
        .handle_data    = usb_hid_handle_data,
595 806b6024 Gerd Hoffmann
        .handle_destroy = usb_hid_handle_destroy,
596 806b6024 Gerd Hoffmann
    },{
597 806b6024 Gerd Hoffmann
        /* end of list */
598 806b6024 Gerd Hoffmann
    }
599 806b6024 Gerd Hoffmann
};
600 806b6024 Gerd Hoffmann
601 806b6024 Gerd Hoffmann
static void usb_hid_register_devices(void)
602 806b6024 Gerd Hoffmann
{
603 806b6024 Gerd Hoffmann
    usb_qdev_register_many(hid_info);
604 806b6024 Gerd Hoffmann
}
605 806b6024 Gerd Hoffmann
device_init(usb_hid_register_devices)