Statistics
| Branch: | Revision:

root / usb-linux.c @ 079d0b7f

History | View | Annotate | Download (52.1 kB)

1 bb36d470 bellard
/*
2 bb36d470 bellard
 * Linux host USB redirector
3 bb36d470 bellard
 *
4 bb36d470 bellard
 * Copyright (c) 2005 Fabrice Bellard
5 5fafdf24 ths
 *
6 64838171 aliguori
 * Copyright (c) 2008 Max Krasnyansky
7 64838171 aliguori
 *      Support for host device auto connect & disconnect
8 5d0c5750 aliguori
 *      Major rewrite to support fully async operation
9 4b096fc9 aliguori
 *
10 0f431527 aliguori
 * Copyright 2008 TJ <linux@tjworld.net>
11 0f431527 aliguori
 *      Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition
12 0f431527 aliguori
 *      to the legacy /proc/bus/usb USB device discovery and handling
13 0f431527 aliguori
 *
14 bb36d470 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 bb36d470 bellard
 * of this software and associated documentation files (the "Software"), to deal
16 bb36d470 bellard
 * in the Software without restriction, including without limitation the rights
17 bb36d470 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 bb36d470 bellard
 * copies of the Software, and to permit persons to whom the Software is
19 bb36d470 bellard
 * furnished to do so, subject to the following conditions:
20 bb36d470 bellard
 *
21 bb36d470 bellard
 * The above copyright notice and this permission notice shall be included in
22 bb36d470 bellard
 * all copies or substantial portions of the Software.
23 bb36d470 bellard
 *
24 bb36d470 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 bb36d470 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 bb36d470 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 bb36d470 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 bb36d470 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 bb36d470 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 bb36d470 bellard
 * THE SOFTWARE.
31 bb36d470 bellard
 */
32 446ab128 aliguori
33 87ecb68b pbrook
#include "qemu-common.h"
34 1f3870ab aliguori
#include "qemu-timer.h"
35 376253ec aliguori
#include "monitor.h"
36 b373a63a Shahar Havivi
#include "sysemu.h"
37 e6a2f500 Gerd Hoffmann
#include "trace.h"
38 bb36d470 bellard
39 bb36d470 bellard
#include <dirent.h>
40 bb36d470 bellard
#include <sys/ioctl.h>
41 bb36d470 bellard
42 446ab128 aliguori
#include <linux/usbdevice_fs.h>
43 446ab128 aliguori
#include <linux/version.h>
44 446ab128 aliguori
#include "hw/usb.h"
45 bb36d470 bellard
46 d9cf1578 blueswir1
/* We redefine it to avoid version problems */
47 d9cf1578 blueswir1
struct usb_ctrltransfer {
48 d9cf1578 blueswir1
    uint8_t  bRequestType;
49 d9cf1578 blueswir1
    uint8_t  bRequest;
50 d9cf1578 blueswir1
    uint16_t wValue;
51 d9cf1578 blueswir1
    uint16_t wIndex;
52 d9cf1578 blueswir1
    uint16_t wLength;
53 d9cf1578 blueswir1
    uint32_t timeout;
54 d9cf1578 blueswir1
    void *data;
55 d9cf1578 blueswir1
};
56 d9cf1578 blueswir1
57 ba9acab9 Gerd Hoffmann
typedef int USBScanFunc(void *opaque, int bus_num, int addr, const char *port,
58 0f5160d1 Hans de Goede
                        int class_id, int vendor_id, int product_id,
59 a594cfbf bellard
                        const char *product_name, int speed);
60 26a9e82a Gerd Hoffmann
61 0745eb1e Markus Armbruster
//#define DEBUG
62 64838171 aliguori
63 64838171 aliguori
#ifdef DEBUG
64 d0f2c4c6 malc
#define DPRINTF printf
65 64838171 aliguori
#else
66 d0f2c4c6 malc
#define DPRINTF(...)
67 64838171 aliguori
#endif
68 bb36d470 bellard
69 1f6e24e7 bellard
#define PRODUCT_NAME_SZ 32
70 5557d820 Gerd Hoffmann
#define MAX_PORTLEN 16
71 bb36d470 bellard
72 b9dc033c balrog
/* endpoint association data */
73 060dc841 Hans de Goede
#define ISO_FRAME_DESC_PER_URB 32
74 060dc841 Hans de Goede
75 71138531 Gerd Hoffmann
/* devio.c limits single requests to 16k */
76 71138531 Gerd Hoffmann
#define MAX_USBFS_BUFFER_SIZE 16384
77 71138531 Gerd Hoffmann
78 060dc841 Hans de Goede
typedef struct AsyncURB AsyncURB;
79 060dc841 Hans de Goede
80 b9dc033c balrog
struct endp_data {
81 64838171 aliguori
    uint8_t halted;
82 bb6d5498 Hans de Goede
    uint8_t iso_started;
83 060dc841 Hans de Goede
    AsyncURB *iso_urb;
84 060dc841 Hans de Goede
    int iso_urb_idx;
85 bb6d5498 Hans de Goede
    int iso_buffer_used;
86 82887262 Gerd Hoffmann
    int inflight;
87 b9dc033c balrog
};
88 b9dc033c balrog
89 26a9e82a Gerd Hoffmann
struct USBAutoFilter {
90 26a9e82a Gerd Hoffmann
    uint32_t bus_num;
91 26a9e82a Gerd Hoffmann
    uint32_t addr;
92 9056a297 Gerd Hoffmann
    char     *port;
93 26a9e82a Gerd Hoffmann
    uint32_t vendor_id;
94 26a9e82a Gerd Hoffmann
    uint32_t product_id;
95 26a9e82a Gerd Hoffmann
};
96 26a9e82a Gerd Hoffmann
97 bb36d470 bellard
typedef struct USBHostDevice {
98 bb36d470 bellard
    USBDevice dev;
99 64838171 aliguori
    int       fd;
100 9516bb47 Gerd Hoffmann
    int       hub_fd;
101 c75fead6 Gerd Hoffmann
    int       hub_port;
102 64838171 aliguori
103 f8ddbfbc Hans de Goede
    uint8_t   descr[8192];
104 64838171 aliguori
    int       descr_len;
105 24772c1e aliguori
    int       closing;
106 b81bcd8a Gerd Hoffmann
    uint32_t  iso_urb_count;
107 b373a63a Shahar Havivi
    Notifier  exit;
108 64838171 aliguori
109 d8e17efd Gerd Hoffmann
    struct endp_data ep_in[USB_MAX_ENDPOINTS];
110 d8e17efd Gerd Hoffmann
    struct endp_data ep_out[USB_MAX_ENDPOINTS];
111 7a8fc83f Gerd Hoffmann
    QLIST_HEAD(, AsyncURB) aurbs;
112 4b096fc9 aliguori
113 4b096fc9 aliguori
    /* Host side address */
114 4b096fc9 aliguori
    int bus_num;
115 4b096fc9 aliguori
    int addr;
116 5557d820 Gerd Hoffmann
    char port[MAX_PORTLEN];
117 26a9e82a Gerd Hoffmann
    struct USBAutoFilter match;
118 3ee886c5 Gerd Hoffmann
    int seen, errcount;
119 4b096fc9 aliguori
120 26a9e82a Gerd Hoffmann
    QTAILQ_ENTRY(USBHostDevice) next;
121 bb36d470 bellard
} USBHostDevice;
122 bb36d470 bellard
123 26a9e82a Gerd Hoffmann
static QTAILQ_HEAD(, USBHostDevice) hostdevs = QTAILQ_HEAD_INITIALIZER(hostdevs);
124 26a9e82a Gerd Hoffmann
125 26a9e82a Gerd Hoffmann
static int usb_host_close(USBHostDevice *dev);
126 26a9e82a Gerd Hoffmann
static int parse_filter(const char *spec, struct USBAutoFilter *f);
127 26a9e82a Gerd Hoffmann
static void usb_host_auto_check(void *unused);
128 2cc59d8c Hans de Goede
static int usb_host_read_file(char *line, size_t line_size,
129 2cc59d8c Hans de Goede
                            const char *device_file, const char *device_name);
130 9b87e19b Gerd Hoffmann
static int usb_linux_update_endp_table(USBHostDevice *s);
131 26a9e82a Gerd Hoffmann
132 d8e17efd Gerd Hoffmann
static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p)
133 d8e17efd Gerd Hoffmann
{
134 d8e17efd Gerd Hoffmann
    static const int usbfs[] = {
135 d8e17efd Gerd Hoffmann
        [USB_ENDPOINT_XFER_CONTROL] = USBDEVFS_URB_TYPE_CONTROL,
136 d8e17efd Gerd Hoffmann
        [USB_ENDPOINT_XFER_ISOC]    = USBDEVFS_URB_TYPE_ISO,
137 d8e17efd Gerd Hoffmann
        [USB_ENDPOINT_XFER_BULK]    = USBDEVFS_URB_TYPE_BULK,
138 d8e17efd Gerd Hoffmann
        [USB_ENDPOINT_XFER_INT]     = USBDEVFS_URB_TYPE_INTERRUPT,
139 d8e17efd Gerd Hoffmann
    };
140 079d0b7f Gerd Hoffmann
    uint8_t type = p->ep->type;
141 d8e17efd Gerd Hoffmann
    assert(type < ARRAY_SIZE(usbfs));
142 d8e17efd Gerd Hoffmann
    return usbfs[type];
143 d8e17efd Gerd Hoffmann
}
144 d8e17efd Gerd Hoffmann
145 c7662daa Gerd Hoffmann
static int usb_host_do_reset(USBHostDevice *dev)
146 c7662daa Gerd Hoffmann
{
147 c7662daa Gerd Hoffmann
    struct timeval s, e;
148 c7662daa Gerd Hoffmann
    uint32_t usecs;
149 c7662daa Gerd Hoffmann
    int ret;
150 c7662daa Gerd Hoffmann
151 c7662daa Gerd Hoffmann
    gettimeofday(&s, NULL);
152 c7662daa Gerd Hoffmann
    ret = ioctl(dev->fd, USBDEVFS_RESET);
153 c7662daa Gerd Hoffmann
    gettimeofday(&e, NULL);
154 c7662daa Gerd Hoffmann
    usecs = (e.tv_sec  - s.tv_sec) * 1000000;
155 c7662daa Gerd Hoffmann
    usecs += e.tv_usec - s.tv_usec;
156 c7662daa Gerd Hoffmann
    if (usecs > 1000000) {
157 c7662daa Gerd Hoffmann
        /* more than a second, something is fishy, broken usb device? */
158 c7662daa Gerd Hoffmann
        fprintf(stderr, "husb: device %d:%d reset took %d.%06d seconds\n",
159 c7662daa Gerd Hoffmann
                dev->bus_num, dev->addr, usecs / 1000000, usecs % 1000000);
160 c7662daa Gerd Hoffmann
    }
161 c7662daa Gerd Hoffmann
    return ret;
162 c7662daa Gerd Hoffmann
}
163 c7662daa Gerd Hoffmann
164 c0e5750b Gerd Hoffmann
static struct endp_data *get_endp(USBHostDevice *s, int pid, int ep)
165 ca3a36cf Gerd Hoffmann
{
166 c0e5750b Gerd Hoffmann
    struct endp_data *eps = pid == USB_TOKEN_IN ? s->ep_in : s->ep_out;
167 c0e5750b Gerd Hoffmann
    assert(pid == USB_TOKEN_IN || pid == USB_TOKEN_OUT);
168 d8e17efd Gerd Hoffmann
    assert(ep > 0 && ep <= USB_MAX_ENDPOINTS);
169 c0e5750b Gerd Hoffmann
    return eps + ep - 1;
170 ca3a36cf Gerd Hoffmann
}
171 ca3a36cf Gerd Hoffmann
172 c0e5750b Gerd Hoffmann
static int is_isoc(USBHostDevice *s, int pid, int ep)
173 64838171 aliguori
{
174 d8e17efd Gerd Hoffmann
    return usb_ep_get_type(&s->dev, pid, ep) == USB_ENDPOINT_XFER_ISOC;
175 64838171 aliguori
}
176 64838171 aliguori
177 c0e5750b Gerd Hoffmann
static int is_valid(USBHostDevice *s, int pid, int ep)
178 a0b5fece Hans de Goede
{
179 d8e17efd Gerd Hoffmann
    return usb_ep_get_type(&s->dev, pid, ep) != USB_ENDPOINT_XFER_INVALID;
180 a0b5fece Hans de Goede
}
181 a0b5fece Hans de Goede
182 c0e5750b Gerd Hoffmann
static int is_halted(USBHostDevice *s, int pid, int ep)
183 64838171 aliguori
{
184 c0e5750b Gerd Hoffmann
    return get_endp(s, pid, ep)->halted;
185 64838171 aliguori
}
186 64838171 aliguori
187 c0e5750b Gerd Hoffmann
static void clear_halt(USBHostDevice *s, int pid, int ep)
188 64838171 aliguori
{
189 e6a2f500 Gerd Hoffmann
    trace_usb_host_ep_clear_halt(s->bus_num, s->addr, ep);
190 c0e5750b Gerd Hoffmann
    get_endp(s, pid, ep)->halted = 0;
191 64838171 aliguori
}
192 64838171 aliguori
193 c0e5750b Gerd Hoffmann
static void set_halt(USBHostDevice *s, int pid, int ep)
194 64838171 aliguori
{
195 c0e5750b Gerd Hoffmann
    if (ep != 0) {
196 c0e5750b Gerd Hoffmann
        trace_usb_host_ep_set_halt(s->bus_num, s->addr, ep);
197 c0e5750b Gerd Hoffmann
        get_endp(s, pid, ep)->halted = 1;
198 c0e5750b Gerd Hoffmann
    }
199 64838171 aliguori
}
200 64838171 aliguori
201 c0e5750b Gerd Hoffmann
static int is_iso_started(USBHostDevice *s, int pid, int ep)
202 bb6d5498 Hans de Goede
{
203 c0e5750b Gerd Hoffmann
    return get_endp(s, pid, ep)->iso_started;
204 bb6d5498 Hans de Goede
}
205 bb6d5498 Hans de Goede
206 c0e5750b Gerd Hoffmann
static void clear_iso_started(USBHostDevice *s, int pid, int ep)
207 bb6d5498 Hans de Goede
{
208 e6a2f500 Gerd Hoffmann
    trace_usb_host_ep_stop_iso(s->bus_num, s->addr, ep);
209 c0e5750b Gerd Hoffmann
    get_endp(s, pid, ep)->iso_started = 0;
210 bb6d5498 Hans de Goede
}
211 bb6d5498 Hans de Goede
212 c0e5750b Gerd Hoffmann
static void set_iso_started(USBHostDevice *s, int pid, int ep)
213 bb6d5498 Hans de Goede
{
214 c0e5750b Gerd Hoffmann
    struct endp_data *e = get_endp(s, pid, ep);
215 e6a2f500 Gerd Hoffmann
216 e6a2f500 Gerd Hoffmann
    trace_usb_host_ep_start_iso(s->bus_num, s->addr, ep);
217 82887262 Gerd Hoffmann
    if (!e->iso_started) {
218 82887262 Gerd Hoffmann
        e->iso_started = 1;
219 82887262 Gerd Hoffmann
        e->inflight = 0;
220 82887262 Gerd Hoffmann
    }
221 82887262 Gerd Hoffmann
}
222 82887262 Gerd Hoffmann
223 c0e5750b Gerd Hoffmann
static int change_iso_inflight(USBHostDevice *s, int pid, int ep, int value)
224 82887262 Gerd Hoffmann
{
225 c0e5750b Gerd Hoffmann
    struct endp_data *e = get_endp(s, pid, ep);
226 82887262 Gerd Hoffmann
227 82887262 Gerd Hoffmann
    e->inflight += value;
228 82887262 Gerd Hoffmann
    return e->inflight;
229 bb6d5498 Hans de Goede
}
230 bb6d5498 Hans de Goede
231 c0e5750b Gerd Hoffmann
static void set_iso_urb(USBHostDevice *s, int pid, int ep, AsyncURB *iso_urb)
232 060dc841 Hans de Goede
{
233 c0e5750b Gerd Hoffmann
    get_endp(s, pid, ep)->iso_urb = iso_urb;
234 060dc841 Hans de Goede
}
235 060dc841 Hans de Goede
236 c0e5750b Gerd Hoffmann
static AsyncURB *get_iso_urb(USBHostDevice *s, int pid, int ep)
237 060dc841 Hans de Goede
{
238 c0e5750b Gerd Hoffmann
    return get_endp(s, pid, ep)->iso_urb;
239 060dc841 Hans de Goede
}
240 060dc841 Hans de Goede
241 c0e5750b Gerd Hoffmann
static void set_iso_urb_idx(USBHostDevice *s, int pid, int ep, int i)
242 060dc841 Hans de Goede
{
243 c0e5750b Gerd Hoffmann
    get_endp(s, pid, ep)->iso_urb_idx = i;
244 060dc841 Hans de Goede
}
245 060dc841 Hans de Goede
246 c0e5750b Gerd Hoffmann
static int get_iso_urb_idx(USBHostDevice *s, int pid, int ep)
247 060dc841 Hans de Goede
{
248 c0e5750b Gerd Hoffmann
    return get_endp(s, pid, ep)->iso_urb_idx;
249 060dc841 Hans de Goede
}
250 060dc841 Hans de Goede
251 c0e5750b Gerd Hoffmann
static void set_iso_buffer_used(USBHostDevice *s, int pid, int ep, int i)
252 bb6d5498 Hans de Goede
{
253 c0e5750b Gerd Hoffmann
    get_endp(s, pid, ep)->iso_buffer_used = i;
254 bb6d5498 Hans de Goede
}
255 bb6d5498 Hans de Goede
256 c0e5750b Gerd Hoffmann
static int get_iso_buffer_used(USBHostDevice *s, int pid, int ep)
257 bb6d5498 Hans de Goede
{
258 c0e5750b Gerd Hoffmann
    return get_endp(s, pid, ep)->iso_buffer_used;
259 bb6d5498 Hans de Goede
}
260 bb6d5498 Hans de Goede
261 2791104c David Ahern
/*
262 64838171 aliguori
 * Async URB state.
263 060dc841 Hans de Goede
 * We always allocate iso packet descriptors even for bulk transfers
264 2791104c David Ahern
 * to simplify allocation and casts.
265 64838171 aliguori
 */
266 060dc841 Hans de Goede
struct AsyncURB
267 64838171 aliguori
{
268 64838171 aliguori
    struct usbdevfs_urb urb;
269 060dc841 Hans de Goede
    struct usbdevfs_iso_packet_desc isocpd[ISO_FRAME_DESC_PER_URB];
270 7a8fc83f Gerd Hoffmann
    USBHostDevice *hdev;
271 7a8fc83f Gerd Hoffmann
    QLIST_ENTRY(AsyncURB) next;
272 b9dc033c balrog
273 060dc841 Hans de Goede
    /* For regular async urbs */
274 64838171 aliguori
    USBPacket     *packet;
275 71138531 Gerd Hoffmann
    int more; /* large transfer, more urbs follow */
276 060dc841 Hans de Goede
277 060dc841 Hans de Goede
    /* For buffered iso handling */
278 060dc841 Hans de Goede
    int iso_frame_idx; /* -1 means in flight */
279 060dc841 Hans de Goede
};
280 b9dc033c balrog
281 7a8fc83f Gerd Hoffmann
static AsyncURB *async_alloc(USBHostDevice *s)
282 b9dc033c balrog
{
283 7267c094 Anthony Liguori
    AsyncURB *aurb = g_malloc0(sizeof(AsyncURB));
284 7a8fc83f Gerd Hoffmann
    aurb->hdev = s;
285 7a8fc83f Gerd Hoffmann
    QLIST_INSERT_HEAD(&s->aurbs, aurb, next);
286 7a8fc83f Gerd Hoffmann
    return aurb;
287 b9dc033c balrog
}
288 b9dc033c balrog
289 64838171 aliguori
static void async_free(AsyncURB *aurb)
290 b9dc033c balrog
{
291 7a8fc83f Gerd Hoffmann
    QLIST_REMOVE(aurb, next);
292 7267c094 Anthony Liguori
    g_free(aurb);
293 64838171 aliguori
}
294 b9dc033c balrog
295 41c01ee7 Gerd Hoffmann
static void do_disconnect(USBHostDevice *s)
296 41c01ee7 Gerd Hoffmann
{
297 41c01ee7 Gerd Hoffmann
    usb_host_close(s);
298 41c01ee7 Gerd Hoffmann
    usb_host_auto_check(NULL);
299 41c01ee7 Gerd Hoffmann
}
300 41c01ee7 Gerd Hoffmann
301 64838171 aliguori
static void async_complete(void *opaque)
302 64838171 aliguori
{
303 64838171 aliguori
    USBHostDevice *s = opaque;
304 64838171 aliguori
    AsyncURB *aurb;
305 82887262 Gerd Hoffmann
    int urbs = 0;
306 64838171 aliguori
307 64838171 aliguori
    while (1) {
308 2791104c David Ahern
        USBPacket *p;
309 b9dc033c balrog
310 2791104c David Ahern
        int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
311 64838171 aliguori
        if (r < 0) {
312 2791104c David Ahern
            if (errno == EAGAIN) {
313 82887262 Gerd Hoffmann
                if (urbs > 2) {
314 82887262 Gerd Hoffmann
                    fprintf(stderr, "husb: %d iso urbs finished at once\n", urbs);
315 82887262 Gerd Hoffmann
                }
316 64838171 aliguori
                return;
317 2791104c David Ahern
            }
318 40197c35 Gerd Hoffmann
            if (errno == ENODEV) {
319 40197c35 Gerd Hoffmann
                if (!s->closing) {
320 40197c35 Gerd Hoffmann
                    trace_usb_host_disconnect(s->bus_num, s->addr);
321 40197c35 Gerd Hoffmann
                    do_disconnect(s);
322 40197c35 Gerd Hoffmann
                }
323 64838171 aliguori
                return;
324 64838171 aliguori
            }
325 64838171 aliguori
326 e6a2f500 Gerd Hoffmann
            perror("USBDEVFS_REAPURBNDELAY");
327 64838171 aliguori
            return;
328 b9dc033c balrog
        }
329 64838171 aliguori
330 2791104c David Ahern
        DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
331 64838171 aliguori
                aurb, aurb->urb.status, aurb->urb.actual_length);
332 64838171 aliguori
333 060dc841 Hans de Goede
        /* If this is a buffered iso urb mark it as complete and don't do
334 060dc841 Hans de Goede
           anything else (it is handled further in usb_host_handle_iso_data) */
335 060dc841 Hans de Goede
        if (aurb->iso_frame_idx == -1) {
336 82887262 Gerd Hoffmann
            int inflight;
337 c0e5750b Gerd Hoffmann
            int pid = (aurb->urb.endpoint & USB_DIR_IN) ?
338 c0e5750b Gerd Hoffmann
                USB_TOKEN_IN : USB_TOKEN_OUT;
339 c0e5750b Gerd Hoffmann
            int ep = aurb->urb.endpoint & 0xf;
340 060dc841 Hans de Goede
            if (aurb->urb.status == -EPIPE) {
341 c0e5750b Gerd Hoffmann
                set_halt(s, pid, ep);
342 060dc841 Hans de Goede
            }
343 060dc841 Hans de Goede
            aurb->iso_frame_idx = 0;
344 82887262 Gerd Hoffmann
            urbs++;
345 c0e5750b Gerd Hoffmann
            inflight = change_iso_inflight(s, pid, ep, -1);
346 c0e5750b Gerd Hoffmann
            if (inflight == 0 && is_iso_started(s, pid, ep)) {
347 82887262 Gerd Hoffmann
                fprintf(stderr, "husb: out of buffers for iso stream\n");
348 82887262 Gerd Hoffmann
            }
349 060dc841 Hans de Goede
            continue;
350 060dc841 Hans de Goede
        }
351 060dc841 Hans de Goede
352 060dc841 Hans de Goede
        p = aurb->packet;
353 e6a2f500 Gerd Hoffmann
        trace_usb_host_urb_complete(s->bus_num, s->addr, aurb, aurb->urb.status,
354 e6a2f500 Gerd Hoffmann
                                    aurb->urb.actual_length, aurb->more);
355 060dc841 Hans de Goede
356 2791104c David Ahern
        if (p) {
357 64838171 aliguori
            switch (aurb->urb.status) {
358 64838171 aliguori
            case 0:
359 4f4321c1 Gerd Hoffmann
                p->result += aurb->urb.actual_length;
360 64838171 aliguori
                break;
361 64838171 aliguori
362 64838171 aliguori
            case -EPIPE:
363 079d0b7f Gerd Hoffmann
                set_halt(s, p->pid, p->ep->nr);
364 4f4321c1 Gerd Hoffmann
                p->result = USB_RET_STALL;
365 2791104c David Ahern
                break;
366 dcc7e25f Paul Bolle
367 64838171 aliguori
            default:
368 4f4321c1 Gerd Hoffmann
                p->result = USB_RET_NAK;
369 64838171 aliguori
                break;
370 64838171 aliguori
            }
371 64838171 aliguori
372 50b7963e Hans de Goede
            if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
373 e6a2f500 Gerd Hoffmann
                trace_usb_host_req_complete(s->bus_num, s->addr, p->result);
374 50b7963e Hans de Goede
                usb_generic_async_ctrl_complete(&s->dev, p);
375 71138531 Gerd Hoffmann
            } else if (!aurb->more) {
376 e6a2f500 Gerd Hoffmann
                trace_usb_host_req_complete(s->bus_num, s->addr, p->result);
377 50b7963e Hans de Goede
                usb_packet_complete(&s->dev, p);
378 50b7963e Hans de Goede
            }
379 2791104c David Ahern
        }
380 64838171 aliguori
381 64838171 aliguori
        async_free(aurb);
382 b9dc033c balrog
    }
383 b9dc033c balrog
}
384 b9dc033c balrog
385 eb5e680a Gerd Hoffmann
static void usb_host_async_cancel(USBDevice *dev, USBPacket *p)
386 b9dc033c balrog
{
387 eb5e680a Gerd Hoffmann
    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
388 227ebeb5 Gerd Hoffmann
    AsyncURB *aurb;
389 b9dc033c balrog
390 227ebeb5 Gerd Hoffmann
    QLIST_FOREACH(aurb, &s->aurbs, next) {
391 227ebeb5 Gerd Hoffmann
        if (p != aurb->packet) {
392 227ebeb5 Gerd Hoffmann
            continue;
393 227ebeb5 Gerd Hoffmann
        }
394 64838171 aliguori
395 227ebeb5 Gerd Hoffmann
        DPRINTF("husb: async cancel: packet %p, aurb %p\n", p, aurb);
396 b9dc033c balrog
397 227ebeb5 Gerd Hoffmann
        /* Mark it as dead (see async_complete above) */
398 227ebeb5 Gerd Hoffmann
        aurb->packet = NULL;
399 227ebeb5 Gerd Hoffmann
400 227ebeb5 Gerd Hoffmann
        int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb);
401 227ebeb5 Gerd Hoffmann
        if (r < 0) {
402 227ebeb5 Gerd Hoffmann
            DPRINTF("husb: async. discard urb failed errno %d\n", errno);
403 227ebeb5 Gerd Hoffmann
        }
404 b9dc033c balrog
    }
405 b9dc033c balrog
}
406 b9dc033c balrog
407 097db438 Gerd Hoffmann
static int usb_host_open_device(int bus, int addr)
408 097db438 Gerd Hoffmann
{
409 097db438 Gerd Hoffmann
    const char *usbfs = NULL;
410 097db438 Gerd Hoffmann
    char filename[32];
411 097db438 Gerd Hoffmann
    struct stat st;
412 097db438 Gerd Hoffmann
    int fd, rc;
413 097db438 Gerd Hoffmann
414 097db438 Gerd Hoffmann
    rc = stat("/dev/bus/usb", &st);
415 097db438 Gerd Hoffmann
    if (rc == 0 && S_ISDIR(st.st_mode)) {
416 097db438 Gerd Hoffmann
        /* udev-created device nodes available */
417 097db438 Gerd Hoffmann
        usbfs = "/dev/bus/usb";
418 097db438 Gerd Hoffmann
    } else {
419 097db438 Gerd Hoffmann
        /* fallback: usbfs mounted below /proc */
420 097db438 Gerd Hoffmann
        usbfs = "/proc/bus/usb";
421 097db438 Gerd Hoffmann
    }
422 097db438 Gerd Hoffmann
423 097db438 Gerd Hoffmann
    snprintf(filename, sizeof(filename), "%s/%03d/%03d",
424 097db438 Gerd Hoffmann
             usbfs, bus, addr);
425 097db438 Gerd Hoffmann
    fd = open(filename, O_RDWR | O_NONBLOCK);
426 097db438 Gerd Hoffmann
    if (fd < 0) {
427 097db438 Gerd Hoffmann
        fprintf(stderr, "husb: open %s: %s\n", filename, strerror(errno));
428 097db438 Gerd Hoffmann
    }
429 097db438 Gerd Hoffmann
    return fd;
430 097db438 Gerd Hoffmann
}
431 097db438 Gerd Hoffmann
432 e6274727 Gerd Hoffmann
static int usb_host_claim_port(USBHostDevice *s)
433 e6274727 Gerd Hoffmann
{
434 e6274727 Gerd Hoffmann
#ifdef USBDEVFS_CLAIM_PORT
435 e6274727 Gerd Hoffmann
    char *h, hub_name[64], line[1024];
436 c75fead6 Gerd Hoffmann
    int hub_addr, ret;
437 e6274727 Gerd Hoffmann
438 e6274727 Gerd Hoffmann
    snprintf(hub_name, sizeof(hub_name), "%d-%s",
439 e6274727 Gerd Hoffmann
             s->match.bus_num, s->match.port);
440 e6274727 Gerd Hoffmann
441 e6274727 Gerd Hoffmann
    /* try strip off last ".$portnr" to get hub */
442 e6274727 Gerd Hoffmann
    h = strrchr(hub_name, '.');
443 e6274727 Gerd Hoffmann
    if (h != NULL) {
444 c75fead6 Gerd Hoffmann
        s->hub_port = atoi(h+1);
445 e6274727 Gerd Hoffmann
        *h = '\0';
446 e6274727 Gerd Hoffmann
    } else {
447 e6274727 Gerd Hoffmann
        /* no dot in there -> it is the root hub */
448 e6274727 Gerd Hoffmann
        snprintf(hub_name, sizeof(hub_name), "usb%d",
449 e6274727 Gerd Hoffmann
                 s->match.bus_num);
450 c75fead6 Gerd Hoffmann
        s->hub_port = atoi(s->match.port);
451 e6274727 Gerd Hoffmann
    }
452 e6274727 Gerd Hoffmann
453 e6274727 Gerd Hoffmann
    if (!usb_host_read_file(line, sizeof(line), "devnum",
454 e6274727 Gerd Hoffmann
                            hub_name)) {
455 e6274727 Gerd Hoffmann
        return -1;
456 e6274727 Gerd Hoffmann
    }
457 e6274727 Gerd Hoffmann
    if (sscanf(line, "%d", &hub_addr) != 1) {
458 e6274727 Gerd Hoffmann
        return -1;
459 e6274727 Gerd Hoffmann
    }
460 e6274727 Gerd Hoffmann
461 097db438 Gerd Hoffmann
    s->hub_fd = usb_host_open_device(s->match.bus_num, hub_addr);
462 e6274727 Gerd Hoffmann
    if (s->hub_fd < 0) {
463 e6274727 Gerd Hoffmann
        return -1;
464 e6274727 Gerd Hoffmann
    }
465 e6274727 Gerd Hoffmann
466 c75fead6 Gerd Hoffmann
    ret = ioctl(s->hub_fd, USBDEVFS_CLAIM_PORT, &s->hub_port);
467 e6274727 Gerd Hoffmann
    if (ret < 0) {
468 e6274727 Gerd Hoffmann
        close(s->hub_fd);
469 e6274727 Gerd Hoffmann
        s->hub_fd = -1;
470 e6274727 Gerd Hoffmann
        return -1;
471 e6274727 Gerd Hoffmann
    }
472 e6274727 Gerd Hoffmann
473 c75fead6 Gerd Hoffmann
    trace_usb_host_claim_port(s->match.bus_num, hub_addr, s->hub_port);
474 e6274727 Gerd Hoffmann
    return 0;
475 e6274727 Gerd Hoffmann
#else
476 e6274727 Gerd Hoffmann
    return -1;
477 e6274727 Gerd Hoffmann
#endif
478 e6274727 Gerd Hoffmann
}
479 e6274727 Gerd Hoffmann
480 c75fead6 Gerd Hoffmann
static void usb_host_release_port(USBHostDevice *s)
481 c75fead6 Gerd Hoffmann
{
482 c75fead6 Gerd Hoffmann
    if (s->hub_fd == -1) {
483 c75fead6 Gerd Hoffmann
        return;
484 c75fead6 Gerd Hoffmann
    }
485 c75fead6 Gerd Hoffmann
#ifdef USBDEVFS_RELEASE_PORT
486 c75fead6 Gerd Hoffmann
    ioctl(s->hub_fd, USBDEVFS_RELEASE_PORT, &s->hub_port);
487 c75fead6 Gerd Hoffmann
#endif
488 c75fead6 Gerd Hoffmann
    close(s->hub_fd);
489 c75fead6 Gerd Hoffmann
    s->hub_fd = -1;
490 c75fead6 Gerd Hoffmann
}
491 c75fead6 Gerd Hoffmann
492 e6274727 Gerd Hoffmann
static int usb_host_disconnect_ifaces(USBHostDevice *dev, int nb_interfaces)
493 e6274727 Gerd Hoffmann
{
494 e6274727 Gerd Hoffmann
    /* earlier Linux 2.4 do not support that */
495 e6274727 Gerd Hoffmann
#ifdef USBDEVFS_DISCONNECT
496 e6274727 Gerd Hoffmann
    struct usbdevfs_ioctl ctrl;
497 e6274727 Gerd Hoffmann
    int ret, interface;
498 e6274727 Gerd Hoffmann
499 e6274727 Gerd Hoffmann
    for (interface = 0; interface < nb_interfaces; interface++) {
500 e6274727 Gerd Hoffmann
        ctrl.ioctl_code = USBDEVFS_DISCONNECT;
501 e6274727 Gerd Hoffmann
        ctrl.ifno = interface;
502 e6274727 Gerd Hoffmann
        ctrl.data = 0;
503 e6274727 Gerd Hoffmann
        ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
504 e6274727 Gerd Hoffmann
        if (ret < 0 && errno != ENODATA) {
505 e6274727 Gerd Hoffmann
            perror("USBDEVFS_DISCONNECT");
506 e6274727 Gerd Hoffmann
            return -1;
507 e6274727 Gerd Hoffmann
        }
508 e6274727 Gerd Hoffmann
    }
509 e6274727 Gerd Hoffmann
#endif
510 e6274727 Gerd Hoffmann
    return 0;
511 e6274727 Gerd Hoffmann
}
512 e6274727 Gerd Hoffmann
513 0fcc3bfc Gerd Hoffmann
static int usb_linux_get_num_interfaces(USBHostDevice *s)
514 0fcc3bfc Gerd Hoffmann
{
515 0fcc3bfc Gerd Hoffmann
    char device_name[64], line[1024];
516 0fcc3bfc Gerd Hoffmann
    int num_interfaces = 0;
517 0fcc3bfc Gerd Hoffmann
518 0fcc3bfc Gerd Hoffmann
    sprintf(device_name, "%d-%s", s->bus_num, s->port);
519 0fcc3bfc Gerd Hoffmann
    if (!usb_host_read_file(line, sizeof(line), "bNumInterfaces",
520 0fcc3bfc Gerd Hoffmann
                            device_name)) {
521 0fcc3bfc Gerd Hoffmann
        return -1;
522 0fcc3bfc Gerd Hoffmann
    }
523 0fcc3bfc Gerd Hoffmann
    if (sscanf(line, "%d", &num_interfaces) != 1) {
524 0fcc3bfc Gerd Hoffmann
        return -1;
525 0fcc3bfc Gerd Hoffmann
    }
526 0fcc3bfc Gerd Hoffmann
    return num_interfaces;
527 0fcc3bfc Gerd Hoffmann
}
528 0fcc3bfc Gerd Hoffmann
529 446ab128 aliguori
static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
530 b9dc033c balrog
{
531 41c01ee7 Gerd Hoffmann
    const char *op = NULL;
532 b9dc033c balrog
    int dev_descr_len, config_descr_len;
533 d4c4e6fd Blue Swirl
    int interface, nb_interfaces;
534 b9dc033c balrog
    int ret, i;
535 b9dc033c balrog
536 1de14d43 Gerd Hoffmann
    for (i = 0; i < USB_MAX_INTERFACES; i++) {
537 1de14d43 Gerd Hoffmann
        dev->dev.altsetting[i] = 0;
538 1de14d43 Gerd Hoffmann
    }
539 1de14d43 Gerd Hoffmann
540 eb7700bb Gerd Hoffmann
    if (configuration == 0) { /* address state - ignore */
541 65360511 Gerd Hoffmann
        dev->dev.ninterfaces   = 0;
542 65360511 Gerd Hoffmann
        dev->dev.configuration = 0;
543 b9dc033c balrog
        return 1;
544 eb7700bb Gerd Hoffmann
    }
545 b9dc033c balrog
546 d0f2c4c6 malc
    DPRINTF("husb: claiming interfaces. config %d\n", configuration);
547 446ab128 aliguori
548 b9dc033c balrog
    i = 0;
549 b9dc033c balrog
    dev_descr_len = dev->descr[0];
550 2791104c David Ahern
    if (dev_descr_len > dev->descr_len) {
551 61c1117f Hans de Goede
        fprintf(stderr, "husb: update iface failed. descr too short\n");
552 61c1117f Hans de Goede
        return 0;
553 2791104c David Ahern
    }
554 b9dc033c balrog
555 b9dc033c balrog
    i += dev_descr_len;
556 b9dc033c balrog
    while (i < dev->descr_len) {
557 2791104c David Ahern
        DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
558 2791104c David Ahern
                i, dev->descr_len,
559 b9dc033c balrog
               dev->descr[i], dev->descr[i+1]);
560 64838171 aliguori
561 b9dc033c balrog
        if (dev->descr[i+1] != USB_DT_CONFIG) {
562 b9dc033c balrog
            i += dev->descr[i];
563 b9dc033c balrog
            continue;
564 b9dc033c balrog
        }
565 b9dc033c balrog
        config_descr_len = dev->descr[i];
566 b9dc033c balrog
567 e6a2f500 Gerd Hoffmann
        DPRINTF("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
568 1f3870ab aliguori
569 eb7700bb Gerd Hoffmann
        if (configuration == dev->descr[i + 5]) {
570 446ab128 aliguori
            configuration = dev->descr[i + 5];
571 b9dc033c balrog
            break;
572 446ab128 aliguori
        }
573 b9dc033c balrog
574 b9dc033c balrog
        i += config_descr_len;
575 b9dc033c balrog
    }
576 b9dc033c balrog
577 b9dc033c balrog
    if (i >= dev->descr_len) {
578 2791104c David Ahern
        fprintf(stderr,
579 2791104c David Ahern
                "husb: update iface failed. no matching configuration\n");
580 61c1117f Hans de Goede
        return 0;
581 b9dc033c balrog
    }
582 b9dc033c balrog
    nb_interfaces = dev->descr[i + 4];
583 b9dc033c balrog
584 e6274727 Gerd Hoffmann
    if (usb_host_disconnect_ifaces(dev, nb_interfaces) < 0) {
585 e6274727 Gerd Hoffmann
        goto fail;
586 b9dc033c balrog
    }
587 b9dc033c balrog
588 b9dc033c balrog
    /* XXX: only grab if all interfaces are free */
589 b9dc033c balrog
    for (interface = 0; interface < nb_interfaces; interface++) {
590 41c01ee7 Gerd Hoffmann
        op = "USBDEVFS_CLAIMINTERFACE";
591 b9dc033c balrog
        ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
592 b9dc033c balrog
        if (ret < 0) {
593 41c01ee7 Gerd Hoffmann
            goto fail;
594 b9dc033c balrog
        }
595 b9dc033c balrog
    }
596 b9dc033c balrog
597 e6a2f500 Gerd Hoffmann
    trace_usb_host_claim_interfaces(dev->bus_num, dev->addr,
598 e6a2f500 Gerd Hoffmann
                                    nb_interfaces, configuration);
599 b9dc033c balrog
600 65360511 Gerd Hoffmann
    dev->dev.ninterfaces   = nb_interfaces;
601 65360511 Gerd Hoffmann
    dev->dev.configuration = configuration;
602 446ab128 aliguori
    return 1;
603 41c01ee7 Gerd Hoffmann
604 41c01ee7 Gerd Hoffmann
fail:
605 41c01ee7 Gerd Hoffmann
    if (errno == ENODEV) {
606 41c01ee7 Gerd Hoffmann
        do_disconnect(dev);
607 41c01ee7 Gerd Hoffmann
    }
608 41c01ee7 Gerd Hoffmann
    perror(op);
609 41c01ee7 Gerd Hoffmann
    return 0;
610 446ab128 aliguori
}
611 446ab128 aliguori
612 446ab128 aliguori
static int usb_host_release_interfaces(USBHostDevice *s)
613 446ab128 aliguori
{
614 446ab128 aliguori
    int ret, i;
615 446ab128 aliguori
616 e6a2f500 Gerd Hoffmann
    trace_usb_host_release_interfaces(s->bus_num, s->addr);
617 446ab128 aliguori
618 65360511 Gerd Hoffmann
    for (i = 0; i < s->dev.ninterfaces; i++) {
619 446ab128 aliguori
        ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i);
620 446ab128 aliguori
        if (ret < 0) {
621 e6a2f500 Gerd Hoffmann
            perror("USBDEVFS_RELEASEINTERFACE");
622 446ab128 aliguori
            return 0;
623 446ab128 aliguori
        }
624 446ab128 aliguori
    }
625 b9dc033c balrog
    return 1;
626 b9dc033c balrog
}
627 b9dc033c balrog
628 059809e4 bellard
static void usb_host_handle_reset(USBDevice *dev)
629 bb36d470 bellard
{
630 26a9e82a Gerd Hoffmann
    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
631 64838171 aliguori
632 e6a2f500 Gerd Hoffmann
    trace_usb_host_reset(s->bus_num, s->addr);
633 64838171 aliguori
634 c7662daa Gerd Hoffmann
    usb_host_do_reset(s);;
635 446ab128 aliguori
636 eb7700bb Gerd Hoffmann
    usb_host_claim_interfaces(s, 0);
637 9b87e19b Gerd Hoffmann
    usb_linux_update_endp_table(s);
638 5fafdf24 ths
}
639 bb36d470 bellard
640 059809e4 bellard
static void usb_host_handle_destroy(USBDevice *dev)
641 059809e4 bellard
{
642 059809e4 bellard
    USBHostDevice *s = (USBHostDevice *)dev;
643 059809e4 bellard
644 c75fead6 Gerd Hoffmann
    usb_host_release_port(s);
645 26a9e82a Gerd Hoffmann
    usb_host_close(s);
646 26a9e82a Gerd Hoffmann
    QTAILQ_REMOVE(&hostdevs, s, next);
647 b373a63a Shahar Havivi
    qemu_remove_exit_notifier(&s->exit);
648 059809e4 bellard
}
649 059809e4 bellard
650 060dc841 Hans de Goede
/* iso data is special, we need to keep enough urbs in flight to make sure
651 060dc841 Hans de Goede
   that the controller never runs out of them, otherwise the device will
652 060dc841 Hans de Goede
   likely suffer a buffer underrun / overrun. */
653 c0e5750b Gerd Hoffmann
static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, int pid, uint8_t ep)
654 060dc841 Hans de Goede
{
655 060dc841 Hans de Goede
    AsyncURB *aurb;
656 f003397c Gerd Hoffmann
    int i, j, len = usb_ep_get_max_packet_size(&s->dev, pid, ep);
657 060dc841 Hans de Goede
658 7267c094 Anthony Liguori
    aurb = g_malloc0(s->iso_urb_count * sizeof(*aurb));
659 b81bcd8a Gerd Hoffmann
    for (i = 0; i < s->iso_urb_count; i++) {
660 060dc841 Hans de Goede
        aurb[i].urb.endpoint      = ep;
661 060dc841 Hans de Goede
        aurb[i].urb.buffer_length = ISO_FRAME_DESC_PER_URB * len;
662 7267c094 Anthony Liguori
        aurb[i].urb.buffer        = g_malloc(aurb[i].urb.buffer_length);
663 060dc841 Hans de Goede
        aurb[i].urb.type          = USBDEVFS_URB_TYPE_ISO;
664 060dc841 Hans de Goede
        aurb[i].urb.flags         = USBDEVFS_URB_ISO_ASAP;
665 060dc841 Hans de Goede
        aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB;
666 060dc841 Hans de Goede
        for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++)
667 060dc841 Hans de Goede
            aurb[i].urb.iso_frame_desc[j].length = len;
668 c0e5750b Gerd Hoffmann
        if (pid == USB_TOKEN_IN) {
669 060dc841 Hans de Goede
            aurb[i].urb.endpoint |= 0x80;
670 060dc841 Hans de Goede
            /* Mark as fully consumed (idle) */
671 060dc841 Hans de Goede
            aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB;
672 060dc841 Hans de Goede
        }
673 060dc841 Hans de Goede
    }
674 c0e5750b Gerd Hoffmann
    set_iso_urb(s, pid, ep, aurb);
675 060dc841 Hans de Goede
676 060dc841 Hans de Goede
    return aurb;
677 060dc841 Hans de Goede
}
678 060dc841 Hans de Goede
679 c0e5750b Gerd Hoffmann
static void usb_host_stop_n_free_iso(USBHostDevice *s, int pid, uint8_t ep)
680 060dc841 Hans de Goede
{
681 060dc841 Hans de Goede
    AsyncURB *aurb;
682 060dc841 Hans de Goede
    int i, ret, killed = 0, free = 1;
683 060dc841 Hans de Goede
684 c0e5750b Gerd Hoffmann
    aurb = get_iso_urb(s, pid, ep);
685 060dc841 Hans de Goede
    if (!aurb) {
686 060dc841 Hans de Goede
        return;
687 060dc841 Hans de Goede
    }
688 060dc841 Hans de Goede
689 b81bcd8a Gerd Hoffmann
    for (i = 0; i < s->iso_urb_count; i++) {
690 060dc841 Hans de Goede
        /* in flight? */
691 060dc841 Hans de Goede
        if (aurb[i].iso_frame_idx == -1) {
692 060dc841 Hans de Goede
            ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]);
693 060dc841 Hans de Goede
            if (ret < 0) {
694 e6a2f500 Gerd Hoffmann
                perror("USBDEVFS_DISCARDURB");
695 060dc841 Hans de Goede
                free = 0;
696 060dc841 Hans de Goede
                continue;
697 060dc841 Hans de Goede
            }
698 060dc841 Hans de Goede
            killed++;
699 060dc841 Hans de Goede
        }
700 060dc841 Hans de Goede
    }
701 060dc841 Hans de Goede
702 060dc841 Hans de Goede
    /* Make sure any urbs we've killed are reaped before we free them */
703 060dc841 Hans de Goede
    if (killed) {
704 060dc841 Hans de Goede
        async_complete(s);
705 060dc841 Hans de Goede
    }
706 060dc841 Hans de Goede
707 b81bcd8a Gerd Hoffmann
    for (i = 0; i < s->iso_urb_count; i++) {
708 7267c094 Anthony Liguori
        g_free(aurb[i].urb.buffer);
709 060dc841 Hans de Goede
    }
710 060dc841 Hans de Goede
711 060dc841 Hans de Goede
    if (free)
712 7267c094 Anthony Liguori
        g_free(aurb);
713 060dc841 Hans de Goede
    else
714 060dc841 Hans de Goede
        printf("husb: leaking iso urbs because of discard failure\n");
715 c0e5750b Gerd Hoffmann
    set_iso_urb(s, pid, ep, NULL);
716 c0e5750b Gerd Hoffmann
    set_iso_urb_idx(s, pid, ep, 0);
717 c0e5750b Gerd Hoffmann
    clear_iso_started(s, pid, ep);
718 060dc841 Hans de Goede
}
719 060dc841 Hans de Goede
720 060dc841 Hans de Goede
static int urb_status_to_usb_ret(int status)
721 060dc841 Hans de Goede
{
722 060dc841 Hans de Goede
    switch (status) {
723 060dc841 Hans de Goede
    case -EPIPE:
724 060dc841 Hans de Goede
        return USB_RET_STALL;
725 060dc841 Hans de Goede
    default:
726 060dc841 Hans de Goede
        return USB_RET_NAK;
727 060dc841 Hans de Goede
    }
728 060dc841 Hans de Goede
}
729 060dc841 Hans de Goede
730 bb6d5498 Hans de Goede
static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
731 060dc841 Hans de Goede
{
732 060dc841 Hans de Goede
    AsyncURB *aurb;
733 bb6d5498 Hans de Goede
    int i, j, ret, max_packet_size, offset, len = 0;
734 4f4321c1 Gerd Hoffmann
    uint8_t *buf;
735 975f2998 Hans de Goede
736 079d0b7f Gerd Hoffmann
    max_packet_size = p->ep->max_packet_size;
737 975f2998 Hans de Goede
    if (max_packet_size == 0)
738 975f2998 Hans de Goede
        return USB_RET_NAK;
739 060dc841 Hans de Goede
740 079d0b7f Gerd Hoffmann
    aurb = get_iso_urb(s, p->pid, p->ep->nr);
741 060dc841 Hans de Goede
    if (!aurb) {
742 079d0b7f Gerd Hoffmann
        aurb = usb_host_alloc_iso(s, p->pid, p->ep->nr);
743 060dc841 Hans de Goede
    }
744 060dc841 Hans de Goede
745 079d0b7f Gerd Hoffmann
    i = get_iso_urb_idx(s, p->pid, p->ep->nr);
746 060dc841 Hans de Goede
    j = aurb[i].iso_frame_idx;
747 060dc841 Hans de Goede
    if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
748 bb6d5498 Hans de Goede
        if (in) {
749 bb6d5498 Hans de Goede
            /* Check urb status  */
750 bb6d5498 Hans de Goede
            if (aurb[i].urb.status) {
751 bb6d5498 Hans de Goede
                len = urb_status_to_usb_ret(aurb[i].urb.status);
752 bb6d5498 Hans de Goede
                /* Move to the next urb */
753 bb6d5498 Hans de Goede
                aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
754 bb6d5498 Hans de Goede
            /* Check frame status */
755 bb6d5498 Hans de Goede
            } else if (aurb[i].urb.iso_frame_desc[j].status) {
756 bb6d5498 Hans de Goede
                len = urb_status_to_usb_ret(
757 bb6d5498 Hans de Goede
                                        aurb[i].urb.iso_frame_desc[j].status);
758 bb6d5498 Hans de Goede
            /* Check the frame fits */
759 4f4321c1 Gerd Hoffmann
            } else if (aurb[i].urb.iso_frame_desc[j].actual_length
760 4f4321c1 Gerd Hoffmann
                       > p->iov.size) {
761 bb6d5498 Hans de Goede
                printf("husb: received iso data is larger then packet\n");
762 bb6d5498 Hans de Goede
                len = USB_RET_NAK;
763 bb6d5498 Hans de Goede
            /* All good copy data over */
764 bb6d5498 Hans de Goede
            } else {
765 bb6d5498 Hans de Goede
                len = aurb[i].urb.iso_frame_desc[j].actual_length;
766 4f4321c1 Gerd Hoffmann
                buf  = aurb[i].urb.buffer +
767 4f4321c1 Gerd Hoffmann
                    j * aurb[i].urb.iso_frame_desc[0].length;
768 4f4321c1 Gerd Hoffmann
                usb_packet_copy(p, buf, len);
769 bb6d5498 Hans de Goede
            }
770 060dc841 Hans de Goede
        } else {
771 4f4321c1 Gerd Hoffmann
            len = p->iov.size;
772 079d0b7f Gerd Hoffmann
            offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->pid, p->ep->nr);
773 bb6d5498 Hans de Goede
774 bb6d5498 Hans de Goede
            /* Check the frame fits */
775 bb6d5498 Hans de Goede
            if (len > max_packet_size) {
776 bb6d5498 Hans de Goede
                printf("husb: send iso data is larger then max packet size\n");
777 bb6d5498 Hans de Goede
                return USB_RET_NAK;
778 bb6d5498 Hans de Goede
            }
779 bb6d5498 Hans de Goede
780 bb6d5498 Hans de Goede
            /* All good copy data over */
781 4f4321c1 Gerd Hoffmann
            usb_packet_copy(p, aurb[i].urb.buffer + offset, len);
782 bb6d5498 Hans de Goede
            aurb[i].urb.iso_frame_desc[j].length = len;
783 bb6d5498 Hans de Goede
            offset += len;
784 079d0b7f Gerd Hoffmann
            set_iso_buffer_used(s, p->pid, p->ep->nr, offset);
785 bb6d5498 Hans de Goede
786 bb6d5498 Hans de Goede
            /* Start the stream once we have buffered enough data */
787 079d0b7f Gerd Hoffmann
            if (!is_iso_started(s, p->pid, p->ep->nr) && i == 1 && j == 8) {
788 079d0b7f Gerd Hoffmann
                set_iso_started(s, p->pid, p->ep->nr);
789 bb6d5498 Hans de Goede
            }
790 060dc841 Hans de Goede
        }
791 060dc841 Hans de Goede
        aurb[i].iso_frame_idx++;
792 060dc841 Hans de Goede
        if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
793 b81bcd8a Gerd Hoffmann
            i = (i + 1) % s->iso_urb_count;
794 079d0b7f Gerd Hoffmann
            set_iso_urb_idx(s, p->pid, p->ep->nr, i);
795 060dc841 Hans de Goede
        }
796 bb6d5498 Hans de Goede
    } else {
797 bb6d5498 Hans de Goede
        if (in) {
798 079d0b7f Gerd Hoffmann
            set_iso_started(s, p->pid, p->ep->nr);
799 bb6d5498 Hans de Goede
        } else {
800 bb6d5498 Hans de Goede
            DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
801 bb6d5498 Hans de Goede
        }
802 060dc841 Hans de Goede
    }
803 060dc841 Hans de Goede
804 079d0b7f Gerd Hoffmann
    if (is_iso_started(s, p->pid, p->ep->nr)) {
805 bb6d5498 Hans de Goede
        /* (Re)-submit all fully consumed / filled urbs */
806 b81bcd8a Gerd Hoffmann
        for (i = 0; i < s->iso_urb_count; i++) {
807 bb6d5498 Hans de Goede
            if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
808 bb6d5498 Hans de Goede
                ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
809 bb6d5498 Hans de Goede
                if (ret < 0) {
810 e6a2f500 Gerd Hoffmann
                    perror("USBDEVFS_SUBMITURB");
811 bb6d5498 Hans de Goede
                    if (!in || len == 0) {
812 bb6d5498 Hans de Goede
                        switch(errno) {
813 bb6d5498 Hans de Goede
                        case ETIMEDOUT:
814 bb6d5498 Hans de Goede
                            len = USB_RET_NAK;
815 0225e254 Stefan Weil
                            break;
816 bb6d5498 Hans de Goede
                        case EPIPE:
817 bb6d5498 Hans de Goede
                        default:
818 bb6d5498 Hans de Goede
                            len = USB_RET_STALL;
819 bb6d5498 Hans de Goede
                        }
820 060dc841 Hans de Goede
                    }
821 bb6d5498 Hans de Goede
                    break;
822 060dc841 Hans de Goede
                }
823 bb6d5498 Hans de Goede
                aurb[i].iso_frame_idx = -1;
824 079d0b7f Gerd Hoffmann
                change_iso_inflight(s, p->pid, p->ep->nr, 1);
825 060dc841 Hans de Goede
            }
826 060dc841 Hans de Goede
        }
827 060dc841 Hans de Goede
    }
828 060dc841 Hans de Goede
829 060dc841 Hans de Goede
    return len;
830 060dc841 Hans de Goede
}
831 060dc841 Hans de Goede
832 50b7963e Hans de Goede
static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
833 bb36d470 bellard
{
834 50b7963e Hans de Goede
    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
835 64838171 aliguori
    struct usbdevfs_urb *urb;
836 446ab128 aliguori
    AsyncURB *aurb;
837 b621bab4 Gerd Hoffmann
    int ret, rem, prem, v;
838 71138531 Gerd Hoffmann
    uint8_t *pbuf;
839 060dc841 Hans de Goede
    uint8_t ep;
840 b9dc033c balrog
841 e6a2f500 Gerd Hoffmann
    trace_usb_host_req_data(s->bus_num, s->addr,
842 e6a2f500 Gerd Hoffmann
                            p->pid == USB_TOKEN_IN,
843 079d0b7f Gerd Hoffmann
                            p->ep->nr, p->iov.size);
844 e6a2f500 Gerd Hoffmann
845 079d0b7f Gerd Hoffmann
    if (!is_valid(s, p->pid, p->ep->nr)) {
846 e6a2f500 Gerd Hoffmann
        trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
847 a0b5fece Hans de Goede
        return USB_RET_NAK;
848 a0b5fece Hans de Goede
    }
849 a0b5fece Hans de Goede
850 2791104c David Ahern
    if (p->pid == USB_TOKEN_IN) {
851 079d0b7f Gerd Hoffmann
        ep = p->ep->nr | 0x80;
852 2791104c David Ahern
    } else {
853 079d0b7f Gerd Hoffmann
        ep = p->ep->nr;
854 2791104c David Ahern
    }
855 64838171 aliguori
856 079d0b7f Gerd Hoffmann
    if (is_halted(s, p->pid, p->ep->nr)) {
857 9b87e19b Gerd Hoffmann
        unsigned int arg = ep;
858 9b87e19b Gerd Hoffmann
        ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
859 64838171 aliguori
        if (ret < 0) {
860 e6a2f500 Gerd Hoffmann
            perror("USBDEVFS_CLEAR_HALT");
861 e6a2f500 Gerd Hoffmann
            trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
862 bb36d470 bellard
            return USB_RET_NAK;
863 bb36d470 bellard
        }
864 079d0b7f Gerd Hoffmann
        clear_halt(s, p->pid, p->ep->nr);
865 4d043a09 balrog
    }
866 4d043a09 balrog
867 079d0b7f Gerd Hoffmann
    if (is_isoc(s, p->pid, p->ep->nr)) {
868 bb6d5498 Hans de Goede
        return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
869 bb6d5498 Hans de Goede
    }
870 060dc841 Hans de Goede
871 b621bab4 Gerd Hoffmann
    v = 0;
872 b621bab4 Gerd Hoffmann
    prem = p->iov.iov[v].iov_len;
873 b621bab4 Gerd Hoffmann
    pbuf = p->iov.iov[v].iov_base;
874 b621bab4 Gerd Hoffmann
    rem = p->iov.size;
875 71138531 Gerd Hoffmann
    while (rem) {
876 b621bab4 Gerd Hoffmann
        if (prem == 0) {
877 b621bab4 Gerd Hoffmann
            v++;
878 b621bab4 Gerd Hoffmann
            assert(v < p->iov.niov);
879 b621bab4 Gerd Hoffmann
            prem = p->iov.iov[v].iov_len;
880 b621bab4 Gerd Hoffmann
            pbuf = p->iov.iov[v].iov_base;
881 b621bab4 Gerd Hoffmann
            assert(prem <= rem);
882 b621bab4 Gerd Hoffmann
        }
883 71138531 Gerd Hoffmann
        aurb = async_alloc(s);
884 71138531 Gerd Hoffmann
        aurb->packet = p;
885 71138531 Gerd Hoffmann
886 71138531 Gerd Hoffmann
        urb = &aurb->urb;
887 71138531 Gerd Hoffmann
        urb->endpoint      = ep;
888 d8e17efd Gerd Hoffmann
        urb->type          = usb_host_usbfs_type(s, p);
889 71138531 Gerd Hoffmann
        urb->usercontext   = s;
890 71138531 Gerd Hoffmann
        urb->buffer        = pbuf;
891 b621bab4 Gerd Hoffmann
        urb->buffer_length = prem;
892 71138531 Gerd Hoffmann
893 b621bab4 Gerd Hoffmann
        if (urb->buffer_length > MAX_USBFS_BUFFER_SIZE) {
894 71138531 Gerd Hoffmann
            urb->buffer_length = MAX_USBFS_BUFFER_SIZE;
895 71138531 Gerd Hoffmann
        }
896 71138531 Gerd Hoffmann
        pbuf += urb->buffer_length;
897 b621bab4 Gerd Hoffmann
        prem -= urb->buffer_length;
898 71138531 Gerd Hoffmann
        rem  -= urb->buffer_length;
899 b621bab4 Gerd Hoffmann
        if (rem) {
900 b621bab4 Gerd Hoffmann
            aurb->more         = 1;
901 b621bab4 Gerd Hoffmann
        }
902 b9dc033c balrog
903 e6a2f500 Gerd Hoffmann
        trace_usb_host_urb_submit(s->bus_num, s->addr, aurb,
904 e6a2f500 Gerd Hoffmann
                                  urb->buffer_length, aurb->more);
905 71138531 Gerd Hoffmann
        ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
906 b9dc033c balrog
907 71138531 Gerd Hoffmann
        DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n",
908 71138531 Gerd Hoffmann
                urb->endpoint, urb->buffer_length, aurb->more, p, aurb);
909 b9dc033c balrog
910 71138531 Gerd Hoffmann
        if (ret < 0) {
911 e6a2f500 Gerd Hoffmann
            perror("USBDEVFS_SUBMITURB");
912 71138531 Gerd Hoffmann
            async_free(aurb);
913 b9dc033c balrog
914 71138531 Gerd Hoffmann
            switch(errno) {
915 71138531 Gerd Hoffmann
            case ETIMEDOUT:
916 e6a2f500 Gerd Hoffmann
                trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
917 71138531 Gerd Hoffmann
                return USB_RET_NAK;
918 71138531 Gerd Hoffmann
            case EPIPE:
919 71138531 Gerd Hoffmann
            default:
920 e6a2f500 Gerd Hoffmann
                trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_STALL);
921 71138531 Gerd Hoffmann
                return USB_RET_STALL;
922 71138531 Gerd Hoffmann
            }
923 b9dc033c balrog
        }
924 b9dc033c balrog
    }
925 64838171 aliguori
926 b9dc033c balrog
    return USB_RET_ASYNC;
927 b9dc033c balrog
}
928 b9dc033c balrog
929 446ab128 aliguori
static int ctrl_error(void)
930 446ab128 aliguori
{
931 2791104c David Ahern
    if (errno == ETIMEDOUT) {
932 446ab128 aliguori
        return USB_RET_NAK;
933 2791104c David Ahern
    } else {
934 446ab128 aliguori
        return USB_RET_STALL;
935 2791104c David Ahern
    }
936 446ab128 aliguori
}
937 446ab128 aliguori
938 446ab128 aliguori
static int usb_host_set_address(USBHostDevice *s, int addr)
939 446ab128 aliguori
{
940 e6a2f500 Gerd Hoffmann
    trace_usb_host_set_address(s->bus_num, s->addr, addr);
941 446ab128 aliguori
    s->dev.addr = addr;
942 446ab128 aliguori
    return 0;
943 446ab128 aliguori
}
944 446ab128 aliguori
945 446ab128 aliguori
static int usb_host_set_config(USBHostDevice *s, int config)
946 446ab128 aliguori
{
947 0fcc3bfc Gerd Hoffmann
    int ret, first = 1;
948 0fcc3bfc Gerd Hoffmann
949 e6a2f500 Gerd Hoffmann
    trace_usb_host_set_config(s->bus_num, s->addr, config);
950 e6a2f500 Gerd Hoffmann
951 446ab128 aliguori
    usb_host_release_interfaces(s);
952 446ab128 aliguori
953 0fcc3bfc Gerd Hoffmann
again:
954 0fcc3bfc Gerd Hoffmann
    ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
955 2791104c David Ahern
956 d0f2c4c6 malc
    DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno);
957 2791104c David Ahern
958 0fcc3bfc Gerd Hoffmann
    if (ret < 0 && errno == EBUSY && first) {
959 0fcc3bfc Gerd Hoffmann
        /* happens if usb device is in use by host drivers */
960 0fcc3bfc Gerd Hoffmann
        int count = usb_linux_get_num_interfaces(s);
961 0fcc3bfc Gerd Hoffmann
        if (count > 0) {
962 0fcc3bfc Gerd Hoffmann
            DPRINTF("husb: busy -> disconnecting %d interfaces\n", count);
963 0fcc3bfc Gerd Hoffmann
            usb_host_disconnect_ifaces(s, count);
964 0fcc3bfc Gerd Hoffmann
            first = 0;
965 0fcc3bfc Gerd Hoffmann
            goto again;
966 0fcc3bfc Gerd Hoffmann
        }
967 0fcc3bfc Gerd Hoffmann
    }
968 0fcc3bfc Gerd Hoffmann
969 2791104c David Ahern
    if (ret < 0) {
970 446ab128 aliguori
        return ctrl_error();
971 2791104c David Ahern
    }
972 446ab128 aliguori
    usb_host_claim_interfaces(s, config);
973 eb7700bb Gerd Hoffmann
    usb_linux_update_endp_table(s);
974 446ab128 aliguori
    return 0;
975 446ab128 aliguori
}
976 446ab128 aliguori
977 446ab128 aliguori
static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
978 446ab128 aliguori
{
979 446ab128 aliguori
    struct usbdevfs_setinterface si;
980 060dc841 Hans de Goede
    int i, ret;
981 060dc841 Hans de Goede
982 e6a2f500 Gerd Hoffmann
    trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt);
983 e6a2f500 Gerd Hoffmann
984 d8e17efd Gerd Hoffmann
    for (i = 1; i <= USB_MAX_ENDPOINTS; i++) {
985 c0e5750b Gerd Hoffmann
        if (is_isoc(s, USB_TOKEN_IN, i)) {
986 c0e5750b Gerd Hoffmann
            usb_host_stop_n_free_iso(s, USB_TOKEN_IN, i);
987 c0e5750b Gerd Hoffmann
        }
988 c0e5750b Gerd Hoffmann
        if (is_isoc(s, USB_TOKEN_OUT, i)) {
989 c0e5750b Gerd Hoffmann
            usb_host_stop_n_free_iso(s, USB_TOKEN_OUT, i);
990 060dc841 Hans de Goede
        }
991 060dc841 Hans de Goede
    }
992 446ab128 aliguori
993 1de14d43 Gerd Hoffmann
    if (iface >= USB_MAX_INTERFACES) {
994 1de14d43 Gerd Hoffmann
        return USB_RET_STALL;
995 1de14d43 Gerd Hoffmann
    }
996 1de14d43 Gerd Hoffmann
997 446ab128 aliguori
    si.interface  = iface;
998 446ab128 aliguori
    si.altsetting = alt;
999 446ab128 aliguori
    ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
1000 446ab128 aliguori
1001 2791104c David Ahern
    DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
1002 2791104c David Ahern
            iface, alt, ret, errno);
1003 2791104c David Ahern
1004 2791104c David Ahern
    if (ret < 0) {
1005 2791104c David Ahern
        return ctrl_error();
1006 2791104c David Ahern
    }
1007 1de14d43 Gerd Hoffmann
1008 1de14d43 Gerd Hoffmann
    s->dev.altsetting[iface] = alt;
1009 446ab128 aliguori
    usb_linux_update_endp_table(s);
1010 446ab128 aliguori
    return 0;
1011 446ab128 aliguori
}
1012 446ab128 aliguori
1013 50b7963e Hans de Goede
static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
1014 50b7963e Hans de Goede
               int request, int value, int index, int length, uint8_t *data)
1015 446ab128 aliguori
{
1016 50b7963e Hans de Goede
    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
1017 446ab128 aliguori
    struct usbdevfs_urb *urb;
1018 446ab128 aliguori
    AsyncURB *aurb;
1019 50b7963e Hans de Goede
    int ret;
1020 446ab128 aliguori
1021 2791104c David Ahern
    /*
1022 446ab128 aliguori
     * Process certain standard device requests.
1023 446ab128 aliguori
     * These are infrequent and are processed synchronously.
1024 446ab128 aliguori
     */
1025 446ab128 aliguori
1026 50b7963e Hans de Goede
    /* Note request is (bRequestType << 8) | bRequest */
1027 e6a2f500 Gerd Hoffmann
    trace_usb_host_req_control(s->bus_num, s->addr, request, value, index);
1028 446ab128 aliguori
1029 50b7963e Hans de Goede
    switch (request) {
1030 50b7963e Hans de Goede
    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
1031 50b7963e Hans de Goede
        return usb_host_set_address(s, value);
1032 446ab128 aliguori
1033 50b7963e Hans de Goede
    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
1034 50b7963e Hans de Goede
        return usb_host_set_config(s, value & 0xff);
1035 446ab128 aliguori
1036 50b7963e Hans de Goede
    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
1037 446ab128 aliguori
        return usb_host_set_interface(s, index, value);
1038 2791104c David Ahern
    }
1039 446ab128 aliguori
1040 446ab128 aliguori
    /* The rest are asynchronous */
1041 446ab128 aliguori
1042 50b7963e Hans de Goede
    if (length > sizeof(dev->data_buf)) {
1043 50b7963e Hans de Goede
        fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n",
1044 50b7963e Hans de Goede
                length, sizeof(dev->data_buf));
1045 b2e3b6e9 malc
        return USB_RET_STALL;
1046 c4c0e236 Jim Paris
    }
1047 c4c0e236 Jim Paris
1048 7a8fc83f Gerd Hoffmann
    aurb = async_alloc(s);
1049 446ab128 aliguori
    aurb->packet = p;
1050 446ab128 aliguori
1051 2791104c David Ahern
    /*
1052 446ab128 aliguori
     * Setup ctrl transfer.
1053 446ab128 aliguori
     *
1054 a0102082 Brad Hards
     * s->ctrl is laid out such that data buffer immediately follows
1055 446ab128 aliguori
     * 'req' struct which is exactly what usbdevfs expects.
1056 2791104c David Ahern
     */
1057 446ab128 aliguori
    urb = &aurb->urb;
1058 446ab128 aliguori
1059 446ab128 aliguori
    urb->type     = USBDEVFS_URB_TYPE_CONTROL;
1060 079d0b7f Gerd Hoffmann
    urb->endpoint = p->ep->nr;
1061 446ab128 aliguori
1062 50b7963e Hans de Goede
    urb->buffer        = &dev->setup_buf;
1063 50b7963e Hans de Goede
    urb->buffer_length = length + 8;
1064 446ab128 aliguori
1065 446ab128 aliguori
    urb->usercontext = s;
1066 446ab128 aliguori
1067 e6a2f500 Gerd Hoffmann
    trace_usb_host_urb_submit(s->bus_num, s->addr, aurb,
1068 e6a2f500 Gerd Hoffmann
                              urb->buffer_length, aurb->more);
1069 446ab128 aliguori
    ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
1070 446ab128 aliguori
1071 d0f2c4c6 malc
    DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb->buffer_length, aurb);
1072 446ab128 aliguori
1073 446ab128 aliguori
    if (ret < 0) {
1074 d0f2c4c6 malc
        DPRINTF("husb: submit failed. errno %d\n", errno);
1075 446ab128 aliguori
        async_free(aurb);
1076 446ab128 aliguori
1077 446ab128 aliguori
        switch(errno) {
1078 446ab128 aliguori
        case ETIMEDOUT:
1079 446ab128 aliguori
            return USB_RET_NAK;
1080 446ab128 aliguori
        case EPIPE:
1081 446ab128 aliguori
        default:
1082 446ab128 aliguori
            return USB_RET_STALL;
1083 446ab128 aliguori
        }
1084 446ab128 aliguori
    }
1085 446ab128 aliguori
1086 446ab128 aliguori
    return USB_RET_ASYNC;
1087 446ab128 aliguori
}
1088 446ab128 aliguori
1089 ed3a328d Hans de Goede
static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
1090 ed3a328d Hans de Goede
    uint8_t configuration, uint8_t interface)
1091 ed3a328d Hans de Goede
{
1092 097db438 Gerd Hoffmann
    char device_name[64], line[1024];
1093 097db438 Gerd Hoffmann
    int alt_setting;
1094 c43831fb Hans de Goede
1095 097db438 Gerd Hoffmann
    sprintf(device_name, "%d-%s:%d.%d", s->bus_num, s->port,
1096 097db438 Gerd Hoffmann
            (int)configuration, (int)interface);
1097 c43831fb Hans de Goede
1098 097db438 Gerd Hoffmann
    if (!usb_host_read_file(line, sizeof(line), "bAlternateSetting",
1099 097db438 Gerd Hoffmann
                            device_name)) {
1100 097db438 Gerd Hoffmann
        /* Assume alt 0 on error */
1101 097db438 Gerd Hoffmann
        return 0;
1102 097db438 Gerd Hoffmann
    }
1103 097db438 Gerd Hoffmann
    if (sscanf(line, "%d", &alt_setting) != 1) {
1104 ed3a328d Hans de Goede
        /* Assume alt 0 on error */
1105 ed3a328d Hans de Goede
        return 0;
1106 ed3a328d Hans de Goede
    }
1107 ed3a328d Hans de Goede
    return alt_setting;
1108 ed3a328d Hans de Goede
}
1109 ed3a328d Hans de Goede
1110 71d71bbd Hans de Goede
/* returns 1 on problem encountered or 0 for success */
1111 71d71bbd Hans de Goede
static int usb_linux_update_endp_table(USBHostDevice *s)
1112 71d71bbd Hans de Goede
{
1113 71d71bbd Hans de Goede
    uint8_t *descriptors;
1114 eb7700bb Gerd Hoffmann
    uint8_t devep, type, alt_interface;
1115 f003397c Gerd Hoffmann
    uint16_t raw;
1116 c0e5750b Gerd Hoffmann
    int interface, length, i, ep, pid;
1117 c0e5750b Gerd Hoffmann
    struct endp_data *epd;
1118 71d71bbd Hans de Goede
1119 d8e17efd Gerd Hoffmann
    usb_ep_init(&s->dev);
1120 a0b5fece Hans de Goede
1121 65360511 Gerd Hoffmann
    if (s->dev.configuration == 0) {
1122 eb7700bb Gerd Hoffmann
        /* not configured yet -- leave all endpoints disabled */
1123 eb7700bb Gerd Hoffmann
        return 0;
1124 eb7700bb Gerd Hoffmann
    }
1125 71d71bbd Hans de Goede
1126 b9dc033c balrog
    /* get the desired configuration, interface, and endpoint descriptors
1127 b9dc033c balrog
     * from device description */
1128 b9dc033c balrog
    descriptors = &s->descr[18];
1129 b9dc033c balrog
    length = s->descr_len - 18;
1130 b9dc033c balrog
    i = 0;
1131 b9dc033c balrog
1132 b9dc033c balrog
    while (i < length) {
1133 7279a85f Cao,Bing Bu
        if (descriptors[i + 1] != USB_DT_CONFIG) {
1134 7279a85f Cao,Bing Bu
            fprintf(stderr, "invalid descriptor data\n");
1135 7279a85f Cao,Bing Bu
            return 1;
1136 65360511 Gerd Hoffmann
        } else if (descriptors[i + 5] != s->dev.configuration) {
1137 65360511 Gerd Hoffmann
            DPRINTF("not requested configuration %d\n", s->dev.configuration);
1138 7279a85f Cao,Bing Bu
            i += (descriptors[i + 3] << 8) + descriptors[i + 2];
1139 7279a85f Cao,Bing Bu
            continue;
1140 7279a85f Cao,Bing Bu
        }
1141 7279a85f Cao,Bing Bu
        i += descriptors[i];
1142 7279a85f Cao,Bing Bu
1143 b9dc033c balrog
        if (descriptors[i + 1] != USB_DT_INTERFACE ||
1144 b9dc033c balrog
            (descriptors[i + 1] == USB_DT_INTERFACE &&
1145 b9dc033c balrog
             descriptors[i + 4] == 0)) {
1146 b9dc033c balrog
            i += descriptors[i];
1147 b9dc033c balrog
            continue;
1148 b9dc033c balrog
        }
1149 b9dc033c balrog
1150 b9dc033c balrog
        interface = descriptors[i + 2];
1151 65360511 Gerd Hoffmann
        alt_interface = usb_linux_get_alt_setting(s, s->dev.configuration,
1152 eb7700bb Gerd Hoffmann
                                                  interface);
1153 b9dc033c balrog
1154 b9dc033c balrog
        /* the current interface descriptor is the active interface
1155 b9dc033c balrog
         * and has endpoints */
1156 b9dc033c balrog
        if (descriptors[i + 3] != alt_interface) {
1157 b9dc033c balrog
            i += descriptors[i];
1158 b9dc033c balrog
            continue;
1159 b9dc033c balrog
        }
1160 b9dc033c balrog
1161 b9dc033c balrog
        /* advance to the endpoints */
1162 2791104c David Ahern
        while (i < length && descriptors[i +1] != USB_DT_ENDPOINT) {
1163 b9dc033c balrog
            i += descriptors[i];
1164 2791104c David Ahern
        }
1165 b9dc033c balrog
1166 b9dc033c balrog
        if (i >= length)
1167 b9dc033c balrog
            break;
1168 b9dc033c balrog
1169 b9dc033c balrog
        while (i < length) {
1170 2791104c David Ahern
            if (descriptors[i + 1] != USB_DT_ENDPOINT) {
1171 b9dc033c balrog
                break;
1172 2791104c David Ahern
            }
1173 b9dc033c balrog
1174 b9dc033c balrog
            devep = descriptors[i + 2];
1175 c0e5750b Gerd Hoffmann
            pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT;
1176 c0e5750b Gerd Hoffmann
            ep = devep & 0xf;
1177 c0e5750b Gerd Hoffmann
            if (ep == 0) {
1178 130314f8 Hans de Goede
                fprintf(stderr, "usb-linux: invalid ep descriptor, ep == 0\n");
1179 130314f8 Hans de Goede
                return 1;
1180 130314f8 Hans de Goede
            }
1181 130314f8 Hans de Goede
1182 d8e17efd Gerd Hoffmann
            type = descriptors[i + 3] & 0x3;
1183 f003397c Gerd Hoffmann
            raw = descriptors[i + 4] + (descriptors[i + 5] << 8);
1184 f003397c Gerd Hoffmann
            usb_ep_set_max_packet_size(&s->dev, pid, ep, raw);
1185 d8e17efd Gerd Hoffmann
            assert(usb_ep_get_type(&s->dev, pid, ep) ==
1186 d8e17efd Gerd Hoffmann
                   USB_ENDPOINT_XFER_INVALID);
1187 d8e17efd Gerd Hoffmann
            usb_ep_set_type(&s->dev, pid, ep, type);
1188 82f02fe9 Gerd Hoffmann
            usb_ep_set_ifnum(&s->dev, pid, ep, interface);
1189 d8e17efd Gerd Hoffmann
1190 c0e5750b Gerd Hoffmann
            epd = get_endp(s, pid, ep);
1191 c0e5750b Gerd Hoffmann
            epd->halted = 0;
1192 b9dc033c balrog
1193 b9dc033c balrog
            i += descriptors[i];
1194 b9dc033c balrog
        }
1195 b9dc033c balrog
    }
1196 5b6780d0 Gerd Hoffmann
#ifdef DEBUG
1197 5b6780d0 Gerd Hoffmann
    usb_ep_dump(&s->dev);
1198 5b6780d0 Gerd Hoffmann
#endif
1199 b9dc033c balrog
    return 0;
1200 b9dc033c balrog
}
1201 b9dc033c balrog
1202 e4b17767 Hans de Goede
/*
1203 e4b17767 Hans de Goede
 * Check if we can safely redirect a usb2 device to a usb1 virtual controller,
1204 e4b17767 Hans de Goede
 * this function assumes this is safe, if:
1205 e4b17767 Hans de Goede
 * 1) There are no isoc endpoints
1206 e4b17767 Hans de Goede
 * 2) There are no interrupt endpoints with a max_packet_size > 64
1207 e4b17767 Hans de Goede
 * Note bulk endpoints with a max_packet_size > 64 in theory also are not
1208 e4b17767 Hans de Goede
 * usb1 compatible, but in practice this seems to work fine.
1209 e4b17767 Hans de Goede
 */
1210 e4b17767 Hans de Goede
static int usb_linux_full_speed_compat(USBHostDevice *dev)
1211 e4b17767 Hans de Goede
{
1212 e4b17767 Hans de Goede
    int i, packet_size;
1213 e4b17767 Hans de Goede
1214 e4b17767 Hans de Goede
    /*
1215 e4b17767 Hans de Goede
     * usb_linux_update_endp_table only registers info about ep in the current
1216 e4b17767 Hans de Goede
     * interface altsettings, so we need to parse the descriptors again.
1217 e4b17767 Hans de Goede
     */
1218 e4b17767 Hans de Goede
    for (i = 0; (i + 5) < dev->descr_len; i += dev->descr[i]) {
1219 e4b17767 Hans de Goede
        if (dev->descr[i + 1] == USB_DT_ENDPOINT) {
1220 e4b17767 Hans de Goede
            switch (dev->descr[i + 3] & 0x3) {
1221 e4b17767 Hans de Goede
            case 0x00: /* CONTROL */
1222 e4b17767 Hans de Goede
                break;
1223 e4b17767 Hans de Goede
            case 0x01: /* ISO */
1224 e4b17767 Hans de Goede
                return 0;
1225 e4b17767 Hans de Goede
            case 0x02: /* BULK */
1226 e4b17767 Hans de Goede
                break;
1227 e4b17767 Hans de Goede
            case 0x03: /* INTERRUPT */
1228 e4b17767 Hans de Goede
                packet_size = dev->descr[i + 4] + (dev->descr[i + 5] << 8);
1229 e4b17767 Hans de Goede
                if (packet_size > 64)
1230 e4b17767 Hans de Goede
                    return 0;
1231 e4b17767 Hans de Goede
                break;
1232 e4b17767 Hans de Goede
            }
1233 e4b17767 Hans de Goede
        }
1234 e4b17767 Hans de Goede
    }
1235 e4b17767 Hans de Goede
    return 1;
1236 e4b17767 Hans de Goede
}
1237 e4b17767 Hans de Goede
1238 26a9e82a Gerd Hoffmann
static int usb_host_open(USBHostDevice *dev, int bus_num,
1239 ba9acab9 Gerd Hoffmann
                         int addr, const char *port,
1240 ba9acab9 Gerd Hoffmann
                         const char *prod_name, int speed)
1241 bb36d470 bellard
{
1242 b9dc033c balrog
    int fd = -1, ret;
1243 1f3870ab aliguori
1244 e6a2f500 Gerd Hoffmann
    trace_usb_host_open_started(bus_num, addr);
1245 e6a2f500 Gerd Hoffmann
1246 2791104c David Ahern
    if (dev->fd != -1) {
1247 26a9e82a Gerd Hoffmann
        goto fail;
1248 2791104c David Ahern
    }
1249 3b46e624 ths
1250 097db438 Gerd Hoffmann
    fd = usb_host_open_device(bus_num, addr);
1251 bb36d470 bellard
    if (fd < 0) {
1252 1f3870ab aliguori
        goto fail;
1253 bb36d470 bellard
    }
1254 d0f2c4c6 malc
    DPRINTF("husb: opened %s\n", buf);
1255 bb36d470 bellard
1256 806b6024 Gerd Hoffmann
    dev->bus_num = bus_num;
1257 806b6024 Gerd Hoffmann
    dev->addr = addr;
1258 5557d820 Gerd Hoffmann
    strcpy(dev->port, port);
1259 22f84e73 Gerd Hoffmann
    dev->fd = fd;
1260 806b6024 Gerd Hoffmann
1261 b9dc033c balrog
    /* read the device description */
1262 b9dc033c balrog
    dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
1263 b9dc033c balrog
    if (dev->descr_len <= 0) {
1264 64838171 aliguori
        perror("husb: reading device data failed");
1265 bb36d470 bellard
        goto fail;
1266 bb36d470 bellard
    }
1267 3b46e624 ths
1268 b9dc033c balrog
#ifdef DEBUG
1269 868bfe2b bellard
    {
1270 b9dc033c balrog
        int x;
1271 b9dc033c balrog
        printf("=== begin dumping device descriptor data ===\n");
1272 2791104c David Ahern
        for (x = 0; x < dev->descr_len; x++) {
1273 b9dc033c balrog
            printf("%02x ", dev->descr[x]);
1274 2791104c David Ahern
        }
1275 b9dc033c balrog
        printf("\n=== end dumping device descriptor data ===\n");
1276 bb36d470 bellard
    }
1277 a594cfbf bellard
#endif
1278 a594cfbf bellard
1279 b9dc033c balrog
1280 eb7700bb Gerd Hoffmann
    /* start unconfigured -- we'll wait for the guest to set a configuration */
1281 eb7700bb Gerd Hoffmann
    if (!usb_host_claim_interfaces(dev, 0)) {
1282 b9dc033c balrog
        goto fail;
1283 2791104c David Ahern
    }
1284 bb36d470 bellard
1285 b9dc033c balrog
    ret = usb_linux_update_endp_table(dev);
1286 2791104c David Ahern
    if (ret) {
1287 bb36d470 bellard
        goto fail;
1288 2791104c David Ahern
    }
1289 b9dc033c balrog
1290 3991c35e Hans de Goede
    if (speed == -1) {
1291 3991c35e Hans de Goede
        struct usbdevfs_connectinfo ci;
1292 3991c35e Hans de Goede
1293 3991c35e Hans de Goede
        ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
1294 3991c35e Hans de Goede
        if (ret < 0) {
1295 3991c35e Hans de Goede
            perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
1296 3991c35e Hans de Goede
            goto fail;
1297 3991c35e Hans de Goede
        }
1298 3991c35e Hans de Goede
1299 3991c35e Hans de Goede
        if (ci.slow) {
1300 3991c35e Hans de Goede
            speed = USB_SPEED_LOW;
1301 3991c35e Hans de Goede
        } else {
1302 3991c35e Hans de Goede
            speed = USB_SPEED_HIGH;
1303 3991c35e Hans de Goede
        }
1304 2791104c David Ahern
    }
1305 3991c35e Hans de Goede
    dev->dev.speed = speed;
1306 ba3f9bfb Hans de Goede
    dev->dev.speedmask = (1 << speed);
1307 e4b17767 Hans de Goede
    if (dev->dev.speed == USB_SPEED_HIGH && usb_linux_full_speed_compat(dev)) {
1308 e4b17767 Hans de Goede
        dev->dev.speedmask |= USB_SPEED_MASK_FULL;
1309 e4b17767 Hans de Goede
    }
1310 3991c35e Hans de Goede
1311 e6a2f500 Gerd Hoffmann
    trace_usb_host_open_success(bus_num, addr);
1312 bb36d470 bellard
1313 2791104c David Ahern
    if (!prod_name || prod_name[0] == '\0') {
1314 0fe6d12e Markus Armbruster
        snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
1315 4b096fc9 aliguori
                 "host:%d.%d", bus_num, addr);
1316 2791104c David Ahern
    } else {
1317 0fe6d12e Markus Armbruster
        pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
1318 4b096fc9 aliguori
                prod_name);
1319 2791104c David Ahern
    }
1320 1f6e24e7 bellard
1321 fa19bf83 Hans de Goede
    ret = usb_device_attach(&dev->dev);
1322 fa19bf83 Hans de Goede
    if (ret) {
1323 fa19bf83 Hans de Goede
        goto fail;
1324 fa19bf83 Hans de Goede
    }
1325 fa19bf83 Hans de Goede
1326 64838171 aliguori
    /* USB devio uses 'write' flag to check for async completions */
1327 64838171 aliguori
    qemu_set_fd_handler(dev->fd, NULL, async_complete, dev);
1328 1f3870ab aliguori
1329 26a9e82a Gerd Hoffmann
    return 0;
1330 4b096fc9 aliguori
1331 b9dc033c balrog
fail:
1332 e6a2f500 Gerd Hoffmann
    trace_usb_host_open_failure(bus_num, addr);
1333 1f45a81b Gerd Hoffmann
    if (dev->fd != -1) {
1334 1f45a81b Gerd Hoffmann
        close(dev->fd);
1335 1f45a81b Gerd Hoffmann
        dev->fd = -1;
1336 2791104c David Ahern
    }
1337 26a9e82a Gerd Hoffmann
    return -1;
1338 26a9e82a Gerd Hoffmann
}
1339 26a9e82a Gerd Hoffmann
1340 26a9e82a Gerd Hoffmann
static int usb_host_close(USBHostDevice *dev)
1341 26a9e82a Gerd Hoffmann
{
1342 060dc841 Hans de Goede
    int i;
1343 060dc841 Hans de Goede
1344 39fba3ad Gerd Hoffmann
    if (dev->fd == -1) {
1345 26a9e82a Gerd Hoffmann
        return -1;
1346 2791104c David Ahern
    }
1347 26a9e82a Gerd Hoffmann
1348 e6a2f500 Gerd Hoffmann
    trace_usb_host_close(dev->bus_num, dev->addr);
1349 e6a2f500 Gerd Hoffmann
1350 26a9e82a Gerd Hoffmann
    qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
1351 26a9e82a Gerd Hoffmann
    dev->closing = 1;
1352 d8e17efd Gerd Hoffmann
    for (i = 1; i <= USB_MAX_ENDPOINTS; i++) {
1353 c0e5750b Gerd Hoffmann
        if (is_isoc(dev, USB_TOKEN_IN, i)) {
1354 c0e5750b Gerd Hoffmann
            usb_host_stop_n_free_iso(dev, USB_TOKEN_IN, i);
1355 c0e5750b Gerd Hoffmann
        }
1356 c0e5750b Gerd Hoffmann
        if (is_isoc(dev, USB_TOKEN_OUT, i)) {
1357 c0e5750b Gerd Hoffmann
            usb_host_stop_n_free_iso(dev, USB_TOKEN_OUT, i);
1358 060dc841 Hans de Goede
        }
1359 060dc841 Hans de Goede
    }
1360 26a9e82a Gerd Hoffmann
    async_complete(dev);
1361 26a9e82a Gerd Hoffmann
    dev->closing = 0;
1362 39fba3ad Gerd Hoffmann
    if (dev->dev.attached) {
1363 39fba3ad Gerd Hoffmann
        usb_device_detach(&dev->dev);
1364 39fba3ad Gerd Hoffmann
    }
1365 c7662daa Gerd Hoffmann
    usb_host_do_reset(dev);
1366 26a9e82a Gerd Hoffmann
    close(dev->fd);
1367 26a9e82a Gerd Hoffmann
    dev->fd = -1;
1368 26a9e82a Gerd Hoffmann
    return 0;
1369 26a9e82a Gerd Hoffmann
}
1370 26a9e82a Gerd Hoffmann
1371 9e8dd451 Jan Kiszka
static void usb_host_exit_notifier(struct Notifier *n, void *data)
1372 b373a63a Shahar Havivi
{
1373 b373a63a Shahar Havivi
    USBHostDevice *s = container_of(n, USBHostDevice, exit);
1374 b373a63a Shahar Havivi
1375 c75fead6 Gerd Hoffmann
    usb_host_release_port(s);
1376 b373a63a Shahar Havivi
    if (s->fd != -1) {
1377 c7662daa Gerd Hoffmann
        usb_host_do_reset(s);;
1378 b373a63a Shahar Havivi
    }
1379 b373a63a Shahar Havivi
}
1380 b373a63a Shahar Havivi
1381 26a9e82a Gerd Hoffmann
static int usb_host_initfn(USBDevice *dev)
1382 26a9e82a Gerd Hoffmann
{
1383 26a9e82a Gerd Hoffmann
    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
1384 26a9e82a Gerd Hoffmann
1385 26a9e82a Gerd Hoffmann
    dev->auto_attach = 0;
1386 26a9e82a Gerd Hoffmann
    s->fd = -1;
1387 9516bb47 Gerd Hoffmann
    s->hub_fd = -1;
1388 9516bb47 Gerd Hoffmann
1389 26a9e82a Gerd Hoffmann
    QTAILQ_INSERT_TAIL(&hostdevs, s, next);
1390 b373a63a Shahar Havivi
    s->exit.notify = usb_host_exit_notifier;
1391 b373a63a Shahar Havivi
    qemu_add_exit_notifier(&s->exit);
1392 26a9e82a Gerd Hoffmann
    usb_host_auto_check(NULL);
1393 9516bb47 Gerd Hoffmann
1394 9516bb47 Gerd Hoffmann
    if (s->match.bus_num != 0 && s->match.port != NULL) {
1395 e6274727 Gerd Hoffmann
        usb_host_claim_port(s);
1396 9516bb47 Gerd Hoffmann
    }
1397 26a9e82a Gerd Hoffmann
    return 0;
1398 a594cfbf bellard
}
1399 bb36d470 bellard
1400 d6791578 Gerd Hoffmann
static const VMStateDescription vmstate_usb_host = {
1401 d6791578 Gerd Hoffmann
    .name = "usb-host",
1402 d6791578 Gerd Hoffmann
    .unmigratable = 1,
1403 d6791578 Gerd Hoffmann
};
1404 d6791578 Gerd Hoffmann
1405 39bffca2 Anthony Liguori
static Property usb_host_dev_properties[] = {
1406 39bffca2 Anthony Liguori
    DEFINE_PROP_UINT32("hostbus",  USBHostDevice, match.bus_num,    0),
1407 39bffca2 Anthony Liguori
    DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr,       0),
1408 39bffca2 Anthony Liguori
    DEFINE_PROP_STRING("hostport", USBHostDevice, match.port),
1409 39bffca2 Anthony Liguori
    DEFINE_PROP_HEX32("vendorid",  USBHostDevice, match.vendor_id,  0),
1410 39bffca2 Anthony Liguori
    DEFINE_PROP_HEX32("productid", USBHostDevice, match.product_id, 0),
1411 39bffca2 Anthony Liguori
    DEFINE_PROP_UINT32("isobufs",  USBHostDevice, iso_urb_count,    4),
1412 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
1413 39bffca2 Anthony Liguori
};
1414 39bffca2 Anthony Liguori
1415 62aed765 Anthony Liguori
static void usb_host_class_initfn(ObjectClass *klass, void *data)
1416 62aed765 Anthony Liguori
{
1417 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
1418 62aed765 Anthony Liguori
    USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
1419 62aed765 Anthony Liguori
1420 62aed765 Anthony Liguori
    uc->init           = usb_host_initfn;
1421 62aed765 Anthony Liguori
    uc->product_desc   = "USB Host Device";
1422 62aed765 Anthony Liguori
    uc->cancel_packet  = usb_host_async_cancel;
1423 62aed765 Anthony Liguori
    uc->handle_data    = usb_host_handle_data;
1424 62aed765 Anthony Liguori
    uc->handle_control = usb_host_handle_control;
1425 62aed765 Anthony Liguori
    uc->handle_reset   = usb_host_handle_reset;
1426 62aed765 Anthony Liguori
    uc->handle_destroy = usb_host_handle_destroy;
1427 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_usb_host;
1428 39bffca2 Anthony Liguori
    dc->props = usb_host_dev_properties;
1429 62aed765 Anthony Liguori
}
1430 62aed765 Anthony Liguori
1431 39bffca2 Anthony Liguori
static TypeInfo usb_host_dev_info = {
1432 39bffca2 Anthony Liguori
    .name          = "usb-host",
1433 39bffca2 Anthony Liguori
    .parent        = TYPE_USB_DEVICE,
1434 39bffca2 Anthony Liguori
    .instance_size = sizeof(USBHostDevice),
1435 39bffca2 Anthony Liguori
    .class_init    = usb_host_class_initfn,
1436 806b6024 Gerd Hoffmann
};
1437 806b6024 Gerd Hoffmann
1438 806b6024 Gerd Hoffmann
static void usb_host_register_devices(void)
1439 806b6024 Gerd Hoffmann
{
1440 39bffca2 Anthony Liguori
    type_register_static(&usb_host_dev_info);
1441 ba02430f Anthony Liguori
    usb_legacy_register("usb-host", "host", usb_host_device_open);
1442 806b6024 Gerd Hoffmann
}
1443 806b6024 Gerd Hoffmann
device_init(usb_host_register_devices)
1444 806b6024 Gerd Hoffmann
1445 4b096fc9 aliguori
USBDevice *usb_host_device_open(const char *devname)
1446 4b096fc9 aliguori
{
1447 0745eb1e Markus Armbruster
    struct USBAutoFilter filter;
1448 26a9e82a Gerd Hoffmann
    USBDevice *dev;
1449 26a9e82a Gerd Hoffmann
    char *p;
1450 26a9e82a Gerd Hoffmann
1451 556cd098 Markus Armbruster
    dev = usb_create(NULL /* FIXME */, "usb-host");
1452 4b096fc9 aliguori
1453 5d0c5750 aliguori
    if (strstr(devname, "auto:")) {
1454 2791104c David Ahern
        if (parse_filter(devname, &filter) < 0) {
1455 26a9e82a Gerd Hoffmann
            goto fail;
1456 2791104c David Ahern
        }
1457 26a9e82a Gerd Hoffmann
    } else {
1458 26a9e82a Gerd Hoffmann
        if ((p = strchr(devname, '.'))) {
1459 0745eb1e Markus Armbruster
            filter.bus_num    = strtoul(devname, NULL, 0);
1460 0745eb1e Markus Armbruster
            filter.addr       = strtoul(p + 1, NULL, 0);
1461 0745eb1e Markus Armbruster
            filter.vendor_id  = 0;
1462 0745eb1e Markus Armbruster
            filter.product_id = 0;
1463 26a9e82a Gerd Hoffmann
        } else if ((p = strchr(devname, ':'))) {
1464 0745eb1e Markus Armbruster
            filter.bus_num    = 0;
1465 0745eb1e Markus Armbruster
            filter.addr       = 0;
1466 26a9e82a Gerd Hoffmann
            filter.vendor_id  = strtoul(devname, NULL, 16);
1467 0745eb1e Markus Armbruster
            filter.product_id = strtoul(p + 1, NULL, 16);
1468 26a9e82a Gerd Hoffmann
        } else {
1469 26a9e82a Gerd Hoffmann
            goto fail;
1470 26a9e82a Gerd Hoffmann
        }
1471 5d0c5750 aliguori
    }
1472 4b096fc9 aliguori
1473 0745eb1e Markus Armbruster
    qdev_prop_set_uint32(&dev->qdev, "hostbus",   filter.bus_num);
1474 0745eb1e Markus Armbruster
    qdev_prop_set_uint32(&dev->qdev, "hostaddr",  filter.addr);
1475 26a9e82a Gerd Hoffmann
    qdev_prop_set_uint32(&dev->qdev, "vendorid",  filter.vendor_id);
1476 26a9e82a Gerd Hoffmann
    qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id);
1477 beb6f0de Kevin Wolf
    qdev_init_nofail(&dev->qdev);
1478 26a9e82a Gerd Hoffmann
    return dev;
1479 5d0c5750 aliguori
1480 26a9e82a Gerd Hoffmann
fail:
1481 26a9e82a Gerd Hoffmann
    qdev_free(&dev->qdev);
1482 26a9e82a Gerd Hoffmann
    return NULL;
1483 4b096fc9 aliguori
}
1484 5d0c5750 aliguori
1485 5d0c5750 aliguori
int usb_host_device_close(const char *devname)
1486 5d0c5750 aliguori
{
1487 26a9e82a Gerd Hoffmann
#if 0
1488 5d0c5750 aliguori
    char product_name[PRODUCT_NAME_SZ];
1489 5d0c5750 aliguori
    int bus_num, addr;
1490 5d0c5750 aliguori
    USBHostDevice *s;
1491 5d0c5750 aliguori

1492 2791104c David Ahern
    if (strstr(devname, "auto:")) {
1493 5d0c5750 aliguori
        return usb_host_auto_del(devname);
1494 2791104c David Ahern
    }
1495 2791104c David Ahern
    if (usb_host_find_device(&bus_num, &addr, product_name,
1496 2791104c David Ahern
                                    sizeof(product_name), devname) < 0) {
1497 5d0c5750 aliguori
        return -1;
1498 2791104c David Ahern
    }
1499 5d0c5750 aliguori
    s = hostdev_find(bus_num, addr);
1500 5d0c5750 aliguori
    if (s) {
1501 a5d2f727 Gerd Hoffmann
        usb_device_delete_addr(s->bus_num, s->dev.addr);
1502 5d0c5750 aliguori
        return 0;
1503 5d0c5750 aliguori
    }
1504 26a9e82a Gerd Hoffmann
#endif
1505 5d0c5750 aliguori
1506 5d0c5750 aliguori
    return -1;
1507 5d0c5750 aliguori
}
1508 a5d2f727 Gerd Hoffmann
1509 0f431527 aliguori
/*
1510 0f431527 aliguori
 * Read sys file-system device file
1511 0f431527 aliguori
 *
1512 0f431527 aliguori
 * @line address of buffer to put file contents in
1513 0f431527 aliguori
 * @line_size size of line
1514 0f431527 aliguori
 * @device_file path to device file (printf format string)
1515 0f431527 aliguori
 * @device_name device being opened (inserted into device_file)
1516 0f431527 aliguori
 *
1517 0f431527 aliguori
 * @return 0 failed, 1 succeeded ('line' contains data)
1518 0f431527 aliguori
 */
1519 2791104c David Ahern
static int usb_host_read_file(char *line, size_t line_size,
1520 2791104c David Ahern
                              const char *device_file, const char *device_name)
1521 0f431527 aliguori
{
1522 0f431527 aliguori
    FILE *f;
1523 0f431527 aliguori
    int ret = 0;
1524 0f431527 aliguori
    char filename[PATH_MAX];
1525 0f431527 aliguori
1526 097db438 Gerd Hoffmann
    snprintf(filename, PATH_MAX, "/sys/bus/usb/devices/%s/%s", device_name,
1527 b4e237aa blueswir1
             device_file);
1528 0f431527 aliguori
    f = fopen(filename, "r");
1529 0f431527 aliguori
    if (f) {
1530 9f99cee7 Kirill A. Shutemov
        ret = fgets(line, line_size, f) != NULL;
1531 0f431527 aliguori
        fclose(f);
1532 0f431527 aliguori
    }
1533 0f431527 aliguori
1534 0f431527 aliguori
    return ret;
1535 0f431527 aliguori
}
1536 0f431527 aliguori
1537 0f431527 aliguori
/*
1538 0f431527 aliguori
 * Use /sys/bus/usb/devices/ directory to determine host's USB
1539 0f431527 aliguori
 * devices.
1540 0f431527 aliguori
 *
1541 0f431527 aliguori
 * This code is based on Robert Schiele's original patches posted to
1542 0f431527 aliguori
 * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950
1543 0f431527 aliguori
 */
1544 097db438 Gerd Hoffmann
static int usb_host_scan(void *opaque, USBScanFunc *func)
1545 0f431527 aliguori
{
1546 660f11be Blue Swirl
    DIR *dir = NULL;
1547 0f431527 aliguori
    char line[1024];
1548 5557d820 Gerd Hoffmann
    int bus_num, addr, speed, class_id, product_id, vendor_id;
1549 0f431527 aliguori
    int ret = 0;
1550 5557d820 Gerd Hoffmann
    char port[MAX_PORTLEN];
1551 0f431527 aliguori
    char product_name[512];
1552 0f431527 aliguori
    struct dirent *de;
1553 0f431527 aliguori
1554 097db438 Gerd Hoffmann
    dir = opendir("/sys/bus/usb/devices");
1555 0f431527 aliguori
    if (!dir) {
1556 097db438 Gerd Hoffmann
        perror("husb: opendir /sys/bus/usb/devices");
1557 097db438 Gerd Hoffmann
        fprintf(stderr, "husb: please make sure sysfs is mounted at /sys\n");
1558 0f431527 aliguori
        goto the_end;
1559 0f431527 aliguori
    }
1560 0f431527 aliguori
1561 0f431527 aliguori
    while ((de = readdir(dir))) {
1562 0f431527 aliguori
        if (de->d_name[0] != '.' && !strchr(de->d_name, ':')) {
1563 5557d820 Gerd Hoffmann
            if (sscanf(de->d_name, "%d-%7[0-9.]", &bus_num, port) < 2) {
1564 5557d820 Gerd Hoffmann
                continue;
1565 0f5160d1 Hans de Goede
            }
1566 0f431527 aliguori
1567 2791104c David Ahern
            if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name)) {
1568 0f431527 aliguori
                goto the_end;
1569 2791104c David Ahern
            }
1570 2791104c David Ahern
            if (sscanf(line, "%d", &addr) != 1) {
1571 0f431527 aliguori
                goto the_end;
1572 2791104c David Ahern
            }
1573 b4e237aa blueswir1
            if (!usb_host_read_file(line, sizeof(line), "bDeviceClass",
1574 2791104c David Ahern
                                    de->d_name)) {
1575 0f431527 aliguori
                goto the_end;
1576 2791104c David Ahern
            }
1577 2791104c David Ahern
            if (sscanf(line, "%x", &class_id) != 1) {
1578 0f431527 aliguori
                goto the_end;
1579 2791104c David Ahern
            }
1580 0f431527 aliguori
1581 2791104c David Ahern
            if (!usb_host_read_file(line, sizeof(line), "idVendor",
1582 2791104c David Ahern
                                    de->d_name)) {
1583 0f431527 aliguori
                goto the_end;
1584 2791104c David Ahern
            }
1585 2791104c David Ahern
            if (sscanf(line, "%x", &vendor_id) != 1) {
1586 0f431527 aliguori
                goto the_end;
1587 2791104c David Ahern
            }
1588 b4e237aa blueswir1
            if (!usb_host_read_file(line, sizeof(line), "idProduct",
1589 2791104c David Ahern
                                    de->d_name)) {
1590 0f431527 aliguori
                goto the_end;
1591 2791104c David Ahern
            }
1592 2791104c David Ahern
            if (sscanf(line, "%x", &product_id) != 1) {
1593 0f431527 aliguori
                goto the_end;
1594 2791104c David Ahern
            }
1595 b4e237aa blueswir1
            if (!usb_host_read_file(line, sizeof(line), "product",
1596 b4e237aa blueswir1
                                    de->d_name)) {
1597 0f431527 aliguori
                *product_name = 0;
1598 0f431527 aliguori
            } else {
1599 2791104c David Ahern
                if (strlen(line) > 0) {
1600 0f431527 aliguori
                    line[strlen(line) - 1] = '\0';
1601 2791104c David Ahern
                }
1602 0f431527 aliguori
                pstrcpy(product_name, sizeof(product_name), line);
1603 0f431527 aliguori
            }
1604 0f431527 aliguori
1605 2791104c David Ahern
            if (!usb_host_read_file(line, sizeof(line), "speed", de->d_name)) {
1606 0f431527 aliguori
                goto the_end;
1607 2791104c David Ahern
            }
1608 f264cfbf Hans de Goede
            if (!strcmp(line, "5000\n")) {
1609 f264cfbf Hans de Goede
                speed = USB_SPEED_SUPER;
1610 f264cfbf Hans de Goede
            } else if (!strcmp(line, "480\n")) {
1611 0f431527 aliguori
                speed = USB_SPEED_HIGH;
1612 2791104c David Ahern
            } else if (!strcmp(line, "1.5\n")) {
1613 0f431527 aliguori
                speed = USB_SPEED_LOW;
1614 2791104c David Ahern
            } else {
1615 0f431527 aliguori
                speed = USB_SPEED_FULL;
1616 2791104c David Ahern
            }
1617 0f431527 aliguori
1618 5557d820 Gerd Hoffmann
            ret = func(opaque, bus_num, addr, port, class_id, vendor_id,
1619 0f431527 aliguori
                       product_id, product_name, speed);
1620 2791104c David Ahern
            if (ret) {
1621 0f431527 aliguori
                goto the_end;
1622 2791104c David Ahern
            }
1623 0f431527 aliguori
        }
1624 0f431527 aliguori
    }
1625 0f431527 aliguori
 the_end:
1626 2791104c David Ahern
    if (dir) {
1627 0f431527 aliguori
        closedir(dir);
1628 2791104c David Ahern
    }
1629 0f431527 aliguori
    return ret;
1630 0f431527 aliguori
}
1631 0f431527 aliguori
1632 4b096fc9 aliguori
static QEMUTimer *usb_auto_timer;
1633 4b096fc9 aliguori
1634 ba9acab9 Gerd Hoffmann
static int usb_host_auto_scan(void *opaque, int bus_num,
1635 ba9acab9 Gerd Hoffmann
                              int addr, const char *port,
1636 26a9e82a Gerd Hoffmann
                              int class_id, int vendor_id, int product_id,
1637 26a9e82a Gerd Hoffmann
                              const char *product_name, int speed)
1638 4b096fc9 aliguori
{
1639 4b096fc9 aliguori
    struct USBAutoFilter *f;
1640 26a9e82a Gerd Hoffmann
    struct USBHostDevice *s;
1641 4b096fc9 aliguori
1642 4b096fc9 aliguori
    /* Ignore hubs */
1643 4b096fc9 aliguori
    if (class_id == 9)
1644 4b096fc9 aliguori
        return 0;
1645 4b096fc9 aliguori
1646 26a9e82a Gerd Hoffmann
    QTAILQ_FOREACH(s, &hostdevs, next) {
1647 26a9e82a Gerd Hoffmann
        f = &s->match;
1648 26a9e82a Gerd Hoffmann
1649 2791104c David Ahern
        if (f->bus_num > 0 && f->bus_num != bus_num) {
1650 4b096fc9 aliguori
            continue;
1651 2791104c David Ahern
        }
1652 2791104c David Ahern
        if (f->addr > 0 && f->addr != addr) {
1653 4b096fc9 aliguori
            continue;
1654 2791104c David Ahern
        }
1655 9056a297 Gerd Hoffmann
        if (f->port != NULL && (port == NULL || strcmp(f->port, port) != 0)) {
1656 9056a297 Gerd Hoffmann
            continue;
1657 9056a297 Gerd Hoffmann
        }
1658 4b096fc9 aliguori
1659 2791104c David Ahern
        if (f->vendor_id > 0 && f->vendor_id != vendor_id) {
1660 4b096fc9 aliguori
            continue;
1661 2791104c David Ahern
        }
1662 4b096fc9 aliguori
1663 2791104c David Ahern
        if (f->product_id > 0 && f->product_id != product_id) {
1664 4b096fc9 aliguori
            continue;
1665 2791104c David Ahern
        }
1666 4b096fc9 aliguori
        /* We got a match */
1667 3ee886c5 Gerd Hoffmann
        s->seen++;
1668 3ee886c5 Gerd Hoffmann
        if (s->errcount >= 3) {
1669 3ee886c5 Gerd Hoffmann
            return 0;
1670 3ee886c5 Gerd Hoffmann
        }
1671 4b096fc9 aliguori
1672 33e66b86 Markus Armbruster
        /* Already attached ? */
1673 2791104c David Ahern
        if (s->fd != -1) {
1674 4b096fc9 aliguori
            return 0;
1675 2791104c David Ahern
        }
1676 d0f2c4c6 malc
        DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr);
1677 4b096fc9 aliguori
1678 3ee886c5 Gerd Hoffmann
        if (usb_host_open(s, bus_num, addr, port, product_name, speed) < 0) {
1679 3ee886c5 Gerd Hoffmann
            s->errcount++;
1680 3ee886c5 Gerd Hoffmann
        }
1681 97f86166 Hans de Goede
        break;
1682 4b096fc9 aliguori
    }
1683 4b096fc9 aliguori
1684 4b096fc9 aliguori
    return 0;
1685 4b096fc9 aliguori
}
1686 4b096fc9 aliguori
1687 26a9e82a Gerd Hoffmann
static void usb_host_auto_check(void *unused)
1688 4b096fc9 aliguori
{
1689 26a9e82a Gerd Hoffmann
    struct USBHostDevice *s;
1690 26a9e82a Gerd Hoffmann
    int unconnected = 0;
1691 26a9e82a Gerd Hoffmann
1692 4b096fc9 aliguori
    usb_host_scan(NULL, usb_host_auto_scan);
1693 26a9e82a Gerd Hoffmann
1694 26a9e82a Gerd Hoffmann
    QTAILQ_FOREACH(s, &hostdevs, next) {
1695 2791104c David Ahern
        if (s->fd == -1) {
1696 26a9e82a Gerd Hoffmann
            unconnected++;
1697 2791104c David Ahern
        }
1698 3ee886c5 Gerd Hoffmann
        if (s->seen == 0) {
1699 3ee886c5 Gerd Hoffmann
            s->errcount = 0;
1700 3ee886c5 Gerd Hoffmann
        }
1701 3ee886c5 Gerd Hoffmann
        s->seen = 0;
1702 26a9e82a Gerd Hoffmann
    }
1703 26a9e82a Gerd Hoffmann
1704 26a9e82a Gerd Hoffmann
    if (unconnected == 0) {
1705 26a9e82a Gerd Hoffmann
        /* nothing to watch */
1706 2791104c David Ahern
        if (usb_auto_timer) {
1707 26a9e82a Gerd Hoffmann
            qemu_del_timer(usb_auto_timer);
1708 e6a2f500 Gerd Hoffmann
            trace_usb_host_auto_scan_disabled();
1709 2791104c David Ahern
        }
1710 26a9e82a Gerd Hoffmann
        return;
1711 26a9e82a Gerd Hoffmann
    }
1712 26a9e82a Gerd Hoffmann
1713 26a9e82a Gerd Hoffmann
    if (!usb_auto_timer) {
1714 7bd427d8 Paolo Bonzini
        usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL);
1715 2791104c David Ahern
        if (!usb_auto_timer) {
1716 26a9e82a Gerd Hoffmann
            return;
1717 2791104c David Ahern
        }
1718 e6a2f500 Gerd Hoffmann
        trace_usb_host_auto_scan_enabled();
1719 26a9e82a Gerd Hoffmann
    }
1720 7bd427d8 Paolo Bonzini
    qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000);
1721 4b096fc9 aliguori
}
1722 4b096fc9 aliguori
1723 4b096fc9 aliguori
/*
1724 5d0c5750 aliguori
 * Autoconnect filter
1725 5d0c5750 aliguori
 * Format:
1726 5d0c5750 aliguori
 *    auto:bus:dev[:vid:pid]
1727 5d0c5750 aliguori
 *    auto:bus.dev[:vid:pid]
1728 5d0c5750 aliguori
 *
1729 5d0c5750 aliguori
 *    bus  - bus number    (dec, * means any)
1730 5d0c5750 aliguori
 *    dev  - device number (dec, * means any)
1731 5d0c5750 aliguori
 *    vid  - vendor id     (hex, * means any)
1732 5d0c5750 aliguori
 *    pid  - product id    (hex, * means any)
1733 5d0c5750 aliguori
 *
1734 5d0c5750 aliguori
 *    See 'lsusb' output.
1735 4b096fc9 aliguori
 */
1736 5d0c5750 aliguori
static int parse_filter(const char *spec, struct USBAutoFilter *f)
1737 4b096fc9 aliguori
{
1738 5d0c5750 aliguori
    enum { BUS, DEV, VID, PID, DONE };
1739 5d0c5750 aliguori
    const char *p = spec;
1740 5d0c5750 aliguori
    int i;
1741 5d0c5750 aliguori
1742 0745eb1e Markus Armbruster
    f->bus_num    = 0;
1743 0745eb1e Markus Armbruster
    f->addr       = 0;
1744 0745eb1e Markus Armbruster
    f->vendor_id  = 0;
1745 0745eb1e Markus Armbruster
    f->product_id = 0;
1746 5d0c5750 aliguori
1747 5d0c5750 aliguori
    for (i = BUS; i < DONE; i++) {
1748 2791104c David Ahern
        p = strpbrk(p, ":.");
1749 2791104c David Ahern
        if (!p) {
1750 2791104c David Ahern
            break;
1751 2791104c David Ahern
        }
1752 5d0c5750 aliguori
        p++;
1753 5d0c5750 aliguori
1754 2791104c David Ahern
        if (*p == '*') {
1755 2791104c David Ahern
            continue;
1756 2791104c David Ahern
        }
1757 5d0c5750 aliguori
        switch(i) {
1758 5d0c5750 aliguori
        case BUS: f->bus_num = strtol(p, NULL, 10);    break;
1759 5d0c5750 aliguori
        case DEV: f->addr    = strtol(p, NULL, 10);    break;
1760 5d0c5750 aliguori
        case VID: f->vendor_id  = strtol(p, NULL, 16); break;
1761 5d0c5750 aliguori
        case PID: f->product_id = strtol(p, NULL, 16); break;
1762 5d0c5750 aliguori
        }
1763 5d0c5750 aliguori
    }
1764 5d0c5750 aliguori
1765 5d0c5750 aliguori
    if (i < DEV) {
1766 5d0c5750 aliguori
        fprintf(stderr, "husb: invalid auto filter spec %s\n", spec);
1767 5d0c5750 aliguori
        return -1;
1768 5d0c5750 aliguori
    }
1769 5d0c5750 aliguori
1770 5d0c5750 aliguori
    return 0;
1771 5d0c5750 aliguori
}
1772 5d0c5750 aliguori
1773 a594cfbf bellard
/**********************/
1774 a594cfbf bellard
/* USB host device info */
1775 a594cfbf bellard
1776 a594cfbf bellard
struct usb_class_info {
1777 a594cfbf bellard
    int class;
1778 a594cfbf bellard
    const char *class_name;
1779 a594cfbf bellard
};
1780 a594cfbf bellard
1781 a594cfbf bellard
static const struct usb_class_info usb_class_info[] = {
1782 a594cfbf bellard
    { USB_CLASS_AUDIO, "Audio"},
1783 a594cfbf bellard
    { USB_CLASS_COMM, "Communication"},
1784 a594cfbf bellard
    { USB_CLASS_HID, "HID"},
1785 a594cfbf bellard
    { USB_CLASS_HUB, "Hub" },
1786 a594cfbf bellard
    { USB_CLASS_PHYSICAL, "Physical" },
1787 a594cfbf bellard
    { USB_CLASS_PRINTER, "Printer" },
1788 a594cfbf bellard
    { USB_CLASS_MASS_STORAGE, "Storage" },
1789 a594cfbf bellard
    { USB_CLASS_CDC_DATA, "Data" },
1790 a594cfbf bellard
    { USB_CLASS_APP_SPEC, "Application Specific" },
1791 a594cfbf bellard
    { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
1792 a594cfbf bellard
    { USB_CLASS_STILL_IMAGE, "Still Image" },
1793 b9dc033c balrog
    { USB_CLASS_CSCID, "Smart Card" },
1794 a594cfbf bellard
    { USB_CLASS_CONTENT_SEC, "Content Security" },
1795 a594cfbf bellard
    { -1, NULL }
1796 a594cfbf bellard
};
1797 a594cfbf bellard
1798 a594cfbf bellard
static const char *usb_class_str(uint8_t class)
1799 bb36d470 bellard
{
1800 a594cfbf bellard
    const struct usb_class_info *p;
1801 a594cfbf bellard
    for(p = usb_class_info; p->class != -1; p++) {
1802 2791104c David Ahern
        if (p->class == class) {
1803 a594cfbf bellard
            break;
1804 2791104c David Ahern
        }
1805 bb36d470 bellard
    }
1806 a594cfbf bellard
    return p->class_name;
1807 a594cfbf bellard
}
1808 a594cfbf bellard
1809 ba9acab9 Gerd Hoffmann
static void usb_info_device(Monitor *mon, int bus_num,
1810 ba9acab9 Gerd Hoffmann
                            int addr, const char *port,
1811 5557d820 Gerd Hoffmann
                            int class_id, int vendor_id, int product_id,
1812 9596ebb7 pbrook
                            const char *product_name,
1813 9596ebb7 pbrook
                            int speed)
1814 a594cfbf bellard
{
1815 a594cfbf bellard
    const char *class_str, *speed_str;
1816 a594cfbf bellard
1817 a594cfbf bellard
    switch(speed) {
1818 5fafdf24 ths
    case USB_SPEED_LOW:
1819 5fafdf24 ths
        speed_str = "1.5";
1820 a594cfbf bellard
        break;
1821 5fafdf24 ths
    case USB_SPEED_FULL:
1822 5fafdf24 ths
        speed_str = "12";
1823 a594cfbf bellard
        break;
1824 5fafdf24 ths
    case USB_SPEED_HIGH:
1825 5fafdf24 ths
        speed_str = "480";
1826 a594cfbf bellard
        break;
1827 f264cfbf Hans de Goede
    case USB_SPEED_SUPER:
1828 f264cfbf Hans de Goede
        speed_str = "5000";
1829 f264cfbf Hans de Goede
        break;
1830 a594cfbf bellard
    default:
1831 5fafdf24 ths
        speed_str = "?";
1832 a594cfbf bellard
        break;
1833 a594cfbf bellard
    }
1834 a594cfbf bellard
1835 5557d820 Gerd Hoffmann
    monitor_printf(mon, "  Bus %d, Addr %d, Port %s, Speed %s Mb/s\n",
1836 5557d820 Gerd Hoffmann
                   bus_num, addr, port, speed_str);
1837 a594cfbf bellard
    class_str = usb_class_str(class_id);
1838 2791104c David Ahern
    if (class_str) {
1839 376253ec aliguori
        monitor_printf(mon, "    %s:", class_str);
1840 2791104c David Ahern
    } else {
1841 376253ec aliguori
        monitor_printf(mon, "    Class %02x:", class_id);
1842 2791104c David Ahern
    }
1843 376253ec aliguori
    monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
1844 2791104c David Ahern
    if (product_name[0] != '\0') {
1845 376253ec aliguori
        monitor_printf(mon, ", %s", product_name);
1846 2791104c David Ahern
    }
1847 376253ec aliguori
    monitor_printf(mon, "\n");
1848 a594cfbf bellard
}
1849 a594cfbf bellard
1850 5fafdf24 ths
static int usb_host_info_device(void *opaque, int bus_num, int addr,
1851 ba9acab9 Gerd Hoffmann
                                const char *path, int class_id,
1852 5fafdf24 ths
                                int vendor_id, int product_id,
1853 a594cfbf bellard
                                const char *product_name,
1854 a594cfbf bellard
                                int speed)
1855 a594cfbf bellard
{
1856 179da8af Blue Swirl
    Monitor *mon = opaque;
1857 179da8af Blue Swirl
1858 5557d820 Gerd Hoffmann
    usb_info_device(mon, bus_num, addr, path, class_id, vendor_id, product_id,
1859 a594cfbf bellard
                    product_name, speed);
1860 a594cfbf bellard
    return 0;
1861 a594cfbf bellard
}
1862 a594cfbf bellard
1863 ac4ffb5a aliguori
static void dec2str(int val, char *str, size_t size)
1864 5d0c5750 aliguori
{
1865 2791104c David Ahern
    if (val == 0) {
1866 ac4ffb5a aliguori
        snprintf(str, size, "*");
1867 2791104c David Ahern
    } else {
1868 2791104c David Ahern
        snprintf(str, size, "%d", val);
1869 2791104c David Ahern
    }
1870 5d0c5750 aliguori
}
1871 5d0c5750 aliguori
1872 ac4ffb5a aliguori
static void hex2str(int val, char *str, size_t size)
1873 5d0c5750 aliguori
{
1874 2791104c David Ahern
    if (val == 0) {
1875 ac4ffb5a aliguori
        snprintf(str, size, "*");
1876 2791104c David Ahern
    } else {
1877 26a9e82a Gerd Hoffmann
        snprintf(str, size, "%04x", val);
1878 2791104c David Ahern
    }
1879 5d0c5750 aliguori
}
1880 5d0c5750 aliguori
1881 376253ec aliguori
void usb_host_info(Monitor *mon)
1882 a594cfbf bellard
{
1883 5d0c5750 aliguori
    struct USBAutoFilter *f;
1884 26a9e82a Gerd Hoffmann
    struct USBHostDevice *s;
1885 5d0c5750 aliguori
1886 179da8af Blue Swirl
    usb_host_scan(mon, usb_host_info_device);
1887 5d0c5750 aliguori
1888 2791104c David Ahern
    if (QTAILQ_EMPTY(&hostdevs)) {
1889 26a9e82a Gerd Hoffmann
        return;
1890 2791104c David Ahern
    }
1891 2791104c David Ahern
1892 26a9e82a Gerd Hoffmann
    monitor_printf(mon, "  Auto filters:\n");
1893 26a9e82a Gerd Hoffmann
    QTAILQ_FOREACH(s, &hostdevs, next) {
1894 5d0c5750 aliguori
        char bus[10], addr[10], vid[10], pid[10];
1895 26a9e82a Gerd Hoffmann
        f = &s->match;
1896 ac4ffb5a aliguori
        dec2str(f->bus_num, bus, sizeof(bus));
1897 ac4ffb5a aliguori
        dec2str(f->addr, addr, sizeof(addr));
1898 ac4ffb5a aliguori
        hex2str(f->vendor_id, vid, sizeof(vid));
1899 ac4ffb5a aliguori
        hex2str(f->product_id, pid, sizeof(pid));
1900 9056a297 Gerd Hoffmann
        monitor_printf(mon, "    Bus %s, Addr %s, Port %s, ID %s:%s\n",
1901 9056a297 Gerd Hoffmann
                       bus, addr, f->port ? f->port : "*", vid, pid);
1902 5d0c5750 aliguori
    }
1903 bb36d470 bellard
}