Statistics
| Branch: | Revision:

root / usb-linux.c @ a74cdab4

History | View | Annotate | Download (53.4 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 bb36d470 bellard
38 bb36d470 bellard
#include <dirent.h>
39 bb36d470 bellard
#include <sys/ioctl.h>
40 b9dc033c balrog
#include <signal.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 d9cf1578 blueswir1
struct usb_ctrlrequest {
58 d9cf1578 blueswir1
    uint8_t bRequestType;
59 d9cf1578 blueswir1
    uint8_t bRequest;
60 d9cf1578 blueswir1
    uint16_t wValue;
61 d9cf1578 blueswir1
    uint16_t wIndex;
62 d9cf1578 blueswir1
    uint16_t wLength;
63 d9cf1578 blueswir1
};
64 d9cf1578 blueswir1
65 0f5160d1 Hans de Goede
typedef int USBScanFunc(void *opaque, int bus_num, int addr, int devpath,
66 0f5160d1 Hans de Goede
                        int class_id, int vendor_id, int product_id,
67 a594cfbf bellard
                        const char *product_name, int speed);
68 26a9e82a Gerd Hoffmann
69 0745eb1e Markus Armbruster
//#define DEBUG
70 64838171 aliguori
71 64838171 aliguori
#ifdef DEBUG
72 d0f2c4c6 malc
#define DPRINTF printf
73 64838171 aliguori
#else
74 d0f2c4c6 malc
#define DPRINTF(...)
75 64838171 aliguori
#endif
76 bb36d470 bellard
77 5be8e1f2 blueswir1
#define USBDBG_DEVOPENED "husb: opened %s/devices\n"
78 5be8e1f2 blueswir1
79 0f431527 aliguori
#define USBPROCBUS_PATH "/proc/bus/usb"
80 1f6e24e7 bellard
#define PRODUCT_NAME_SZ 32
81 3a4854b3 Hans de Goede
#define MAX_ENDPOINTS 15
82 0f431527 aliguori
#define USBDEVBUS_PATH "/dev/bus/usb"
83 0f431527 aliguori
#define USBSYSBUS_PATH "/sys/bus/usb"
84 0f431527 aliguori
85 0f431527 aliguori
static char *usb_host_device_path;
86 0f431527 aliguori
87 0f431527 aliguori
#define USB_FS_NONE 0
88 0f431527 aliguori
#define USB_FS_PROC 1
89 0f431527 aliguori
#define USB_FS_DEV 2
90 0f431527 aliguori
#define USB_FS_SYS 3
91 0f431527 aliguori
92 0f431527 aliguori
static int usb_fs_type;
93 bb36d470 bellard
94 b9dc033c balrog
/* endpoint association data */
95 060dc841 Hans de Goede
#define ISO_FRAME_DESC_PER_URB 32
96 060dc841 Hans de Goede
#define ISO_URB_COUNT 3
97 a0b5fece Hans de Goede
#define INVALID_EP_TYPE 255
98 060dc841 Hans de Goede
99 060dc841 Hans de Goede
typedef struct AsyncURB AsyncURB;
100 060dc841 Hans de Goede
101 b9dc033c balrog
struct endp_data {
102 b9dc033c balrog
    uint8_t type;
103 64838171 aliguori
    uint8_t halted;
104 bb6d5498 Hans de Goede
    uint8_t iso_started;
105 060dc841 Hans de Goede
    AsyncURB *iso_urb;
106 060dc841 Hans de Goede
    int iso_urb_idx;
107 bb6d5498 Hans de Goede
    int iso_buffer_used;
108 060dc841 Hans de Goede
    int max_packet_size;
109 b9dc033c balrog
};
110 b9dc033c balrog
111 446ab128 aliguori
enum {
112 446ab128 aliguori
    CTRL_STATE_IDLE = 0,
113 446ab128 aliguori
    CTRL_STATE_SETUP,
114 446ab128 aliguori
    CTRL_STATE_DATA,
115 446ab128 aliguori
    CTRL_STATE_ACK
116 446ab128 aliguori
};
117 446ab128 aliguori
118 446ab128 aliguori
/*
119 446ab128 aliguori
 * Control transfer state.
120 2791104c David Ahern
 * Note that 'buffer' _must_ follow 'req' field because
121 a0102082 Brad Hards
 * we need contiguous buffer when we submit control URB.
122 2791104c David Ahern
 */
123 446ab128 aliguori
struct ctrl_struct {
124 446ab128 aliguori
    uint16_t len;
125 446ab128 aliguori
    uint16_t offset;
126 446ab128 aliguori
    uint8_t  state;
127 446ab128 aliguori
    struct   usb_ctrlrequest req;
128 fd7a446f Christian Krause
    uint8_t  buffer[8192];
129 446ab128 aliguori
};
130 446ab128 aliguori
131 26a9e82a Gerd Hoffmann
struct USBAutoFilter {
132 26a9e82a Gerd Hoffmann
    uint32_t bus_num;
133 26a9e82a Gerd Hoffmann
    uint32_t addr;
134 26a9e82a Gerd Hoffmann
    uint32_t vendor_id;
135 26a9e82a Gerd Hoffmann
    uint32_t product_id;
136 26a9e82a Gerd Hoffmann
};
137 26a9e82a Gerd Hoffmann
138 bb36d470 bellard
typedef struct USBHostDevice {
139 bb36d470 bellard
    USBDevice dev;
140 64838171 aliguori
    int       fd;
141 64838171 aliguori
142 64838171 aliguori
    uint8_t   descr[1024];
143 64838171 aliguori
    int       descr_len;
144 64838171 aliguori
    int       configuration;
145 446ab128 aliguori
    int       ninterfaces;
146 24772c1e aliguori
    int       closing;
147 b373a63a Shahar Havivi
    Notifier  exit;
148 64838171 aliguori
149 446ab128 aliguori
    struct ctrl_struct ctrl;
150 b9dc033c balrog
    struct endp_data endp_table[MAX_ENDPOINTS];
151 4b096fc9 aliguori
152 4b096fc9 aliguori
    /* Host side address */
153 4b096fc9 aliguori
    int bus_num;
154 4b096fc9 aliguori
    int addr;
155 0f5160d1 Hans de Goede
    int devpath;
156 26a9e82a Gerd Hoffmann
    struct USBAutoFilter match;
157 4b096fc9 aliguori
158 26a9e82a Gerd Hoffmann
    QTAILQ_ENTRY(USBHostDevice) next;
159 bb36d470 bellard
} USBHostDevice;
160 bb36d470 bellard
161 26a9e82a Gerd Hoffmann
static QTAILQ_HEAD(, USBHostDevice) hostdevs = QTAILQ_HEAD_INITIALIZER(hostdevs);
162 26a9e82a Gerd Hoffmann
163 26a9e82a Gerd Hoffmann
static int usb_host_close(USBHostDevice *dev);
164 26a9e82a Gerd Hoffmann
static int parse_filter(const char *spec, struct USBAutoFilter *f);
165 26a9e82a Gerd Hoffmann
static void usb_host_auto_check(void *unused);
166 2cc59d8c Hans de Goede
static int usb_host_read_file(char *line, size_t line_size,
167 2cc59d8c Hans de Goede
                            const char *device_file, const char *device_name);
168 26a9e82a Gerd Hoffmann
169 64838171 aliguori
static int is_isoc(USBHostDevice *s, int ep)
170 64838171 aliguori
{
171 64838171 aliguori
    return s->endp_table[ep - 1].type == USBDEVFS_URB_TYPE_ISO;
172 64838171 aliguori
}
173 64838171 aliguori
174 a0b5fece Hans de Goede
static int is_valid(USBHostDevice *s, int ep)
175 a0b5fece Hans de Goede
{
176 a0b5fece Hans de Goede
    return s->endp_table[ep - 1].type != INVALID_EP_TYPE;
177 a0b5fece Hans de Goede
}
178 a0b5fece Hans de Goede
179 64838171 aliguori
static int is_halted(USBHostDevice *s, int ep)
180 64838171 aliguori
{
181 64838171 aliguori
    return s->endp_table[ep - 1].halted;
182 64838171 aliguori
}
183 64838171 aliguori
184 64838171 aliguori
static void clear_halt(USBHostDevice *s, int ep)
185 64838171 aliguori
{
186 64838171 aliguori
    s->endp_table[ep - 1].halted = 0;
187 64838171 aliguori
}
188 64838171 aliguori
189 64838171 aliguori
static void set_halt(USBHostDevice *s, int ep)
190 64838171 aliguori
{
191 64838171 aliguori
    s->endp_table[ep - 1].halted = 1;
192 64838171 aliguori
}
193 64838171 aliguori
194 bb6d5498 Hans de Goede
static int is_iso_started(USBHostDevice *s, int ep)
195 bb6d5498 Hans de Goede
{
196 bb6d5498 Hans de Goede
    return s->endp_table[ep - 1].iso_started;
197 bb6d5498 Hans de Goede
}
198 bb6d5498 Hans de Goede
199 bb6d5498 Hans de Goede
static void clear_iso_started(USBHostDevice *s, int ep)
200 bb6d5498 Hans de Goede
{
201 bb6d5498 Hans de Goede
    s->endp_table[ep - 1].iso_started = 0;
202 bb6d5498 Hans de Goede
}
203 bb6d5498 Hans de Goede
204 bb6d5498 Hans de Goede
static void set_iso_started(USBHostDevice *s, int ep)
205 bb6d5498 Hans de Goede
{
206 bb6d5498 Hans de Goede
    s->endp_table[ep - 1].iso_started = 1;
207 bb6d5498 Hans de Goede
}
208 bb6d5498 Hans de Goede
209 060dc841 Hans de Goede
static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb)
210 060dc841 Hans de Goede
{
211 060dc841 Hans de Goede
    s->endp_table[ep - 1].iso_urb = iso_urb;
212 060dc841 Hans de Goede
}
213 060dc841 Hans de Goede
214 060dc841 Hans de Goede
static AsyncURB *get_iso_urb(USBHostDevice *s, int ep)
215 060dc841 Hans de Goede
{
216 060dc841 Hans de Goede
    return s->endp_table[ep - 1].iso_urb;
217 060dc841 Hans de Goede
}
218 060dc841 Hans de Goede
219 060dc841 Hans de Goede
static void set_iso_urb_idx(USBHostDevice *s, int ep, int i)
220 060dc841 Hans de Goede
{
221 060dc841 Hans de Goede
    s->endp_table[ep - 1].iso_urb_idx = i;
222 060dc841 Hans de Goede
}
223 060dc841 Hans de Goede
224 060dc841 Hans de Goede
static int get_iso_urb_idx(USBHostDevice *s, int ep)
225 060dc841 Hans de Goede
{
226 060dc841 Hans de Goede
    return s->endp_table[ep - 1].iso_urb_idx;
227 060dc841 Hans de Goede
}
228 060dc841 Hans de Goede
229 bb6d5498 Hans de Goede
static void set_iso_buffer_used(USBHostDevice *s, int ep, int i)
230 bb6d5498 Hans de Goede
{
231 bb6d5498 Hans de Goede
    s->endp_table[ep - 1].iso_buffer_used = i;
232 bb6d5498 Hans de Goede
}
233 bb6d5498 Hans de Goede
234 bb6d5498 Hans de Goede
static int get_iso_buffer_used(USBHostDevice *s, int ep)
235 bb6d5498 Hans de Goede
{
236 bb6d5498 Hans de Goede
    return s->endp_table[ep - 1].iso_buffer_used;
237 bb6d5498 Hans de Goede
}
238 bb6d5498 Hans de Goede
239 060dc841 Hans de Goede
static int get_max_packet_size(USBHostDevice *s, int ep)
240 060dc841 Hans de Goede
{
241 060dc841 Hans de Goede
    return s->endp_table[ep - 1].max_packet_size;
242 060dc841 Hans de Goede
}
243 060dc841 Hans de Goede
244 2791104c David Ahern
/*
245 64838171 aliguori
 * Async URB state.
246 060dc841 Hans de Goede
 * We always allocate iso packet descriptors even for bulk transfers
247 2791104c David Ahern
 * to simplify allocation and casts.
248 64838171 aliguori
 */
249 060dc841 Hans de Goede
struct AsyncURB
250 64838171 aliguori
{
251 64838171 aliguori
    struct usbdevfs_urb urb;
252 060dc841 Hans de Goede
    struct usbdevfs_iso_packet_desc isocpd[ISO_FRAME_DESC_PER_URB];
253 b9dc033c balrog
254 060dc841 Hans de Goede
    /* For regular async urbs */
255 64838171 aliguori
    USBPacket     *packet;
256 64838171 aliguori
    USBHostDevice *hdev;
257 060dc841 Hans de Goede
258 060dc841 Hans de Goede
    /* For buffered iso handling */
259 060dc841 Hans de Goede
    int iso_frame_idx; /* -1 means in flight */
260 060dc841 Hans de Goede
};
261 b9dc033c balrog
262 64838171 aliguori
static AsyncURB *async_alloc(void)
263 b9dc033c balrog
{
264 64838171 aliguori
    return (AsyncURB *) qemu_mallocz(sizeof(AsyncURB));
265 b9dc033c balrog
}
266 b9dc033c balrog
267 64838171 aliguori
static void async_free(AsyncURB *aurb)
268 b9dc033c balrog
{
269 64838171 aliguori
    qemu_free(aurb);
270 64838171 aliguori
}
271 b9dc033c balrog
272 446ab128 aliguori
static void async_complete_ctrl(USBHostDevice *s, USBPacket *p)
273 446ab128 aliguori
{
274 446ab128 aliguori
    switch(s->ctrl.state) {
275 446ab128 aliguori
    case CTRL_STATE_SETUP:
276 446ab128 aliguori
        if (p->len < s->ctrl.len)
277 446ab128 aliguori
            s->ctrl.len = p->len;
278 446ab128 aliguori
        s->ctrl.state = CTRL_STATE_DATA;
279 446ab128 aliguori
        p->len = 8;
280 446ab128 aliguori
        break;
281 446ab128 aliguori
282 446ab128 aliguori
    case CTRL_STATE_ACK:
283 446ab128 aliguori
        s->ctrl.state = CTRL_STATE_IDLE;
284 446ab128 aliguori
        p->len = 0;
285 446ab128 aliguori
        break;
286 446ab128 aliguori
287 446ab128 aliguori
    default:
288 446ab128 aliguori
        break;
289 446ab128 aliguori
    }
290 446ab128 aliguori
}
291 446ab128 aliguori
292 64838171 aliguori
static void async_complete(void *opaque)
293 64838171 aliguori
{
294 64838171 aliguori
    USBHostDevice *s = opaque;
295 64838171 aliguori
    AsyncURB *aurb;
296 64838171 aliguori
297 64838171 aliguori
    while (1) {
298 2791104c David Ahern
        USBPacket *p;
299 b9dc033c balrog
300 2791104c David Ahern
        int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
301 64838171 aliguori
        if (r < 0) {
302 2791104c David Ahern
            if (errno == EAGAIN) {
303 64838171 aliguori
                return;
304 2791104c David Ahern
            }
305 24772c1e aliguori
            if (errno == ENODEV && !s->closing) {
306 2791104c David Ahern
                printf("husb: device %d.%d disconnected\n",
307 2791104c David Ahern
                       s->bus_num, s->addr);
308 26a9e82a Gerd Hoffmann
                usb_host_close(s);
309 26a9e82a Gerd Hoffmann
                usb_host_auto_check(NULL);
310 64838171 aliguori
                return;
311 64838171 aliguori
            }
312 64838171 aliguori
313 d0f2c4c6 malc
            DPRINTF("husb: async. reap urb failed errno %d\n", errno);
314 64838171 aliguori
            return;
315 b9dc033c balrog
        }
316 64838171 aliguori
317 2791104c David Ahern
        DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
318 64838171 aliguori
                aurb, aurb->urb.status, aurb->urb.actual_length);
319 64838171 aliguori
320 060dc841 Hans de Goede
        /* If this is a buffered iso urb mark it as complete and don't do
321 060dc841 Hans de Goede
           anything else (it is handled further in usb_host_handle_iso_data) */
322 060dc841 Hans de Goede
        if (aurb->iso_frame_idx == -1) {
323 060dc841 Hans de Goede
            if (aurb->urb.status == -EPIPE) {
324 060dc841 Hans de Goede
                set_halt(s, aurb->urb.endpoint & 0xf);
325 060dc841 Hans de Goede
            }
326 060dc841 Hans de Goede
            aurb->iso_frame_idx = 0;
327 060dc841 Hans de Goede
            continue;
328 060dc841 Hans de Goede
        }
329 060dc841 Hans de Goede
330 060dc841 Hans de Goede
        p = aurb->packet;
331 060dc841 Hans de Goede
332 2791104c David Ahern
        if (p) {
333 64838171 aliguori
            switch (aurb->urb.status) {
334 64838171 aliguori
            case 0:
335 64838171 aliguori
                p->len = aurb->urb.actual_length;
336 2791104c David Ahern
                if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
337 446ab128 aliguori
                    async_complete_ctrl(s, p);
338 2791104c David Ahern
                }
339 64838171 aliguori
                break;
340 64838171 aliguori
341 64838171 aliguori
            case -EPIPE:
342 64838171 aliguori
                set_halt(s, p->devep);
343 2791104c David Ahern
                p->len = USB_RET_STALL;
344 2791104c David Ahern
                break;
345 dcc7e25f Paul Bolle
346 64838171 aliguori
            default:
347 64838171 aliguori
                p->len = USB_RET_NAK;
348 64838171 aliguori
                break;
349 64838171 aliguori
            }
350 64838171 aliguori
351 13a9a0d3 Gerd Hoffmann
            usb_packet_complete(&s->dev, p);
352 2791104c David Ahern
        }
353 64838171 aliguori
354 64838171 aliguori
        async_free(aurb);
355 b9dc033c balrog
    }
356 b9dc033c balrog
}
357 b9dc033c balrog
358 64838171 aliguori
static void async_cancel(USBPacket *unused, void *opaque)
359 b9dc033c balrog
{
360 64838171 aliguori
    AsyncURB *aurb = opaque;
361 64838171 aliguori
    USBHostDevice *s = aurb->hdev;
362 b9dc033c balrog
363 d0f2c4c6 malc
    DPRINTF("husb: async cancel. aurb %p\n", aurb);
364 64838171 aliguori
365 64838171 aliguori
    /* Mark it as dead (see async_complete above) */
366 64838171 aliguori
    aurb->packet = NULL;
367 b9dc033c balrog
368 64838171 aliguori
    int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb);
369 64838171 aliguori
    if (r < 0) {
370 d0f2c4c6 malc
        DPRINTF("husb: async. discard urb failed errno %d\n", errno);
371 b9dc033c balrog
    }
372 b9dc033c balrog
}
373 b9dc033c balrog
374 446ab128 aliguori
static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
375 b9dc033c balrog
{
376 b9dc033c balrog
    int dev_descr_len, config_descr_len;
377 d4c4e6fd Blue Swirl
    int interface, nb_interfaces;
378 b9dc033c balrog
    int ret, i;
379 b9dc033c balrog
380 b9dc033c balrog
    if (configuration == 0) /* address state - ignore */
381 b9dc033c balrog
        return 1;
382 b9dc033c balrog
383 d0f2c4c6 malc
    DPRINTF("husb: claiming interfaces. config %d\n", configuration);
384 446ab128 aliguori
385 b9dc033c balrog
    i = 0;
386 b9dc033c balrog
    dev_descr_len = dev->descr[0];
387 2791104c David Ahern
    if (dev_descr_len > dev->descr_len) {
388 b9dc033c balrog
        goto fail;
389 2791104c David Ahern
    }
390 b9dc033c balrog
391 b9dc033c balrog
    i += dev_descr_len;
392 b9dc033c balrog
    while (i < dev->descr_len) {
393 2791104c David Ahern
        DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
394 2791104c David Ahern
                i, dev->descr_len,
395 b9dc033c balrog
               dev->descr[i], dev->descr[i+1]);
396 64838171 aliguori
397 b9dc033c balrog
        if (dev->descr[i+1] != USB_DT_CONFIG) {
398 b9dc033c balrog
            i += dev->descr[i];
399 b9dc033c balrog
            continue;
400 b9dc033c balrog
        }
401 b9dc033c balrog
        config_descr_len = dev->descr[i];
402 b9dc033c balrog
403 2791104c David Ahern
        printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
404 1f3870ab aliguori
405 446ab128 aliguori
        if (configuration < 0 || configuration == dev->descr[i + 5]) {
406 446ab128 aliguori
            configuration = dev->descr[i + 5];
407 b9dc033c balrog
            break;
408 446ab128 aliguori
        }
409 b9dc033c balrog
410 b9dc033c balrog
        i += config_descr_len;
411 b9dc033c balrog
    }
412 b9dc033c balrog
413 b9dc033c balrog
    if (i >= dev->descr_len) {
414 2791104c David Ahern
        fprintf(stderr,
415 2791104c David Ahern
                "husb: update iface failed. no matching configuration\n");
416 b9dc033c balrog
        goto fail;
417 b9dc033c balrog
    }
418 b9dc033c balrog
    nb_interfaces = dev->descr[i + 4];
419 b9dc033c balrog
420 b9dc033c balrog
#ifdef USBDEVFS_DISCONNECT
421 b9dc033c balrog
    /* earlier Linux 2.4 do not support that */
422 b9dc033c balrog
    {
423 b9dc033c balrog
        struct usbdevfs_ioctl ctrl;
424 b9dc033c balrog
        for (interface = 0; interface < nb_interfaces; interface++) {
425 b9dc033c balrog
            ctrl.ioctl_code = USBDEVFS_DISCONNECT;
426 b9dc033c balrog
            ctrl.ifno = interface;
427 021730f7 Brad Hards
            ctrl.data = 0;
428 b9dc033c balrog
            ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
429 b9dc033c balrog
            if (ret < 0 && errno != ENODATA) {
430 b9dc033c balrog
                perror("USBDEVFS_DISCONNECT");
431 b9dc033c balrog
                goto fail;
432 b9dc033c balrog
            }
433 b9dc033c balrog
        }
434 b9dc033c balrog
    }
435 b9dc033c balrog
#endif
436 b9dc033c balrog
437 b9dc033c balrog
    /* XXX: only grab if all interfaces are free */
438 b9dc033c balrog
    for (interface = 0; interface < nb_interfaces; interface++) {
439 b9dc033c balrog
        ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
440 b9dc033c balrog
        if (ret < 0) {
441 b9dc033c balrog
            if (errno == EBUSY) {
442 64838171 aliguori
                printf("husb: update iface. device already grabbed\n");
443 b9dc033c balrog
            } else {
444 64838171 aliguori
                perror("husb: failed to claim interface");
445 b9dc033c balrog
            }
446 b9dc033c balrog
        fail:
447 b9dc033c balrog
            return 0;
448 b9dc033c balrog
        }
449 b9dc033c balrog
    }
450 b9dc033c balrog
451 64838171 aliguori
    printf("husb: %d interfaces claimed for configuration %d\n",
452 b9dc033c balrog
           nb_interfaces, configuration);
453 b9dc033c balrog
454 446ab128 aliguori
    dev->ninterfaces   = nb_interfaces;
455 446ab128 aliguori
    dev->configuration = configuration;
456 446ab128 aliguori
    return 1;
457 446ab128 aliguori
}
458 446ab128 aliguori
459 446ab128 aliguori
static int usb_host_release_interfaces(USBHostDevice *s)
460 446ab128 aliguori
{
461 446ab128 aliguori
    int ret, i;
462 446ab128 aliguori
463 d0f2c4c6 malc
    DPRINTF("husb: releasing interfaces\n");
464 446ab128 aliguori
465 446ab128 aliguori
    for (i = 0; i < s->ninterfaces; i++) {
466 446ab128 aliguori
        ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i);
467 446ab128 aliguori
        if (ret < 0) {
468 446ab128 aliguori
            perror("husb: failed to release interface");
469 446ab128 aliguori
            return 0;
470 446ab128 aliguori
        }
471 446ab128 aliguori
    }
472 446ab128 aliguori
473 b9dc033c balrog
    return 1;
474 b9dc033c balrog
}
475 b9dc033c balrog
476 059809e4 bellard
static void usb_host_handle_reset(USBDevice *dev)
477 bb36d470 bellard
{
478 26a9e82a Gerd Hoffmann
    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
479 64838171 aliguori
480 d0f2c4c6 malc
    DPRINTF("husb: reset device %u.%u\n", s->bus_num, s->addr);
481 64838171 aliguori
482 bb36d470 bellard
    ioctl(s->fd, USBDEVFS_RESET);
483 446ab128 aliguori
484 446ab128 aliguori
    usb_host_claim_interfaces(s, s->configuration);
485 5fafdf24 ths
}
486 bb36d470 bellard
487 059809e4 bellard
static void usb_host_handle_destroy(USBDevice *dev)
488 059809e4 bellard
{
489 059809e4 bellard
    USBHostDevice *s = (USBHostDevice *)dev;
490 059809e4 bellard
491 26a9e82a Gerd Hoffmann
    usb_host_close(s);
492 26a9e82a Gerd Hoffmann
    QTAILQ_REMOVE(&hostdevs, s, next);
493 b373a63a Shahar Havivi
    qemu_remove_exit_notifier(&s->exit);
494 059809e4 bellard
}
495 059809e4 bellard
496 b9dc033c balrog
static int usb_linux_update_endp_table(USBHostDevice *s);
497 b9dc033c balrog
498 060dc841 Hans de Goede
/* iso data is special, we need to keep enough urbs in flight to make sure
499 060dc841 Hans de Goede
   that the controller never runs out of them, otherwise the device will
500 060dc841 Hans de Goede
   likely suffer a buffer underrun / overrun. */
501 060dc841 Hans de Goede
static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, uint8_t ep, int in)
502 060dc841 Hans de Goede
{
503 060dc841 Hans de Goede
    AsyncURB *aurb;
504 060dc841 Hans de Goede
    int i, j, len = get_max_packet_size(s, ep);
505 060dc841 Hans de Goede
506 060dc841 Hans de Goede
    aurb = qemu_mallocz(ISO_URB_COUNT * sizeof(*aurb));
507 060dc841 Hans de Goede
    for (i = 0; i < ISO_URB_COUNT; i++) {
508 060dc841 Hans de Goede
        aurb[i].urb.endpoint      = ep;
509 060dc841 Hans de Goede
        aurb[i].urb.buffer_length = ISO_FRAME_DESC_PER_URB * len;
510 060dc841 Hans de Goede
        aurb[i].urb.buffer        = qemu_malloc(aurb[i].urb.buffer_length);
511 060dc841 Hans de Goede
        aurb[i].urb.type          = USBDEVFS_URB_TYPE_ISO;
512 060dc841 Hans de Goede
        aurb[i].urb.flags         = USBDEVFS_URB_ISO_ASAP;
513 060dc841 Hans de Goede
        aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB;
514 060dc841 Hans de Goede
        for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++)
515 060dc841 Hans de Goede
            aurb[i].urb.iso_frame_desc[j].length = len;
516 060dc841 Hans de Goede
        if (in) {
517 060dc841 Hans de Goede
            aurb[i].urb.endpoint |= 0x80;
518 060dc841 Hans de Goede
            /* Mark as fully consumed (idle) */
519 060dc841 Hans de Goede
            aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB;
520 060dc841 Hans de Goede
        }
521 060dc841 Hans de Goede
    }
522 060dc841 Hans de Goede
    set_iso_urb(s, ep, aurb);
523 060dc841 Hans de Goede
524 060dc841 Hans de Goede
    return aurb;
525 060dc841 Hans de Goede
}
526 060dc841 Hans de Goede
527 060dc841 Hans de Goede
static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
528 060dc841 Hans de Goede
{
529 060dc841 Hans de Goede
    AsyncURB *aurb;
530 060dc841 Hans de Goede
    int i, ret, killed = 0, free = 1;
531 060dc841 Hans de Goede
532 060dc841 Hans de Goede
    aurb = get_iso_urb(s, ep);
533 060dc841 Hans de Goede
    if (!aurb) {
534 060dc841 Hans de Goede
        return;
535 060dc841 Hans de Goede
    }
536 060dc841 Hans de Goede
537 060dc841 Hans de Goede
    for (i = 0; i < ISO_URB_COUNT; i++) {
538 060dc841 Hans de Goede
        /* in flight? */
539 060dc841 Hans de Goede
        if (aurb[i].iso_frame_idx == -1) {
540 060dc841 Hans de Goede
            ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]);
541 060dc841 Hans de Goede
            if (ret < 0) {
542 060dc841 Hans de Goede
                printf("husb: discard isoc in urb failed errno %d\n", errno);
543 060dc841 Hans de Goede
                free = 0;
544 060dc841 Hans de Goede
                continue;
545 060dc841 Hans de Goede
            }
546 060dc841 Hans de Goede
            killed++;
547 060dc841 Hans de Goede
        }
548 060dc841 Hans de Goede
    }
549 060dc841 Hans de Goede
550 060dc841 Hans de Goede
    /* Make sure any urbs we've killed are reaped before we free them */
551 060dc841 Hans de Goede
    if (killed) {
552 060dc841 Hans de Goede
        async_complete(s);
553 060dc841 Hans de Goede
    }
554 060dc841 Hans de Goede
555 060dc841 Hans de Goede
    for (i = 0; i < ISO_URB_COUNT; i++) {
556 060dc841 Hans de Goede
        qemu_free(aurb[i].urb.buffer);
557 060dc841 Hans de Goede
    }
558 060dc841 Hans de Goede
559 060dc841 Hans de Goede
    if (free)
560 060dc841 Hans de Goede
        qemu_free(aurb);
561 060dc841 Hans de Goede
    else
562 060dc841 Hans de Goede
        printf("husb: leaking iso urbs because of discard failure\n");
563 060dc841 Hans de Goede
    set_iso_urb(s, ep, NULL);
564 bb6d5498 Hans de Goede
    set_iso_urb_idx(s, ep, 0);
565 bb6d5498 Hans de Goede
    clear_iso_started(s, ep);
566 060dc841 Hans de Goede
}
567 060dc841 Hans de Goede
568 060dc841 Hans de Goede
static int urb_status_to_usb_ret(int status)
569 060dc841 Hans de Goede
{
570 060dc841 Hans de Goede
    switch (status) {
571 060dc841 Hans de Goede
    case -EPIPE:
572 060dc841 Hans de Goede
        return USB_RET_STALL;
573 060dc841 Hans de Goede
    default:
574 060dc841 Hans de Goede
        return USB_RET_NAK;
575 060dc841 Hans de Goede
    }
576 060dc841 Hans de Goede
}
577 060dc841 Hans de Goede
578 bb6d5498 Hans de Goede
static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
579 060dc841 Hans de Goede
{
580 060dc841 Hans de Goede
    AsyncURB *aurb;
581 bb6d5498 Hans de Goede
    int i, j, ret, max_packet_size, offset, len = 0;
582 975f2998 Hans de Goede
583 975f2998 Hans de Goede
    max_packet_size = get_max_packet_size(s, p->devep);
584 975f2998 Hans de Goede
    if (max_packet_size == 0)
585 975f2998 Hans de Goede
        return USB_RET_NAK;
586 060dc841 Hans de Goede
587 060dc841 Hans de Goede
    aurb = get_iso_urb(s, p->devep);
588 060dc841 Hans de Goede
    if (!aurb) {
589 bb6d5498 Hans de Goede
        aurb = usb_host_alloc_iso(s, p->devep, in);
590 060dc841 Hans de Goede
    }
591 060dc841 Hans de Goede
592 060dc841 Hans de Goede
    i = get_iso_urb_idx(s, p->devep);
593 060dc841 Hans de Goede
    j = aurb[i].iso_frame_idx;
594 060dc841 Hans de Goede
    if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
595 bb6d5498 Hans de Goede
        if (in) {
596 bb6d5498 Hans de Goede
            /* Check urb status  */
597 bb6d5498 Hans de Goede
            if (aurb[i].urb.status) {
598 bb6d5498 Hans de Goede
                len = urb_status_to_usb_ret(aurb[i].urb.status);
599 bb6d5498 Hans de Goede
                /* Move to the next urb */
600 bb6d5498 Hans de Goede
                aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
601 bb6d5498 Hans de Goede
            /* Check frame status */
602 bb6d5498 Hans de Goede
            } else if (aurb[i].urb.iso_frame_desc[j].status) {
603 bb6d5498 Hans de Goede
                len = urb_status_to_usb_ret(
604 bb6d5498 Hans de Goede
                                        aurb[i].urb.iso_frame_desc[j].status);
605 bb6d5498 Hans de Goede
            /* Check the frame fits */
606 bb6d5498 Hans de Goede
            } else if (aurb[i].urb.iso_frame_desc[j].actual_length > p->len) {
607 bb6d5498 Hans de Goede
                printf("husb: received iso data is larger then packet\n");
608 bb6d5498 Hans de Goede
                len = USB_RET_NAK;
609 bb6d5498 Hans de Goede
            /* All good copy data over */
610 bb6d5498 Hans de Goede
            } else {
611 bb6d5498 Hans de Goede
                len = aurb[i].urb.iso_frame_desc[j].actual_length;
612 bb6d5498 Hans de Goede
                memcpy(p->data,
613 bb6d5498 Hans de Goede
                       aurb[i].urb.buffer +
614 bb6d5498 Hans de Goede
                           j * aurb[i].urb.iso_frame_desc[0].length,
615 bb6d5498 Hans de Goede
                       len);
616 bb6d5498 Hans de Goede
            }
617 060dc841 Hans de Goede
        } else {
618 bb6d5498 Hans de Goede
            len = p->len;
619 bb6d5498 Hans de Goede
            offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->devep);
620 bb6d5498 Hans de Goede
621 bb6d5498 Hans de Goede
            /* Check the frame fits */
622 bb6d5498 Hans de Goede
            if (len > max_packet_size) {
623 bb6d5498 Hans de Goede
                printf("husb: send iso data is larger then max packet size\n");
624 bb6d5498 Hans de Goede
                return USB_RET_NAK;
625 bb6d5498 Hans de Goede
            }
626 bb6d5498 Hans de Goede
627 bb6d5498 Hans de Goede
            /* All good copy data over */
628 bb6d5498 Hans de Goede
            memcpy(aurb[i].urb.buffer + offset, p->data, len);
629 bb6d5498 Hans de Goede
            aurb[i].urb.iso_frame_desc[j].length = len;
630 bb6d5498 Hans de Goede
            offset += len;
631 bb6d5498 Hans de Goede
            set_iso_buffer_used(s, p->devep, offset);
632 bb6d5498 Hans de Goede
633 bb6d5498 Hans de Goede
            /* Start the stream once we have buffered enough data */
634 bb6d5498 Hans de Goede
            if (!is_iso_started(s, p->devep) && i == 1 && j == 8) {
635 bb6d5498 Hans de Goede
                set_iso_started(s, p->devep);
636 bb6d5498 Hans de Goede
            }
637 060dc841 Hans de Goede
        }
638 060dc841 Hans de Goede
        aurb[i].iso_frame_idx++;
639 060dc841 Hans de Goede
        if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
640 060dc841 Hans de Goede
            i = (i + 1) % ISO_URB_COUNT;
641 060dc841 Hans de Goede
            set_iso_urb_idx(s, p->devep, i);
642 060dc841 Hans de Goede
        }
643 bb6d5498 Hans de Goede
    } else {
644 bb6d5498 Hans de Goede
        if (in) {
645 bb6d5498 Hans de Goede
            set_iso_started(s, p->devep);
646 bb6d5498 Hans de Goede
        } else {
647 bb6d5498 Hans de Goede
            DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
648 bb6d5498 Hans de Goede
        }
649 060dc841 Hans de Goede
    }
650 060dc841 Hans de Goede
651 bb6d5498 Hans de Goede
    if (is_iso_started(s, p->devep)) {
652 bb6d5498 Hans de Goede
        /* (Re)-submit all fully consumed / filled urbs */
653 bb6d5498 Hans de Goede
        for (i = 0; i < ISO_URB_COUNT; i++) {
654 bb6d5498 Hans de Goede
            if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
655 bb6d5498 Hans de Goede
                ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
656 bb6d5498 Hans de Goede
                if (ret < 0) {
657 bb6d5498 Hans de Goede
                    printf("husb error submitting iso urb %d: %d\n", i, errno);
658 bb6d5498 Hans de Goede
                    if (!in || len == 0) {
659 bb6d5498 Hans de Goede
                        switch(errno) {
660 bb6d5498 Hans de Goede
                        case ETIMEDOUT:
661 bb6d5498 Hans de Goede
                            len = USB_RET_NAK;
662 0225e254 Stefan Weil
                            break;
663 bb6d5498 Hans de Goede
                        case EPIPE:
664 bb6d5498 Hans de Goede
                        default:
665 bb6d5498 Hans de Goede
                            len = USB_RET_STALL;
666 bb6d5498 Hans de Goede
                        }
667 060dc841 Hans de Goede
                    }
668 bb6d5498 Hans de Goede
                    break;
669 060dc841 Hans de Goede
                }
670 bb6d5498 Hans de Goede
                aurb[i].iso_frame_idx = -1;
671 060dc841 Hans de Goede
            }
672 060dc841 Hans de Goede
        }
673 060dc841 Hans de Goede
    }
674 060dc841 Hans de Goede
675 060dc841 Hans de Goede
    return len;
676 060dc841 Hans de Goede
}
677 060dc841 Hans de Goede
678 446ab128 aliguori
static int usb_host_handle_data(USBHostDevice *s, USBPacket *p)
679 bb36d470 bellard
{
680 64838171 aliguori
    struct usbdevfs_urb *urb;
681 446ab128 aliguori
    AsyncURB *aurb;
682 bb36d470 bellard
    int ret;
683 060dc841 Hans de Goede
    uint8_t ep;
684 b9dc033c balrog
685 a0b5fece Hans de Goede
    if (!is_valid(s, p->devep)) {
686 a0b5fece Hans de Goede
        return USB_RET_NAK;
687 a0b5fece Hans de Goede
    }
688 a0b5fece Hans de Goede
689 2791104c David Ahern
    if (p->pid == USB_TOKEN_IN) {
690 060dc841 Hans de Goede
        ep = p->devep | 0x80;
691 2791104c David Ahern
    } else {
692 060dc841 Hans de Goede
        ep = p->devep;
693 2791104c David Ahern
    }
694 64838171 aliguori
695 64838171 aliguori
    if (is_halted(s, p->devep)) {
696 060dc841 Hans de Goede
        ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &ep);
697 64838171 aliguori
        if (ret < 0) {
698 2791104c David Ahern
            DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n",
699 060dc841 Hans de Goede
                   ep, errno);
700 bb36d470 bellard
            return USB_RET_NAK;
701 bb36d470 bellard
        }
702 64838171 aliguori
        clear_halt(s, p->devep);
703 4d043a09 balrog
    }
704 4d043a09 balrog
705 bb6d5498 Hans de Goede
    if (is_isoc(s, p->devep)) {
706 bb6d5498 Hans de Goede
        return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
707 bb6d5498 Hans de Goede
    }
708 060dc841 Hans de Goede
709 060dc841 Hans de Goede
    aurb = async_alloc();
710 060dc841 Hans de Goede
    aurb->hdev   = s;
711 060dc841 Hans de Goede
    aurb->packet = p;
712 060dc841 Hans de Goede
713 060dc841 Hans de Goede
    urb = &aurb->urb;
714 060dc841 Hans de Goede
715 060dc841 Hans de Goede
    urb->endpoint      = ep;
716 64838171 aliguori
    urb->buffer        = p->data;
717 64838171 aliguori
    urb->buffer_length = p->len;
718 bb6d5498 Hans de Goede
    urb->type          = USBDEVFS_URB_TYPE_BULK;
719 bb6d5498 Hans de Goede
    urb->usercontext   = s;
720 b9dc033c balrog
721 64838171 aliguori
    ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
722 b9dc033c balrog
723 2791104c David Ahern
    DPRINTF("husb: data submit. ep 0x%x len %u aurb %p\n",
724 2791104c David Ahern
            urb->endpoint, p->len, aurb);
725 b9dc033c balrog
726 64838171 aliguori
    if (ret < 0) {
727 d0f2c4c6 malc
        DPRINTF("husb: submit failed. errno %d\n", errno);
728 64838171 aliguori
        async_free(aurb);
729 b9dc033c balrog
730 b9dc033c balrog
        switch(errno) {
731 b9dc033c balrog
        case ETIMEDOUT:
732 b9dc033c balrog
            return USB_RET_NAK;
733 b9dc033c balrog
        case EPIPE:
734 b9dc033c balrog
        default:
735 b9dc033c balrog
            return USB_RET_STALL;
736 b9dc033c balrog
        }
737 b9dc033c balrog
    }
738 64838171 aliguori
739 64838171 aliguori
    usb_defer_packet(p, async_cancel, aurb);
740 b9dc033c balrog
    return USB_RET_ASYNC;
741 b9dc033c balrog
}
742 b9dc033c balrog
743 446ab128 aliguori
static int ctrl_error(void)
744 446ab128 aliguori
{
745 2791104c David Ahern
    if (errno == ETIMEDOUT) {
746 446ab128 aliguori
        return USB_RET_NAK;
747 2791104c David Ahern
    } else {
748 446ab128 aliguori
        return USB_RET_STALL;
749 2791104c David Ahern
    }
750 446ab128 aliguori
}
751 446ab128 aliguori
752 446ab128 aliguori
static int usb_host_set_address(USBHostDevice *s, int addr)
753 446ab128 aliguori
{
754 d0f2c4c6 malc
    DPRINTF("husb: ctrl set addr %u\n", addr);
755 446ab128 aliguori
    s->dev.addr = addr;
756 446ab128 aliguori
    return 0;
757 446ab128 aliguori
}
758 446ab128 aliguori
759 446ab128 aliguori
static int usb_host_set_config(USBHostDevice *s, int config)
760 446ab128 aliguori
{
761 446ab128 aliguori
    usb_host_release_interfaces(s);
762 446ab128 aliguori
763 446ab128 aliguori
    int ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
764 2791104c David Ahern
765 d0f2c4c6 malc
    DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno);
766 2791104c David Ahern
767 2791104c David Ahern
    if (ret < 0) {
768 446ab128 aliguori
        return ctrl_error();
769 2791104c David Ahern
    }
770 446ab128 aliguori
    usb_host_claim_interfaces(s, config);
771 446ab128 aliguori
    return 0;
772 446ab128 aliguori
}
773 446ab128 aliguori
774 446ab128 aliguori
static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
775 446ab128 aliguori
{
776 446ab128 aliguori
    struct usbdevfs_setinterface si;
777 060dc841 Hans de Goede
    int i, ret;
778 060dc841 Hans de Goede
779 3a4854b3 Hans de Goede
    for (i = 1; i <= MAX_ENDPOINTS; i++) {
780 060dc841 Hans de Goede
        if (is_isoc(s, i)) {
781 060dc841 Hans de Goede
            usb_host_stop_n_free_iso(s, i);
782 060dc841 Hans de Goede
        }
783 060dc841 Hans de Goede
    }
784 446ab128 aliguori
785 446ab128 aliguori
    si.interface  = iface;
786 446ab128 aliguori
    si.altsetting = alt;
787 446ab128 aliguori
    ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
788 446ab128 aliguori
789 2791104c David Ahern
    DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
790 2791104c David Ahern
            iface, alt, ret, errno);
791 2791104c David Ahern
792 2791104c David Ahern
    if (ret < 0) {
793 2791104c David Ahern
        return ctrl_error();
794 2791104c David Ahern
    }
795 446ab128 aliguori
    usb_linux_update_endp_table(s);
796 446ab128 aliguori
    return 0;
797 446ab128 aliguori
}
798 446ab128 aliguori
799 446ab128 aliguori
static int usb_host_handle_control(USBHostDevice *s, USBPacket *p)
800 446ab128 aliguori
{
801 446ab128 aliguori
    struct usbdevfs_urb *urb;
802 446ab128 aliguori
    AsyncURB *aurb;
803 446ab128 aliguori
    int ret, value, index;
804 c4c0e236 Jim Paris
    int buffer_len;
805 446ab128 aliguori
806 2791104c David Ahern
    /*
807 446ab128 aliguori
     * Process certain standard device requests.
808 446ab128 aliguori
     * These are infrequent and are processed synchronously.
809 446ab128 aliguori
     */
810 446ab128 aliguori
    value = le16_to_cpu(s->ctrl.req.wValue);
811 446ab128 aliguori
    index = le16_to_cpu(s->ctrl.req.wIndex);
812 446ab128 aliguori
813 d0f2c4c6 malc
    DPRINTF("husb: ctrl type 0x%x req 0x%x val 0x%x index %u len %u\n",
814 2791104c David Ahern
            s->ctrl.req.bRequestType, s->ctrl.req.bRequest, value, index,
815 2791104c David Ahern
            s->ctrl.len);
816 446ab128 aliguori
817 446ab128 aliguori
    if (s->ctrl.req.bRequestType == 0) {
818 446ab128 aliguori
        switch (s->ctrl.req.bRequest) {
819 446ab128 aliguori
        case USB_REQ_SET_ADDRESS:
820 446ab128 aliguori
            return usb_host_set_address(s, value);
821 446ab128 aliguori
822 446ab128 aliguori
        case USB_REQ_SET_CONFIGURATION:
823 446ab128 aliguori
            return usb_host_set_config(s, value & 0xff);
824 446ab128 aliguori
        }
825 446ab128 aliguori
    }
826 446ab128 aliguori
827 446ab128 aliguori
    if (s->ctrl.req.bRequestType == 1 &&
828 2791104c David Ahern
                  s->ctrl.req.bRequest == USB_REQ_SET_INTERFACE) {
829 446ab128 aliguori
        return usb_host_set_interface(s, index, value);
830 2791104c David Ahern
    }
831 446ab128 aliguori
832 446ab128 aliguori
    /* The rest are asynchronous */
833 446ab128 aliguori
834 c4c0e236 Jim Paris
    buffer_len = 8 + s->ctrl.len;
835 c4c0e236 Jim Paris
    if (buffer_len > sizeof(s->ctrl.buffer)) {
836 b2e3b6e9 malc
        fprintf(stderr, "husb: ctrl buffer too small (%u > %zu)\n",
837 b2e3b6e9 malc
                buffer_len, sizeof(s->ctrl.buffer));
838 b2e3b6e9 malc
        return USB_RET_STALL;
839 c4c0e236 Jim Paris
    }
840 c4c0e236 Jim Paris
841 446ab128 aliguori
    aurb = async_alloc();
842 446ab128 aliguori
    aurb->hdev   = s;
843 446ab128 aliguori
    aurb->packet = p;
844 446ab128 aliguori
845 2791104c David Ahern
    /*
846 446ab128 aliguori
     * Setup ctrl transfer.
847 446ab128 aliguori
     *
848 a0102082 Brad Hards
     * s->ctrl is laid out such that data buffer immediately follows
849 446ab128 aliguori
     * 'req' struct which is exactly what usbdevfs expects.
850 2791104c David Ahern
     */
851 446ab128 aliguori
    urb = &aurb->urb;
852 446ab128 aliguori
853 446ab128 aliguori
    urb->type     = USBDEVFS_URB_TYPE_CONTROL;
854 446ab128 aliguori
    urb->endpoint = p->devep;
855 446ab128 aliguori
856 446ab128 aliguori
    urb->buffer        = &s->ctrl.req;
857 c4c0e236 Jim Paris
    urb->buffer_length = buffer_len;
858 446ab128 aliguori
859 446ab128 aliguori
    urb->usercontext = s;
860 446ab128 aliguori
861 446ab128 aliguori
    ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
862 446ab128 aliguori
863 d0f2c4c6 malc
    DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb->buffer_length, aurb);
864 446ab128 aliguori
865 446ab128 aliguori
    if (ret < 0) {
866 d0f2c4c6 malc
        DPRINTF("husb: submit failed. errno %d\n", errno);
867 446ab128 aliguori
        async_free(aurb);
868 446ab128 aliguori
869 446ab128 aliguori
        switch(errno) {
870 446ab128 aliguori
        case ETIMEDOUT:
871 446ab128 aliguori
            return USB_RET_NAK;
872 446ab128 aliguori
        case EPIPE:
873 446ab128 aliguori
        default:
874 446ab128 aliguori
            return USB_RET_STALL;
875 446ab128 aliguori
        }
876 446ab128 aliguori
    }
877 446ab128 aliguori
878 446ab128 aliguori
    usb_defer_packet(p, async_cancel, aurb);
879 446ab128 aliguori
    return USB_RET_ASYNC;
880 446ab128 aliguori
}
881 446ab128 aliguori
882 446ab128 aliguori
static int do_token_setup(USBDevice *dev, USBPacket *p)
883 446ab128 aliguori
{
884 446ab128 aliguori
    USBHostDevice *s = (USBHostDevice *) dev;
885 446ab128 aliguori
    int ret = 0;
886 446ab128 aliguori
887 2791104c David Ahern
    if (p->len != 8) {
888 446ab128 aliguori
        return USB_RET_STALL;
889 2791104c David Ahern
    }
890 2791104c David Ahern
891 446ab128 aliguori
    memcpy(&s->ctrl.req, p->data, 8);
892 446ab128 aliguori
    s->ctrl.len    = le16_to_cpu(s->ctrl.req.wLength);
893 446ab128 aliguori
    s->ctrl.offset = 0;
894 446ab128 aliguori
    s->ctrl.state  = CTRL_STATE_SETUP;
895 446ab128 aliguori
896 446ab128 aliguori
    if (s->ctrl.req.bRequestType & USB_DIR_IN) {
897 446ab128 aliguori
        ret = usb_host_handle_control(s, p);
898 2791104c David Ahern
        if (ret < 0) {
899 446ab128 aliguori
            return ret;
900 2791104c David Ahern
        }
901 446ab128 aliguori
902 2791104c David Ahern
        if (ret < s->ctrl.len) {
903 446ab128 aliguori
            s->ctrl.len = ret;
904 2791104c David Ahern
        }
905 446ab128 aliguori
        s->ctrl.state = CTRL_STATE_DATA;
906 446ab128 aliguori
    } else {
907 2791104c David Ahern
        if (s->ctrl.len == 0) {
908 446ab128 aliguori
            s->ctrl.state = CTRL_STATE_ACK;
909 2791104c David Ahern
        } else {
910 446ab128 aliguori
            s->ctrl.state = CTRL_STATE_DATA;
911 2791104c David Ahern
        }
912 446ab128 aliguori
    }
913 446ab128 aliguori
914 446ab128 aliguori
    return ret;
915 446ab128 aliguori
}
916 446ab128 aliguori
917 446ab128 aliguori
static int do_token_in(USBDevice *dev, USBPacket *p)
918 446ab128 aliguori
{
919 446ab128 aliguori
    USBHostDevice *s = (USBHostDevice *) dev;
920 446ab128 aliguori
    int ret = 0;
921 446ab128 aliguori
922 2791104c David Ahern
    if (p->devep != 0) {
923 446ab128 aliguori
        return usb_host_handle_data(s, p);
924 2791104c David Ahern
    }
925 446ab128 aliguori
926 446ab128 aliguori
    switch(s->ctrl.state) {
927 446ab128 aliguori
    case CTRL_STATE_ACK:
928 446ab128 aliguori
        if (!(s->ctrl.req.bRequestType & USB_DIR_IN)) {
929 446ab128 aliguori
            ret = usb_host_handle_control(s, p);
930 2791104c David Ahern
            if (ret == USB_RET_ASYNC) {
931 446ab128 aliguori
                return USB_RET_ASYNC;
932 2791104c David Ahern
            }
933 446ab128 aliguori
            s->ctrl.state = CTRL_STATE_IDLE;
934 446ab128 aliguori
            return ret > 0 ? 0 : ret;
935 446ab128 aliguori
        }
936 446ab128 aliguori
937 446ab128 aliguori
        return 0;
938 446ab128 aliguori
939 446ab128 aliguori
    case CTRL_STATE_DATA:
940 446ab128 aliguori
        if (s->ctrl.req.bRequestType & USB_DIR_IN) {
941 446ab128 aliguori
            int len = s->ctrl.len - s->ctrl.offset;
942 2791104c David Ahern
            if (len > p->len) {
943 446ab128 aliguori
                len = p->len;
944 2791104c David Ahern
            }
945 446ab128 aliguori
            memcpy(p->data, s->ctrl.buffer + s->ctrl.offset, len);
946 446ab128 aliguori
            s->ctrl.offset += len;
947 2791104c David Ahern
            if (s->ctrl.offset >= s->ctrl.len) {
948 446ab128 aliguori
                s->ctrl.state = CTRL_STATE_ACK;
949 2791104c David Ahern
            }
950 446ab128 aliguori
            return len;
951 446ab128 aliguori
        }
952 446ab128 aliguori
953 446ab128 aliguori
        s->ctrl.state = CTRL_STATE_IDLE;
954 446ab128 aliguori
        return USB_RET_STALL;
955 446ab128 aliguori
956 446ab128 aliguori
    default:
957 446ab128 aliguori
        return USB_RET_STALL;
958 446ab128 aliguori
    }
959 446ab128 aliguori
}
960 446ab128 aliguori
961 446ab128 aliguori
static int do_token_out(USBDevice *dev, USBPacket *p)
962 446ab128 aliguori
{
963 446ab128 aliguori
    USBHostDevice *s = (USBHostDevice *) dev;
964 446ab128 aliguori
965 2791104c David Ahern
    if (p->devep != 0) {
966 446ab128 aliguori
        return usb_host_handle_data(s, p);
967 2791104c David Ahern
    }
968 446ab128 aliguori
969 446ab128 aliguori
    switch(s->ctrl.state) {
970 446ab128 aliguori
    case CTRL_STATE_ACK:
971 446ab128 aliguori
        if (s->ctrl.req.bRequestType & USB_DIR_IN) {
972 446ab128 aliguori
            s->ctrl.state = CTRL_STATE_IDLE;
973 446ab128 aliguori
            /* transfer OK */
974 446ab128 aliguori
        } else {
975 446ab128 aliguori
            /* ignore additional output */
976 446ab128 aliguori
        }
977 446ab128 aliguori
        return 0;
978 446ab128 aliguori
979 446ab128 aliguori
    case CTRL_STATE_DATA:
980 446ab128 aliguori
        if (!(s->ctrl.req.bRequestType & USB_DIR_IN)) {
981 446ab128 aliguori
            int len = s->ctrl.len - s->ctrl.offset;
982 2791104c David Ahern
            if (len > p->len) {
983 446ab128 aliguori
                len = p->len;
984 2791104c David Ahern
            }
985 446ab128 aliguori
            memcpy(s->ctrl.buffer + s->ctrl.offset, p->data, len);
986 446ab128 aliguori
            s->ctrl.offset += len;
987 2791104c David Ahern
            if (s->ctrl.offset >= s->ctrl.len) {
988 446ab128 aliguori
                s->ctrl.state = CTRL_STATE_ACK;
989 2791104c David Ahern
            }
990 446ab128 aliguori
            return len;
991 446ab128 aliguori
        }
992 446ab128 aliguori
993 446ab128 aliguori
        s->ctrl.state = CTRL_STATE_IDLE;
994 446ab128 aliguori
        return USB_RET_STALL;
995 446ab128 aliguori
996 446ab128 aliguori
    default:
997 446ab128 aliguori
        return USB_RET_STALL;
998 446ab128 aliguori
    }
999 446ab128 aliguori
}
1000 446ab128 aliguori
1001 446ab128 aliguori
/*
1002 446ab128 aliguori
 * Packet handler.
1003 446ab128 aliguori
 * Called by the HC (host controller).
1004 446ab128 aliguori
 *
1005 446ab128 aliguori
 * Returns length of the transaction or one of the USB_RET_XXX codes.
1006 446ab128 aliguori
 */
1007 d9cf1578 blueswir1
static int usb_host_handle_packet(USBDevice *s, USBPacket *p)
1008 446ab128 aliguori
{
1009 446ab128 aliguori
    switch(p->pid) {
1010 446ab128 aliguori
    case USB_MSG_ATTACH:
1011 446ab128 aliguori
        s->state = USB_STATE_ATTACHED;
1012 446ab128 aliguori
        return 0;
1013 446ab128 aliguori
1014 446ab128 aliguori
    case USB_MSG_DETACH:
1015 446ab128 aliguori
        s->state = USB_STATE_NOTATTACHED;
1016 446ab128 aliguori
        return 0;
1017 446ab128 aliguori
1018 446ab128 aliguori
    case USB_MSG_RESET:
1019 446ab128 aliguori
        s->remote_wakeup = 0;
1020 446ab128 aliguori
        s->addr = 0;
1021 446ab128 aliguori
        s->state = USB_STATE_DEFAULT;
1022 806b6024 Gerd Hoffmann
        s->info->handle_reset(s);
1023 446ab128 aliguori
        return 0;
1024 446ab128 aliguori
    }
1025 446ab128 aliguori
1026 446ab128 aliguori
    /* Rest of the PIDs must match our address */
1027 2791104c David Ahern
    if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr) {
1028 446ab128 aliguori
        return USB_RET_NODEV;
1029 2791104c David Ahern
    }
1030 446ab128 aliguori
1031 446ab128 aliguori
    switch (p->pid) {
1032 446ab128 aliguori
    case USB_TOKEN_SETUP:
1033 446ab128 aliguori
        return do_token_setup(s, p);
1034 446ab128 aliguori
1035 446ab128 aliguori
    case USB_TOKEN_IN:
1036 446ab128 aliguori
        return do_token_in(s, p);
1037 446ab128 aliguori
1038 446ab128 aliguori
    case USB_TOKEN_OUT:
1039 446ab128 aliguori
        return do_token_out(s, p);
1040 2791104c David Ahern
1041 446ab128 aliguori
    default:
1042 446ab128 aliguori
        return USB_RET_STALL;
1043 446ab128 aliguori
    }
1044 446ab128 aliguori
}
1045 446ab128 aliguori
1046 71d71bbd Hans de Goede
static int usb_linux_get_configuration(USBHostDevice *s)
1047 b9dc033c balrog
{
1048 71d71bbd Hans de Goede
    uint8_t configuration;
1049 e41b3910 pbrook
    struct usb_ctrltransfer ct;
1050 71d71bbd Hans de Goede
    int ret;
1051 b9dc033c balrog
1052 2cc59d8c Hans de Goede
    if (usb_fs_type == USB_FS_SYS) {
1053 2cc59d8c Hans de Goede
        char device_name[32], line[1024];
1054 2cc59d8c Hans de Goede
        int configuration;
1055 2cc59d8c Hans de Goede
1056 2cc59d8c Hans de Goede
        sprintf(device_name, "%d-%d", s->bus_num, s->devpath);
1057 2cc59d8c Hans de Goede
1058 2cc59d8c Hans de Goede
        if (!usb_host_read_file(line, sizeof(line), "bConfigurationValue",
1059 2cc59d8c Hans de Goede
                                device_name)) {
1060 2cc59d8c Hans de Goede
            goto usbdevfs;
1061 2cc59d8c Hans de Goede
        }
1062 2cc59d8c Hans de Goede
        if (sscanf(line, "%d", &configuration) != 1) {
1063 2cc59d8c Hans de Goede
            goto usbdevfs;
1064 2cc59d8c Hans de Goede
        }
1065 2cc59d8c Hans de Goede
        return configuration;
1066 2cc59d8c Hans de Goede
    }
1067 2cc59d8c Hans de Goede
1068 2cc59d8c Hans de Goede
usbdevfs:
1069 b9dc033c balrog
    ct.bRequestType = USB_DIR_IN;
1070 b9dc033c balrog
    ct.bRequest = USB_REQ_GET_CONFIGURATION;
1071 b9dc033c balrog
    ct.wValue = 0;
1072 b9dc033c balrog
    ct.wIndex = 0;
1073 b9dc033c balrog
    ct.wLength = 1;
1074 b9dc033c balrog
    ct.data = &configuration;
1075 b9dc033c balrog
    ct.timeout = 50;
1076 b9dc033c balrog
1077 b9dc033c balrog
    ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
1078 b9dc033c balrog
    if (ret < 0) {
1079 71d71bbd Hans de Goede
        perror("usb_linux_get_configuration");
1080 71d71bbd Hans de Goede
        return -1;
1081 b9dc033c balrog
    }
1082 b9dc033c balrog
1083 b9dc033c balrog
    /* in address state */
1084 2791104c David Ahern
    if (configuration == 0) {
1085 71d71bbd Hans de Goede
        return -1;
1086 2791104c David Ahern
    }
1087 b9dc033c balrog
1088 71d71bbd Hans de Goede
    return configuration;
1089 71d71bbd Hans de Goede
}
1090 71d71bbd Hans de Goede
1091 ed3a328d Hans de Goede
static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
1092 ed3a328d Hans de Goede
    uint8_t configuration, uint8_t interface)
1093 ed3a328d Hans de Goede
{
1094 ed3a328d Hans de Goede
    uint8_t alt_setting;
1095 ed3a328d Hans de Goede
    struct usb_ctrltransfer ct;
1096 ed3a328d Hans de Goede
    int ret;
1097 ed3a328d Hans de Goede
1098 c43831fb Hans de Goede
    if (usb_fs_type == USB_FS_SYS) {
1099 c43831fb Hans de Goede
        char device_name[64], line[1024];
1100 c43831fb Hans de Goede
        int alt_setting;
1101 c43831fb Hans de Goede
1102 c43831fb Hans de Goede
        sprintf(device_name, "%d-%d:%d.%d", s->bus_num, s->devpath,
1103 c43831fb Hans de Goede
                (int)configuration, (int)interface);
1104 c43831fb Hans de Goede
1105 c43831fb Hans de Goede
        if (!usb_host_read_file(line, sizeof(line), "bAlternateSetting",
1106 c43831fb Hans de Goede
                                device_name)) {
1107 c43831fb Hans de Goede
            goto usbdevfs;
1108 c43831fb Hans de Goede
        }
1109 c43831fb Hans de Goede
        if (sscanf(line, "%d", &alt_setting) != 1) {
1110 c43831fb Hans de Goede
            goto usbdevfs;
1111 c43831fb Hans de Goede
        }
1112 c43831fb Hans de Goede
        return alt_setting;
1113 c43831fb Hans de Goede
    }
1114 c43831fb Hans de Goede
1115 c43831fb Hans de Goede
usbdevfs:
1116 ed3a328d Hans de Goede
    ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
1117 ed3a328d Hans de Goede
    ct.bRequest = USB_REQ_GET_INTERFACE;
1118 ed3a328d Hans de Goede
    ct.wValue = 0;
1119 ed3a328d Hans de Goede
    ct.wIndex = interface;
1120 ed3a328d Hans de Goede
    ct.wLength = 1;
1121 ed3a328d Hans de Goede
    ct.data = &alt_setting;
1122 ed3a328d Hans de Goede
    ct.timeout = 50;
1123 ed3a328d Hans de Goede
    ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
1124 ed3a328d Hans de Goede
    if (ret < 0) {
1125 ed3a328d Hans de Goede
        /* Assume alt 0 on error */
1126 ed3a328d Hans de Goede
        return 0;
1127 ed3a328d Hans de Goede
    }
1128 ed3a328d Hans de Goede
1129 ed3a328d Hans de Goede
    return alt_setting;
1130 ed3a328d Hans de Goede
}
1131 ed3a328d Hans de Goede
1132 71d71bbd Hans de Goede
/* returns 1 on problem encountered or 0 for success */
1133 71d71bbd Hans de Goede
static int usb_linux_update_endp_table(USBHostDevice *s)
1134 71d71bbd Hans de Goede
{
1135 71d71bbd Hans de Goede
    uint8_t *descriptors;
1136 71d71bbd Hans de Goede
    uint8_t devep, type, configuration, alt_interface;
1137 ed3a328d Hans de Goede
    int interface, length, i;
1138 71d71bbd Hans de Goede
1139 a0b5fece Hans de Goede
    for (i = 0; i < MAX_ENDPOINTS; i++)
1140 a0b5fece Hans de Goede
        s->endp_table[i].type = INVALID_EP_TYPE;
1141 a0b5fece Hans de Goede
1142 71d71bbd Hans de Goede
    i = usb_linux_get_configuration(s);
1143 71d71bbd Hans de Goede
    if (i < 0)
1144 71d71bbd Hans de Goede
        return 1;
1145 71d71bbd Hans de Goede
    configuration = i;
1146 71d71bbd Hans de Goede
1147 b9dc033c balrog
    /* get the desired configuration, interface, and endpoint descriptors
1148 b9dc033c balrog
     * from device description */
1149 b9dc033c balrog
    descriptors = &s->descr[18];
1150 b9dc033c balrog
    length = s->descr_len - 18;
1151 b9dc033c balrog
    i = 0;
1152 b9dc033c balrog
1153 b9dc033c balrog
    if (descriptors[i + 1] != USB_DT_CONFIG ||
1154 b9dc033c balrog
        descriptors[i + 5] != configuration) {
1155 d0f2c4c6 malc
        DPRINTF("invalid descriptor data - configuration\n");
1156 b9dc033c balrog
        return 1;
1157 b9dc033c balrog
    }
1158 b9dc033c balrog
    i += descriptors[i];
1159 b9dc033c balrog
1160 b9dc033c balrog
    while (i < length) {
1161 b9dc033c balrog
        if (descriptors[i + 1] != USB_DT_INTERFACE ||
1162 b9dc033c balrog
            (descriptors[i + 1] == USB_DT_INTERFACE &&
1163 b9dc033c balrog
             descriptors[i + 4] == 0)) {
1164 b9dc033c balrog
            i += descriptors[i];
1165 b9dc033c balrog
            continue;
1166 b9dc033c balrog
        }
1167 b9dc033c balrog
1168 b9dc033c balrog
        interface = descriptors[i + 2];
1169 ed3a328d Hans de Goede
        alt_interface = usb_linux_get_alt_setting(s, configuration, interface);
1170 b9dc033c balrog
1171 b9dc033c balrog
        /* the current interface descriptor is the active interface
1172 b9dc033c balrog
         * and has endpoints */
1173 b9dc033c balrog
        if (descriptors[i + 3] != alt_interface) {
1174 b9dc033c balrog
            i += descriptors[i];
1175 b9dc033c balrog
            continue;
1176 b9dc033c balrog
        }
1177 b9dc033c balrog
1178 b9dc033c balrog
        /* advance to the endpoints */
1179 2791104c David Ahern
        while (i < length && descriptors[i +1] != USB_DT_ENDPOINT) {
1180 b9dc033c balrog
            i += descriptors[i];
1181 2791104c David Ahern
        }
1182 b9dc033c balrog
1183 b9dc033c balrog
        if (i >= length)
1184 b9dc033c balrog
            break;
1185 b9dc033c balrog
1186 b9dc033c balrog
        while (i < length) {
1187 2791104c David Ahern
            if (descriptors[i + 1] != USB_DT_ENDPOINT) {
1188 b9dc033c balrog
                break;
1189 2791104c David Ahern
            }
1190 b9dc033c balrog
1191 b9dc033c balrog
            devep = descriptors[i + 2];
1192 b9dc033c balrog
            switch (descriptors[i + 3] & 0x3) {
1193 b9dc033c balrog
            case 0x00:
1194 b9dc033c balrog
                type = USBDEVFS_URB_TYPE_CONTROL;
1195 b9dc033c balrog
                break;
1196 b9dc033c balrog
            case 0x01:
1197 b9dc033c balrog
                type = USBDEVFS_URB_TYPE_ISO;
1198 060dc841 Hans de Goede
                s->endp_table[(devep & 0xf) - 1].max_packet_size =
1199 060dc841 Hans de Goede
                    descriptors[i + 4] + (descriptors[i + 5] << 8);
1200 b9dc033c balrog
                break;
1201 b9dc033c balrog
            case 0x02:
1202 b9dc033c balrog
                type = USBDEVFS_URB_TYPE_BULK;
1203 b9dc033c balrog
                break;
1204 b9dc033c balrog
            case 0x03:
1205 b9dc033c balrog
                type = USBDEVFS_URB_TYPE_INTERRUPT;
1206 b9dc033c balrog
                break;
1207 ddbda432 Anthony Liguori
            default:
1208 ddbda432 Anthony Liguori
                DPRINTF("usb_host: malformed endpoint type\n");
1209 ddbda432 Anthony Liguori
                type = USBDEVFS_URB_TYPE_BULK;
1210 b9dc033c balrog
            }
1211 b9dc033c balrog
            s->endp_table[(devep & 0xf) - 1].type = type;
1212 64838171 aliguori
            s->endp_table[(devep & 0xf) - 1].halted = 0;
1213 b9dc033c balrog
1214 b9dc033c balrog
            i += descriptors[i];
1215 b9dc033c balrog
        }
1216 b9dc033c balrog
    }
1217 b9dc033c balrog
    return 0;
1218 b9dc033c balrog
}
1219 b9dc033c balrog
1220 26a9e82a Gerd Hoffmann
static int usb_host_open(USBHostDevice *dev, int bus_num,
1221 0f5160d1 Hans de Goede
                         int addr, int devpath, const char *prod_name)
1222 bb36d470 bellard
{
1223 b9dc033c balrog
    int fd = -1, ret;
1224 bb36d470 bellard
    struct usbdevfs_connectinfo ci;
1225 a594cfbf bellard
    char buf[1024];
1226 1f3870ab aliguori
1227 2791104c David Ahern
    if (dev->fd != -1) {
1228 26a9e82a Gerd Hoffmann
        goto fail;
1229 2791104c David Ahern
    }
1230 64838171 aliguori
    printf("husb: open device %d.%d\n", bus_num, addr);
1231 3b46e624 ths
1232 0f431527 aliguori
    if (!usb_host_device_path) {
1233 0f431527 aliguori
        perror("husb: USB Host Device Path not set");
1234 0f431527 aliguori
        goto fail;
1235 0f431527 aliguori
    }
1236 0f431527 aliguori
    snprintf(buf, sizeof(buf), "%s/%03d/%03d", usb_host_device_path,
1237 a594cfbf bellard
             bus_num, addr);
1238 b9dc033c balrog
    fd = open(buf, O_RDWR | O_NONBLOCK);
1239 bb36d470 bellard
    if (fd < 0) {
1240 a594cfbf bellard
        perror(buf);
1241 1f3870ab aliguori
        goto fail;
1242 bb36d470 bellard
    }
1243 d0f2c4c6 malc
    DPRINTF("husb: opened %s\n", buf);
1244 bb36d470 bellard
1245 806b6024 Gerd Hoffmann
    dev->bus_num = bus_num;
1246 806b6024 Gerd Hoffmann
    dev->addr = addr;
1247 0f5160d1 Hans de Goede
    dev->devpath = devpath;
1248 22f84e73 Gerd Hoffmann
    dev->fd = fd;
1249 806b6024 Gerd Hoffmann
1250 b9dc033c balrog
    /* read the device description */
1251 b9dc033c balrog
    dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
1252 b9dc033c balrog
    if (dev->descr_len <= 0) {
1253 64838171 aliguori
        perror("husb: reading device data failed");
1254 bb36d470 bellard
        goto fail;
1255 bb36d470 bellard
    }
1256 3b46e624 ths
1257 b9dc033c balrog
#ifdef DEBUG
1258 868bfe2b bellard
    {
1259 b9dc033c balrog
        int x;
1260 b9dc033c balrog
        printf("=== begin dumping device descriptor data ===\n");
1261 2791104c David Ahern
        for (x = 0; x < dev->descr_len; x++) {
1262 b9dc033c balrog
            printf("%02x ", dev->descr[x]);
1263 2791104c David Ahern
        }
1264 b9dc033c balrog
        printf("\n=== end dumping device descriptor data ===\n");
1265 bb36d470 bellard
    }
1266 a594cfbf bellard
#endif
1267 a594cfbf bellard
1268 b9dc033c balrog
1269 2791104c David Ahern
    /*
1270 2791104c David Ahern
     * Initial configuration is -1 which makes us claim first
1271 446ab128 aliguori
     * available config. We used to start with 1, which does not
1272 2791104c David Ahern
     * always work. I've seen devices where first config starts
1273 446ab128 aliguori
     * with 2.
1274 446ab128 aliguori
     */
1275 2791104c David Ahern
    if (!usb_host_claim_interfaces(dev, -1)) {
1276 b9dc033c balrog
        goto fail;
1277 2791104c David Ahern
    }
1278 bb36d470 bellard
1279 bb36d470 bellard
    ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
1280 bb36d470 bellard
    if (ret < 0) {
1281 046833ea balrog
        perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
1282 bb36d470 bellard
        goto fail;
1283 bb36d470 bellard
    }
1284 bb36d470 bellard
1285 64838171 aliguori
    printf("husb: grabbed usb device %d.%d\n", bus_num, addr);
1286 bb36d470 bellard
1287 b9dc033c balrog
    ret = usb_linux_update_endp_table(dev);
1288 2791104c David Ahern
    if (ret) {
1289 bb36d470 bellard
        goto fail;
1290 2791104c David Ahern
    }
1291 b9dc033c balrog
1292 2791104c David Ahern
    if (ci.slow) {
1293 bb36d470 bellard
        dev->dev.speed = USB_SPEED_LOW;
1294 2791104c David Ahern
    } else {
1295 bb36d470 bellard
        dev->dev.speed = USB_SPEED_HIGH;
1296 2791104c David Ahern
    }
1297 bb36d470 bellard
1298 2791104c David Ahern
    if (!prod_name || prod_name[0] == '\0') {
1299 0fe6d12e Markus Armbruster
        snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
1300 4b096fc9 aliguori
                 "host:%d.%d", bus_num, addr);
1301 2791104c David Ahern
    } else {
1302 0fe6d12e Markus Armbruster
        pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
1303 4b096fc9 aliguori
                prod_name);
1304 2791104c David Ahern
    }
1305 1f6e24e7 bellard
1306 64838171 aliguori
    /* USB devio uses 'write' flag to check for async completions */
1307 64838171 aliguori
    qemu_set_fd_handler(dev->fd, NULL, async_complete, dev);
1308 1f3870ab aliguori
1309 26a9e82a Gerd Hoffmann
    usb_device_attach(&dev->dev);
1310 26a9e82a Gerd Hoffmann
    return 0;
1311 4b096fc9 aliguori
1312 b9dc033c balrog
fail:
1313 26a9e82a Gerd Hoffmann
    dev->fd = -1;
1314 2791104c David Ahern
    if (fd != -1) {
1315 806b6024 Gerd Hoffmann
        close(fd);
1316 2791104c David Ahern
    }
1317 26a9e82a Gerd Hoffmann
    return -1;
1318 26a9e82a Gerd Hoffmann
}
1319 26a9e82a Gerd Hoffmann
1320 26a9e82a Gerd Hoffmann
static int usb_host_close(USBHostDevice *dev)
1321 26a9e82a Gerd Hoffmann
{
1322 060dc841 Hans de Goede
    int i;
1323 060dc841 Hans de Goede
1324 2791104c David Ahern
    if (dev->fd == -1) {
1325 26a9e82a Gerd Hoffmann
        return -1;
1326 2791104c David Ahern
    }
1327 26a9e82a Gerd Hoffmann
1328 26a9e82a Gerd Hoffmann
    qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
1329 26a9e82a Gerd Hoffmann
    dev->closing = 1;
1330 3a4854b3 Hans de Goede
    for (i = 1; i <= MAX_ENDPOINTS; i++) {
1331 060dc841 Hans de Goede
        if (is_isoc(dev, i)) {
1332 060dc841 Hans de Goede
            usb_host_stop_n_free_iso(dev, i);
1333 060dc841 Hans de Goede
        }
1334 060dc841 Hans de Goede
    }
1335 26a9e82a Gerd Hoffmann
    async_complete(dev);
1336 26a9e82a Gerd Hoffmann
    dev->closing = 0;
1337 26a9e82a Gerd Hoffmann
    usb_device_detach(&dev->dev);
1338 00ff227a Shahar Havivi
    ioctl(dev->fd, USBDEVFS_RESET);
1339 26a9e82a Gerd Hoffmann
    close(dev->fd);
1340 26a9e82a Gerd Hoffmann
    dev->fd = -1;
1341 26a9e82a Gerd Hoffmann
    return 0;
1342 26a9e82a Gerd Hoffmann
}
1343 26a9e82a Gerd Hoffmann
1344 b373a63a Shahar Havivi
static void usb_host_exit_notifier(struct Notifier* n)
1345 b373a63a Shahar Havivi
{
1346 b373a63a Shahar Havivi
    USBHostDevice *s = container_of(n, USBHostDevice, exit);
1347 b373a63a Shahar Havivi
1348 b373a63a Shahar Havivi
    if (s->fd != -1) {
1349 b373a63a Shahar Havivi
        ioctl(s->fd, USBDEVFS_RESET);
1350 b373a63a Shahar Havivi
    }
1351 b373a63a Shahar Havivi
}
1352 b373a63a Shahar Havivi
1353 26a9e82a Gerd Hoffmann
static int usb_host_initfn(USBDevice *dev)
1354 26a9e82a Gerd Hoffmann
{
1355 26a9e82a Gerd Hoffmann
    USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
1356 26a9e82a Gerd Hoffmann
1357 26a9e82a Gerd Hoffmann
    dev->auto_attach = 0;
1358 26a9e82a Gerd Hoffmann
    s->fd = -1;
1359 26a9e82a Gerd Hoffmann
    QTAILQ_INSERT_TAIL(&hostdevs, s, next);
1360 b373a63a Shahar Havivi
    s->exit.notify = usb_host_exit_notifier;
1361 b373a63a Shahar Havivi
    qemu_add_exit_notifier(&s->exit);
1362 26a9e82a Gerd Hoffmann
    usb_host_auto_check(NULL);
1363 26a9e82a Gerd Hoffmann
    return 0;
1364 a594cfbf bellard
}
1365 bb36d470 bellard
1366 806b6024 Gerd Hoffmann
static struct USBDeviceInfo usb_host_dev_info = {
1367 06384698 Markus Armbruster
    .product_desc   = "USB Host Device",
1368 556cd098 Markus Armbruster
    .qdev.name      = "usb-host",
1369 806b6024 Gerd Hoffmann
    .qdev.size      = sizeof(USBHostDevice),
1370 806b6024 Gerd Hoffmann
    .init           = usb_host_initfn,
1371 806b6024 Gerd Hoffmann
    .handle_packet  = usb_host_handle_packet,
1372 806b6024 Gerd Hoffmann
    .handle_reset   = usb_host_handle_reset,
1373 806b6024 Gerd Hoffmann
    .handle_destroy = usb_host_handle_destroy,
1374 26a9e82a Gerd Hoffmann
    .usbdevice_name = "host",
1375 26a9e82a Gerd Hoffmann
    .usbdevice_init = usb_host_device_open,
1376 26a9e82a Gerd Hoffmann
    .qdev.props     = (Property[]) {
1377 26a9e82a Gerd Hoffmann
        DEFINE_PROP_UINT32("hostbus",  USBHostDevice, match.bus_num,    0),
1378 26a9e82a Gerd Hoffmann
        DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr,       0),
1379 26a9e82a Gerd Hoffmann
        DEFINE_PROP_HEX32("vendorid",  USBHostDevice, match.vendor_id,  0),
1380 26a9e82a Gerd Hoffmann
        DEFINE_PROP_HEX32("productid", USBHostDevice, match.product_id, 0),
1381 26a9e82a Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
1382 26a9e82a Gerd Hoffmann
    },
1383 806b6024 Gerd Hoffmann
};
1384 806b6024 Gerd Hoffmann
1385 806b6024 Gerd Hoffmann
static void usb_host_register_devices(void)
1386 806b6024 Gerd Hoffmann
{
1387 806b6024 Gerd Hoffmann
    usb_qdev_register(&usb_host_dev_info);
1388 806b6024 Gerd Hoffmann
}
1389 806b6024 Gerd Hoffmann
device_init(usb_host_register_devices)
1390 806b6024 Gerd Hoffmann
1391 4b096fc9 aliguori
USBDevice *usb_host_device_open(const char *devname)
1392 4b096fc9 aliguori
{
1393 0745eb1e Markus Armbruster
    struct USBAutoFilter filter;
1394 26a9e82a Gerd Hoffmann
    USBDevice *dev;
1395 26a9e82a Gerd Hoffmann
    char *p;
1396 26a9e82a Gerd Hoffmann
1397 556cd098 Markus Armbruster
    dev = usb_create(NULL /* FIXME */, "usb-host");
1398 4b096fc9 aliguori
1399 5d0c5750 aliguori
    if (strstr(devname, "auto:")) {
1400 2791104c David Ahern
        if (parse_filter(devname, &filter) < 0) {
1401 26a9e82a Gerd Hoffmann
            goto fail;
1402 2791104c David Ahern
        }
1403 26a9e82a Gerd Hoffmann
    } else {
1404 26a9e82a Gerd Hoffmann
        if ((p = strchr(devname, '.'))) {
1405 0745eb1e Markus Armbruster
            filter.bus_num    = strtoul(devname, NULL, 0);
1406 0745eb1e Markus Armbruster
            filter.addr       = strtoul(p + 1, NULL, 0);
1407 0745eb1e Markus Armbruster
            filter.vendor_id  = 0;
1408 0745eb1e Markus Armbruster
            filter.product_id = 0;
1409 26a9e82a Gerd Hoffmann
        } else if ((p = strchr(devname, ':'))) {
1410 0745eb1e Markus Armbruster
            filter.bus_num    = 0;
1411 0745eb1e Markus Armbruster
            filter.addr       = 0;
1412 26a9e82a Gerd Hoffmann
            filter.vendor_id  = strtoul(devname, NULL, 16);
1413 0745eb1e Markus Armbruster
            filter.product_id = strtoul(p + 1, NULL, 16);
1414 26a9e82a Gerd Hoffmann
        } else {
1415 26a9e82a Gerd Hoffmann
            goto fail;
1416 26a9e82a Gerd Hoffmann
        }
1417 5d0c5750 aliguori
    }
1418 4b096fc9 aliguori
1419 0745eb1e Markus Armbruster
    qdev_prop_set_uint32(&dev->qdev, "hostbus",   filter.bus_num);
1420 0745eb1e Markus Armbruster
    qdev_prop_set_uint32(&dev->qdev, "hostaddr",  filter.addr);
1421 26a9e82a Gerd Hoffmann
    qdev_prop_set_uint32(&dev->qdev, "vendorid",  filter.vendor_id);
1422 26a9e82a Gerd Hoffmann
    qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id);
1423 beb6f0de Kevin Wolf
    qdev_init_nofail(&dev->qdev);
1424 26a9e82a Gerd Hoffmann
    return dev;
1425 5d0c5750 aliguori
1426 26a9e82a Gerd Hoffmann
fail:
1427 26a9e82a Gerd Hoffmann
    qdev_free(&dev->qdev);
1428 26a9e82a Gerd Hoffmann
    return NULL;
1429 4b096fc9 aliguori
}
1430 5d0c5750 aliguori
1431 5d0c5750 aliguori
int usb_host_device_close(const char *devname)
1432 5d0c5750 aliguori
{
1433 26a9e82a Gerd Hoffmann
#if 0
1434 5d0c5750 aliguori
    char product_name[PRODUCT_NAME_SZ];
1435 5d0c5750 aliguori
    int bus_num, addr;
1436 5d0c5750 aliguori
    USBHostDevice *s;
1437 5d0c5750 aliguori

1438 2791104c David Ahern
    if (strstr(devname, "auto:")) {
1439 5d0c5750 aliguori
        return usb_host_auto_del(devname);
1440 2791104c David Ahern
    }
1441 2791104c David Ahern
    if (usb_host_find_device(&bus_num, &addr, product_name,
1442 2791104c David Ahern
                                    sizeof(product_name), devname) < 0) {
1443 5d0c5750 aliguori
        return -1;
1444 2791104c David Ahern
    }
1445 5d0c5750 aliguori
    s = hostdev_find(bus_num, addr);
1446 5d0c5750 aliguori
    if (s) {
1447 a5d2f727 Gerd Hoffmann
        usb_device_delete_addr(s->bus_num, s->dev.addr);
1448 5d0c5750 aliguori
        return 0;
1449 5d0c5750 aliguori
    }
1450 26a9e82a Gerd Hoffmann
#endif
1451 5d0c5750 aliguori
1452 5d0c5750 aliguori
    return -1;
1453 5d0c5750 aliguori
}
1454 a5d2f727 Gerd Hoffmann
1455 a594cfbf bellard
static int get_tag_value(char *buf, int buf_size,
1456 5fafdf24 ths
                         const char *str, const char *tag,
1457 a594cfbf bellard
                         const char *stopchars)
1458 a594cfbf bellard
{
1459 a594cfbf bellard
    const char *p;
1460 a594cfbf bellard
    char *q;
1461 a594cfbf bellard
    p = strstr(str, tag);
1462 2791104c David Ahern
    if (!p) {
1463 a594cfbf bellard
        return -1;
1464 2791104c David Ahern
    }
1465 a594cfbf bellard
    p += strlen(tag);
1466 2791104c David Ahern
    while (qemu_isspace(*p)) {
1467 a594cfbf bellard
        p++;
1468 2791104c David Ahern
    }
1469 a594cfbf bellard
    q = buf;
1470 a594cfbf bellard
    while (*p != '\0' && !strchr(stopchars, *p)) {
1471 2791104c David Ahern
        if ((q - buf) < (buf_size - 1)) {
1472 a594cfbf bellard
            *q++ = *p;
1473 2791104c David Ahern
        }
1474 a594cfbf bellard
        p++;
1475 a594cfbf bellard
    }
1476 a594cfbf bellard
    *q = '\0';
1477 a594cfbf bellard
    return q - buf;
1478 bb36d470 bellard
}
1479 bb36d470 bellard
1480 0f431527 aliguori
/*
1481 0f431527 aliguori
 * Use /proc/bus/usb/devices or /dev/bus/usb/devices file to determine
1482 0f431527 aliguori
 * host's USB devices. This is legacy support since many distributions
1483 0f431527 aliguori
 * are moving to /sys/bus/usb
1484 0f431527 aliguori
 */
1485 0f431527 aliguori
static int usb_host_scan_dev(void *opaque, USBScanFunc *func)
1486 bb36d470 bellard
{
1487 660f11be Blue Swirl
    FILE *f = NULL;
1488 a594cfbf bellard
    char line[1024];
1489 bb36d470 bellard
    char buf[1024];
1490 a594cfbf bellard
    int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
1491 a594cfbf bellard
    char product_name[512];
1492 0f431527 aliguori
    int ret = 0;
1493 3b46e624 ths
1494 0f431527 aliguori
    if (!usb_host_device_path) {
1495 0f431527 aliguori
        perror("husb: USB Host Device Path not set");
1496 0f431527 aliguori
        goto the_end;
1497 0f431527 aliguori
    }
1498 0f431527 aliguori
    snprintf(line, sizeof(line), "%s/devices", usb_host_device_path);
1499 0f431527 aliguori
    f = fopen(line, "r");
1500 a594cfbf bellard
    if (!f) {
1501 0f431527 aliguori
        perror("husb: cannot open devices file");
1502 0f431527 aliguori
        goto the_end;
1503 a594cfbf bellard
    }
1504 0f431527 aliguori
1505 a594cfbf bellard
    device_count = 0;
1506 a594cfbf bellard
    bus_num = addr = speed = class_id = product_id = vendor_id = 0;
1507 bb36d470 bellard
    for(;;) {
1508 2791104c David Ahern
        if (fgets(line, sizeof(line), f) == NULL) {
1509 bb36d470 bellard
            break;
1510 2791104c David Ahern
        }
1511 2791104c David Ahern
        if (strlen(line) > 0) {
1512 a594cfbf bellard
            line[strlen(line) - 1] = '\0';
1513 2791104c David Ahern
        }
1514 a594cfbf bellard
        if (line[0] == 'T' && line[1] == ':') {
1515 38ca0f6d pbrook
            if (device_count && (vendor_id || product_id)) {
1516 38ca0f6d pbrook
                /* New device.  Add the previously discovered device.  */
1517 0f5160d1 Hans de Goede
                ret = func(opaque, bus_num, addr, 0, class_id, vendor_id,
1518 a594cfbf bellard
                           product_id, product_name, speed);
1519 2791104c David Ahern
                if (ret) {
1520 a594cfbf bellard
                    goto the_end;
1521 2791104c David Ahern
                }
1522 a594cfbf bellard
            }
1523 2791104c David Ahern
            if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0) {
1524 a594cfbf bellard
                goto fail;
1525 2791104c David Ahern
            }
1526 a594cfbf bellard
            bus_num = atoi(buf);
1527 2791104c David Ahern
            if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0) {
1528 a594cfbf bellard
                goto fail;
1529 2791104c David Ahern
            }
1530 a594cfbf bellard
            addr = atoi(buf);
1531 2791104c David Ahern
            if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0) {
1532 a594cfbf bellard
                goto fail;
1533 2791104c David Ahern
            }
1534 2791104c David Ahern
            if (!strcmp(buf, "480")) {
1535 a594cfbf bellard
                speed = USB_SPEED_HIGH;
1536 2791104c David Ahern
            } else if (!strcmp(buf, "1.5")) {
1537 a594cfbf bellard
                speed = USB_SPEED_LOW;
1538 2791104c David Ahern
            } else {
1539 a594cfbf bellard
                speed = USB_SPEED_FULL;
1540 2791104c David Ahern
            }
1541 a594cfbf bellard
            product_name[0] = '\0';
1542 a594cfbf bellard
            class_id = 0xff;
1543 a594cfbf bellard
            device_count++;
1544 a594cfbf bellard
            product_id = 0;
1545 a594cfbf bellard
            vendor_id = 0;
1546 a594cfbf bellard
        } else if (line[0] == 'P' && line[1] == ':') {
1547 2791104c David Ahern
            if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0) {
1548 a594cfbf bellard
                goto fail;
1549 2791104c David Ahern
            }
1550 a594cfbf bellard
            vendor_id = strtoul(buf, NULL, 16);
1551 2791104c David Ahern
            if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0) {
1552 a594cfbf bellard
                goto fail;
1553 2791104c David Ahern
            }
1554 a594cfbf bellard
            product_id = strtoul(buf, NULL, 16);
1555 a594cfbf bellard
        } else if (line[0] == 'S' && line[1] == ':') {
1556 2791104c David Ahern
            if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0) {
1557 a594cfbf bellard
                goto fail;
1558 2791104c David Ahern
            }
1559 a594cfbf bellard
            pstrcpy(product_name, sizeof(product_name), buf);
1560 a594cfbf bellard
        } else if (line[0] == 'D' && line[1] == ':') {
1561 2791104c David Ahern
            if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0) {
1562 a594cfbf bellard
                goto fail;
1563 2791104c David Ahern
            }
1564 a594cfbf bellard
            class_id = strtoul(buf, NULL, 16);
1565 bb36d470 bellard
        }
1566 a594cfbf bellard
    fail: ;
1567 a594cfbf bellard
    }
1568 38ca0f6d pbrook
    if (device_count && (vendor_id || product_id)) {
1569 38ca0f6d pbrook
        /* Add the last device.  */
1570 0f5160d1 Hans de Goede
        ret = func(opaque, bus_num, addr, 0, class_id, vendor_id,
1571 a594cfbf bellard
                   product_id, product_name, speed);
1572 bb36d470 bellard
    }
1573 a594cfbf bellard
 the_end:
1574 2791104c David Ahern
    if (f) {
1575 0f431527 aliguori
        fclose(f);
1576 2791104c David Ahern
    }
1577 0f431527 aliguori
    return ret;
1578 0f431527 aliguori
}
1579 0f431527 aliguori
1580 0f431527 aliguori
/*
1581 0f431527 aliguori
 * Read sys file-system device file
1582 0f431527 aliguori
 *
1583 0f431527 aliguori
 * @line address of buffer to put file contents in
1584 0f431527 aliguori
 * @line_size size of line
1585 0f431527 aliguori
 * @device_file path to device file (printf format string)
1586 0f431527 aliguori
 * @device_name device being opened (inserted into device_file)
1587 0f431527 aliguori
 *
1588 0f431527 aliguori
 * @return 0 failed, 1 succeeded ('line' contains data)
1589 0f431527 aliguori
 */
1590 2791104c David Ahern
static int usb_host_read_file(char *line, size_t line_size,
1591 2791104c David Ahern
                              const char *device_file, const char *device_name)
1592 0f431527 aliguori
{
1593 0f431527 aliguori
    FILE *f;
1594 0f431527 aliguori
    int ret = 0;
1595 0f431527 aliguori
    char filename[PATH_MAX];
1596 0f431527 aliguori
1597 b4e237aa blueswir1
    snprintf(filename, PATH_MAX, USBSYSBUS_PATH "/devices/%s/%s", device_name,
1598 b4e237aa blueswir1
             device_file);
1599 0f431527 aliguori
    f = fopen(filename, "r");
1600 0f431527 aliguori
    if (f) {
1601 9f99cee7 Kirill A. Shutemov
        ret = fgets(line, line_size, f) != NULL;
1602 0f431527 aliguori
        fclose(f);
1603 0f431527 aliguori
    }
1604 0f431527 aliguori
1605 0f431527 aliguori
    return ret;
1606 0f431527 aliguori
}
1607 0f431527 aliguori
1608 0f431527 aliguori
/*
1609 0f431527 aliguori
 * Use /sys/bus/usb/devices/ directory to determine host's USB
1610 0f431527 aliguori
 * devices.
1611 0f431527 aliguori
 *
1612 0f431527 aliguori
 * This code is based on Robert Schiele's original patches posted to
1613 0f431527 aliguori
 * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950
1614 0f431527 aliguori
 */
1615 0f431527 aliguori
static int usb_host_scan_sys(void *opaque, USBScanFunc *func)
1616 0f431527 aliguori
{
1617 660f11be Blue Swirl
    DIR *dir = NULL;
1618 0f431527 aliguori
    char line[1024];
1619 0f5160d1 Hans de Goede
    int bus_num, addr, devpath, speed, class_id, product_id, vendor_id;
1620 0f431527 aliguori
    int ret = 0;
1621 0f431527 aliguori
    char product_name[512];
1622 0f431527 aliguori
    struct dirent *de;
1623 0f431527 aliguori
1624 0f431527 aliguori
    dir = opendir(USBSYSBUS_PATH "/devices");
1625 0f431527 aliguori
    if (!dir) {
1626 0f431527 aliguori
        perror("husb: cannot open devices directory");
1627 0f431527 aliguori
        goto the_end;
1628 0f431527 aliguori
    }
1629 0f431527 aliguori
1630 0f431527 aliguori
    while ((de = readdir(dir))) {
1631 0f431527 aliguori
        if (de->d_name[0] != '.' && !strchr(de->d_name, ':')) {
1632 0f431527 aliguori
            char *tmpstr = de->d_name;
1633 2791104c David Ahern
            if (!strncmp(de->d_name, "usb", 3)) {
1634 0f431527 aliguori
                tmpstr += 3;
1635 2791104c David Ahern
            }
1636 0f5160d1 Hans de Goede
            if (sscanf(tmpstr, "%d-%d", &bus_num, &devpath) < 1) {
1637 0f5160d1 Hans de Goede
                goto the_end;
1638 0f5160d1 Hans de Goede
            }
1639 0f431527 aliguori
1640 2791104c David Ahern
            if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name)) {
1641 0f431527 aliguori
                goto the_end;
1642 2791104c David Ahern
            }
1643 2791104c David Ahern
            if (sscanf(line, "%d", &addr) != 1) {
1644 0f431527 aliguori
                goto the_end;
1645 2791104c David Ahern
            }
1646 b4e237aa blueswir1
            if (!usb_host_read_file(line, sizeof(line), "bDeviceClass",
1647 2791104c David Ahern
                                    de->d_name)) {
1648 0f431527 aliguori
                goto the_end;
1649 2791104c David Ahern
            }
1650 2791104c David Ahern
            if (sscanf(line, "%x", &class_id) != 1) {
1651 0f431527 aliguori
                goto the_end;
1652 2791104c David Ahern
            }
1653 0f431527 aliguori
1654 2791104c David Ahern
            if (!usb_host_read_file(line, sizeof(line), "idVendor",
1655 2791104c David Ahern
                                    de->d_name)) {
1656 0f431527 aliguori
                goto the_end;
1657 2791104c David Ahern
            }
1658 2791104c David Ahern
            if (sscanf(line, "%x", &vendor_id) != 1) {
1659 0f431527 aliguori
                goto the_end;
1660 2791104c David Ahern
            }
1661 b4e237aa blueswir1
            if (!usb_host_read_file(line, sizeof(line), "idProduct",
1662 2791104c David Ahern
                                    de->d_name)) {
1663 0f431527 aliguori
                goto the_end;
1664 2791104c David Ahern
            }
1665 2791104c David Ahern
            if (sscanf(line, "%x", &product_id) != 1) {
1666 0f431527 aliguori
                goto the_end;
1667 2791104c David Ahern
            }
1668 b4e237aa blueswir1
            if (!usb_host_read_file(line, sizeof(line), "product",
1669 b4e237aa blueswir1
                                    de->d_name)) {
1670 0f431527 aliguori
                *product_name = 0;
1671 0f431527 aliguori
            } else {
1672 2791104c David Ahern
                if (strlen(line) > 0) {
1673 0f431527 aliguori
                    line[strlen(line) - 1] = '\0';
1674 2791104c David Ahern
                }
1675 0f431527 aliguori
                pstrcpy(product_name, sizeof(product_name), line);
1676 0f431527 aliguori
            }
1677 0f431527 aliguori
1678 2791104c David Ahern
            if (!usb_host_read_file(line, sizeof(line), "speed", de->d_name)) {
1679 0f431527 aliguori
                goto the_end;
1680 2791104c David Ahern
            }
1681 2791104c David Ahern
            if (!strcmp(line, "480\n")) {
1682 0f431527 aliguori
                speed = USB_SPEED_HIGH;
1683 2791104c David Ahern
            } else if (!strcmp(line, "1.5\n")) {
1684 0f431527 aliguori
                speed = USB_SPEED_LOW;
1685 2791104c David Ahern
            } else {
1686 0f431527 aliguori
                speed = USB_SPEED_FULL;
1687 2791104c David Ahern
            }
1688 0f431527 aliguori
1689 0f5160d1 Hans de Goede
            ret = func(opaque, bus_num, addr, devpath, class_id, vendor_id,
1690 0f431527 aliguori
                       product_id, product_name, speed);
1691 2791104c David Ahern
            if (ret) {
1692 0f431527 aliguori
                goto the_end;
1693 2791104c David Ahern
            }
1694 0f431527 aliguori
        }
1695 0f431527 aliguori
    }
1696 0f431527 aliguori
 the_end:
1697 2791104c David Ahern
    if (dir) {
1698 0f431527 aliguori
        closedir(dir);
1699 2791104c David Ahern
    }
1700 0f431527 aliguori
    return ret;
1701 0f431527 aliguori
}
1702 0f431527 aliguori
1703 0f431527 aliguori
/*
1704 0f431527 aliguori
 * Determine how to access the host's USB devices and call the
1705 0f431527 aliguori
 * specific support function.
1706 0f431527 aliguori
 */
1707 0f431527 aliguori
static int usb_host_scan(void *opaque, USBScanFunc *func)
1708 0f431527 aliguori
{
1709 376253ec aliguori
    Monitor *mon = cur_mon;
1710 660f11be Blue Swirl
    FILE *f = NULL;
1711 660f11be Blue Swirl
    DIR *dir = NULL;
1712 0f431527 aliguori
    int ret = 0;
1713 0f431527 aliguori
    const char *fs_type[] = {"unknown", "proc", "dev", "sys"};
1714 0f431527 aliguori
    char devpath[PATH_MAX];
1715 0f431527 aliguori
1716 0f431527 aliguori
    /* only check the host once */
1717 0f431527 aliguori
    if (!usb_fs_type) {
1718 55496240 Mark McLoughlin
        dir = opendir(USBSYSBUS_PATH "/devices");
1719 55496240 Mark McLoughlin
        if (dir) {
1720 55496240 Mark McLoughlin
            /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
1721 55496240 Mark McLoughlin
            strcpy(devpath, USBDEVBUS_PATH);
1722 55496240 Mark McLoughlin
            usb_fs_type = USB_FS_SYS;
1723 55496240 Mark McLoughlin
            closedir(dir);
1724 d0f2c4c6 malc
            DPRINTF(USBDBG_DEVOPENED, USBSYSBUS_PATH);
1725 55496240 Mark McLoughlin
            goto found_devices;
1726 55496240 Mark McLoughlin
        }
1727 0f431527 aliguori
        f = fopen(USBPROCBUS_PATH "/devices", "r");
1728 0f431527 aliguori
        if (f) {
1729 0f431527 aliguori
            /* devices found in /proc/bus/usb/ */
1730 0f431527 aliguori
            strcpy(devpath, USBPROCBUS_PATH);
1731 0f431527 aliguori
            usb_fs_type = USB_FS_PROC;
1732 0f431527 aliguori
            fclose(f);
1733 d0f2c4c6 malc
            DPRINTF(USBDBG_DEVOPENED, USBPROCBUS_PATH);
1734 f16a0db3 aliguori
            goto found_devices;
1735 0f431527 aliguori
        }
1736 0f431527 aliguori
        /* try additional methods if an access method hasn't been found yet */
1737 0f431527 aliguori
        f = fopen(USBDEVBUS_PATH "/devices", "r");
1738 f16a0db3 aliguori
        if (f) {
1739 0f431527 aliguori
            /* devices found in /dev/bus/usb/ */
1740 0f431527 aliguori
            strcpy(devpath, USBDEVBUS_PATH);
1741 0f431527 aliguori
            usb_fs_type = USB_FS_DEV;
1742 0f431527 aliguori
            fclose(f);
1743 d0f2c4c6 malc
            DPRINTF(USBDBG_DEVOPENED, USBDEVBUS_PATH);
1744 f16a0db3 aliguori
            goto found_devices;
1745 0f431527 aliguori
        }
1746 f16a0db3 aliguori
    found_devices:
1747 22babebb aliguori
        if (!usb_fs_type) {
1748 2791104c David Ahern
            if (mon) {
1749 eba6fe87 Gerd Hoffmann
                monitor_printf(mon, "husb: unable to access USB devices\n");
1750 2791104c David Ahern
            }
1751 f16a0db3 aliguori
            return -ENOENT;
1752 0f431527 aliguori
        }
1753 0f431527 aliguori
1754 0f431527 aliguori
        /* the module setting (used later for opening devices) */
1755 0f431527 aliguori
        usb_host_device_path = qemu_mallocz(strlen(devpath)+1);
1756 1eec614b aliguori
        strcpy(usb_host_device_path, devpath);
1757 2791104c David Ahern
        if (mon) {
1758 eba6fe87 Gerd Hoffmann
            monitor_printf(mon, "husb: using %s file-system with %s\n",
1759 eba6fe87 Gerd Hoffmann
                           fs_type[usb_fs_type], usb_host_device_path);
1760 2791104c David Ahern
        }
1761 0f431527 aliguori
    }
1762 0f431527 aliguori
1763 0f431527 aliguori
    switch (usb_fs_type) {
1764 0f431527 aliguori
    case USB_FS_PROC:
1765 0f431527 aliguori
    case USB_FS_DEV:
1766 0f431527 aliguori
        ret = usb_host_scan_dev(opaque, func);
1767 0f431527 aliguori
        break;
1768 0f431527 aliguori
    case USB_FS_SYS:
1769 0f431527 aliguori
        ret = usb_host_scan_sys(opaque, func);
1770 0f431527 aliguori
        break;
1771 f16a0db3 aliguori
    default:
1772 f16a0db3 aliguori
        ret = -EINVAL;
1773 f16a0db3 aliguori
        break;
1774 0f431527 aliguori
    }
1775 a594cfbf bellard
    return ret;
1776 bb36d470 bellard
}
1777 bb36d470 bellard
1778 4b096fc9 aliguori
static QEMUTimer *usb_auto_timer;
1779 4b096fc9 aliguori
1780 0f5160d1 Hans de Goede
static int usb_host_auto_scan(void *opaque, int bus_num, int addr, int devpath,
1781 26a9e82a Gerd Hoffmann
                              int class_id, int vendor_id, int product_id,
1782 26a9e82a Gerd Hoffmann
                              const char *product_name, int speed)
1783 4b096fc9 aliguori
{
1784 4b096fc9 aliguori
    struct USBAutoFilter *f;
1785 26a9e82a Gerd Hoffmann
    struct USBHostDevice *s;
1786 4b096fc9 aliguori
1787 4b096fc9 aliguori
    /* Ignore hubs */
1788 4b096fc9 aliguori
    if (class_id == 9)
1789 4b096fc9 aliguori
        return 0;
1790 4b096fc9 aliguori
1791 26a9e82a Gerd Hoffmann
    QTAILQ_FOREACH(s, &hostdevs, next) {
1792 26a9e82a Gerd Hoffmann
        f = &s->match;
1793 26a9e82a Gerd Hoffmann
1794 2791104c David Ahern
        if (f->bus_num > 0 && f->bus_num != bus_num) {
1795 4b096fc9 aliguori
            continue;
1796 2791104c David Ahern
        }
1797 2791104c David Ahern
        if (f->addr > 0 && f->addr != addr) {
1798 4b096fc9 aliguori
            continue;
1799 2791104c David Ahern
        }
1800 4b096fc9 aliguori
1801 2791104c David Ahern
        if (f->vendor_id > 0 && f->vendor_id != vendor_id) {
1802 4b096fc9 aliguori
            continue;
1803 2791104c David Ahern
        }
1804 4b096fc9 aliguori
1805 2791104c David Ahern
        if (f->product_id > 0 && f->product_id != product_id) {
1806 4b096fc9 aliguori
            continue;
1807 2791104c David Ahern
        }
1808 4b096fc9 aliguori
        /* We got a match */
1809 4b096fc9 aliguori
1810 33e66b86 Markus Armbruster
        /* Already attached ? */
1811 2791104c David Ahern
        if (s->fd != -1) {
1812 4b096fc9 aliguori
            return 0;
1813 2791104c David Ahern
        }
1814 d0f2c4c6 malc
        DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr);
1815 4b096fc9 aliguori
1816 0f5160d1 Hans de Goede
        usb_host_open(s, bus_num, addr, devpath, product_name);
1817 4b096fc9 aliguori
    }
1818 4b096fc9 aliguori
1819 4b096fc9 aliguori
    return 0;
1820 4b096fc9 aliguori
}
1821 4b096fc9 aliguori
1822 26a9e82a Gerd Hoffmann
static void usb_host_auto_check(void *unused)
1823 4b096fc9 aliguori
{
1824 26a9e82a Gerd Hoffmann
    struct USBHostDevice *s;
1825 26a9e82a Gerd Hoffmann
    int unconnected = 0;
1826 26a9e82a Gerd Hoffmann
1827 4b096fc9 aliguori
    usb_host_scan(NULL, usb_host_auto_scan);
1828 26a9e82a Gerd Hoffmann
1829 26a9e82a Gerd Hoffmann
    QTAILQ_FOREACH(s, &hostdevs, next) {
1830 2791104c David Ahern
        if (s->fd == -1) {
1831 26a9e82a Gerd Hoffmann
            unconnected++;
1832 2791104c David Ahern
        }
1833 26a9e82a Gerd Hoffmann
    }
1834 26a9e82a Gerd Hoffmann
1835 26a9e82a Gerd Hoffmann
    if (unconnected == 0) {
1836 26a9e82a Gerd Hoffmann
        /* nothing to watch */
1837 2791104c David Ahern
        if (usb_auto_timer) {
1838 26a9e82a Gerd Hoffmann
            qemu_del_timer(usb_auto_timer);
1839 2791104c David Ahern
        }
1840 26a9e82a Gerd Hoffmann
        return;
1841 26a9e82a Gerd Hoffmann
    }
1842 26a9e82a Gerd Hoffmann
1843 26a9e82a Gerd Hoffmann
    if (!usb_auto_timer) {
1844 7bd427d8 Paolo Bonzini
        usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL);
1845 2791104c David Ahern
        if (!usb_auto_timer) {
1846 26a9e82a Gerd Hoffmann
            return;
1847 2791104c David Ahern
        }
1848 26a9e82a Gerd Hoffmann
    }
1849 7bd427d8 Paolo Bonzini
    qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000);
1850 4b096fc9 aliguori
}
1851 4b096fc9 aliguori
1852 4b096fc9 aliguori
/*
1853 5d0c5750 aliguori
 * Autoconnect filter
1854 5d0c5750 aliguori
 * Format:
1855 5d0c5750 aliguori
 *    auto:bus:dev[:vid:pid]
1856 5d0c5750 aliguori
 *    auto:bus.dev[:vid:pid]
1857 5d0c5750 aliguori
 *
1858 5d0c5750 aliguori
 *    bus  - bus number    (dec, * means any)
1859 5d0c5750 aliguori
 *    dev  - device number (dec, * means any)
1860 5d0c5750 aliguori
 *    vid  - vendor id     (hex, * means any)
1861 5d0c5750 aliguori
 *    pid  - product id    (hex, * means any)
1862 5d0c5750 aliguori
 *
1863 5d0c5750 aliguori
 *    See 'lsusb' output.
1864 4b096fc9 aliguori
 */
1865 5d0c5750 aliguori
static int parse_filter(const char *spec, struct USBAutoFilter *f)
1866 4b096fc9 aliguori
{
1867 5d0c5750 aliguori
    enum { BUS, DEV, VID, PID, DONE };
1868 5d0c5750 aliguori
    const char *p = spec;
1869 5d0c5750 aliguori
    int i;
1870 5d0c5750 aliguori
1871 0745eb1e Markus Armbruster
    f->bus_num    = 0;
1872 0745eb1e Markus Armbruster
    f->addr       = 0;
1873 0745eb1e Markus Armbruster
    f->vendor_id  = 0;
1874 0745eb1e Markus Armbruster
    f->product_id = 0;
1875 5d0c5750 aliguori
1876 5d0c5750 aliguori
    for (i = BUS; i < DONE; i++) {
1877 2791104c David Ahern
        p = strpbrk(p, ":.");
1878 2791104c David Ahern
        if (!p) {
1879 2791104c David Ahern
            break;
1880 2791104c David Ahern
        }
1881 5d0c5750 aliguori
        p++;
1882 5d0c5750 aliguori
1883 2791104c David Ahern
        if (*p == '*') {
1884 2791104c David Ahern
            continue;
1885 2791104c David Ahern
        }
1886 5d0c5750 aliguori
        switch(i) {
1887 5d0c5750 aliguori
        case BUS: f->bus_num = strtol(p, NULL, 10);    break;
1888 5d0c5750 aliguori
        case DEV: f->addr    = strtol(p, NULL, 10);    break;
1889 5d0c5750 aliguori
        case VID: f->vendor_id  = strtol(p, NULL, 16); break;
1890 5d0c5750 aliguori
        case PID: f->product_id = strtol(p, NULL, 16); break;
1891 5d0c5750 aliguori
        }
1892 5d0c5750 aliguori
    }
1893 5d0c5750 aliguori
1894 5d0c5750 aliguori
    if (i < DEV) {
1895 5d0c5750 aliguori
        fprintf(stderr, "husb: invalid auto filter spec %s\n", spec);
1896 5d0c5750 aliguori
        return -1;
1897 5d0c5750 aliguori
    }
1898 5d0c5750 aliguori
1899 5d0c5750 aliguori
    return 0;
1900 5d0c5750 aliguori
}
1901 5d0c5750 aliguori
1902 a594cfbf bellard
/**********************/
1903 a594cfbf bellard
/* USB host device info */
1904 a594cfbf bellard
1905 a594cfbf bellard
struct usb_class_info {
1906 a594cfbf bellard
    int class;
1907 a594cfbf bellard
    const char *class_name;
1908 a594cfbf bellard
};
1909 a594cfbf bellard
1910 a594cfbf bellard
static const struct usb_class_info usb_class_info[] = {
1911 a594cfbf bellard
    { USB_CLASS_AUDIO, "Audio"},
1912 a594cfbf bellard
    { USB_CLASS_COMM, "Communication"},
1913 a594cfbf bellard
    { USB_CLASS_HID, "HID"},
1914 a594cfbf bellard
    { USB_CLASS_HUB, "Hub" },
1915 a594cfbf bellard
    { USB_CLASS_PHYSICAL, "Physical" },
1916 a594cfbf bellard
    { USB_CLASS_PRINTER, "Printer" },
1917 a594cfbf bellard
    { USB_CLASS_MASS_STORAGE, "Storage" },
1918 a594cfbf bellard
    { USB_CLASS_CDC_DATA, "Data" },
1919 a594cfbf bellard
    { USB_CLASS_APP_SPEC, "Application Specific" },
1920 a594cfbf bellard
    { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
1921 a594cfbf bellard
    { USB_CLASS_STILL_IMAGE, "Still Image" },
1922 b9dc033c balrog
    { USB_CLASS_CSCID, "Smart Card" },
1923 a594cfbf bellard
    { USB_CLASS_CONTENT_SEC, "Content Security" },
1924 a594cfbf bellard
    { -1, NULL }
1925 a594cfbf bellard
};
1926 a594cfbf bellard
1927 a594cfbf bellard
static const char *usb_class_str(uint8_t class)
1928 bb36d470 bellard
{
1929 a594cfbf bellard
    const struct usb_class_info *p;
1930 a594cfbf bellard
    for(p = usb_class_info; p->class != -1; p++) {
1931 2791104c David Ahern
        if (p->class == class) {
1932 a594cfbf bellard
            break;
1933 2791104c David Ahern
        }
1934 bb36d470 bellard
    }
1935 a594cfbf bellard
    return p->class_name;
1936 a594cfbf bellard
}
1937 a594cfbf bellard
1938 179da8af Blue Swirl
static void usb_info_device(Monitor *mon, int bus_num, int addr, int class_id,
1939 9596ebb7 pbrook
                            int vendor_id, int product_id,
1940 9596ebb7 pbrook
                            const char *product_name,
1941 9596ebb7 pbrook
                            int speed)
1942 a594cfbf bellard
{
1943 a594cfbf bellard
    const char *class_str, *speed_str;
1944 a594cfbf bellard
1945 a594cfbf bellard
    switch(speed) {
1946 5fafdf24 ths
    case USB_SPEED_LOW:
1947 5fafdf24 ths
        speed_str = "1.5";
1948 a594cfbf bellard
        break;
1949 5fafdf24 ths
    case USB_SPEED_FULL:
1950 5fafdf24 ths
        speed_str = "12";
1951 a594cfbf bellard
        break;
1952 5fafdf24 ths
    case USB_SPEED_HIGH:
1953 5fafdf24 ths
        speed_str = "480";
1954 a594cfbf bellard
        break;
1955 a594cfbf bellard
    default:
1956 5fafdf24 ths
        speed_str = "?";
1957 a594cfbf bellard
        break;
1958 a594cfbf bellard
    }
1959 a594cfbf bellard
1960 376253ec aliguori
    monitor_printf(mon, "  Device %d.%d, speed %s Mb/s\n",
1961 a594cfbf bellard
                bus_num, addr, speed_str);
1962 a594cfbf bellard
    class_str = usb_class_str(class_id);
1963 2791104c David Ahern
    if (class_str) {
1964 376253ec aliguori
        monitor_printf(mon, "    %s:", class_str);
1965 2791104c David Ahern
    } else {
1966 376253ec aliguori
        monitor_printf(mon, "    Class %02x:", class_id);
1967 2791104c David Ahern
    }
1968 376253ec aliguori
    monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
1969 2791104c David Ahern
    if (product_name[0] != '\0') {
1970 376253ec aliguori
        monitor_printf(mon, ", %s", product_name);
1971 2791104c David Ahern
    }
1972 376253ec aliguori
    monitor_printf(mon, "\n");
1973 a594cfbf bellard
}
1974 a594cfbf bellard
1975 5fafdf24 ths
static int usb_host_info_device(void *opaque, int bus_num, int addr,
1976 0f5160d1 Hans de Goede
                                int devpath, int class_id,
1977 5fafdf24 ths
                                int vendor_id, int product_id,
1978 a594cfbf bellard
                                const char *product_name,
1979 a594cfbf bellard
                                int speed)
1980 a594cfbf bellard
{
1981 179da8af Blue Swirl
    Monitor *mon = opaque;
1982 179da8af Blue Swirl
1983 179da8af Blue Swirl
    usb_info_device(mon, bus_num, addr, class_id, vendor_id, product_id,
1984 a594cfbf bellard
                    product_name, speed);
1985 a594cfbf bellard
    return 0;
1986 a594cfbf bellard
}
1987 a594cfbf bellard
1988 ac4ffb5a aliguori
static void dec2str(int val, char *str, size_t size)
1989 5d0c5750 aliguori
{
1990 2791104c David Ahern
    if (val == 0) {
1991 ac4ffb5a aliguori
        snprintf(str, size, "*");
1992 2791104c David Ahern
    } else {
1993 2791104c David Ahern
        snprintf(str, size, "%d", val);
1994 2791104c David Ahern
    }
1995 5d0c5750 aliguori
}
1996 5d0c5750 aliguori
1997 ac4ffb5a aliguori
static void hex2str(int val, char *str, size_t size)
1998 5d0c5750 aliguori
{
1999 2791104c David Ahern
    if (val == 0) {
2000 ac4ffb5a aliguori
        snprintf(str, size, "*");
2001 2791104c David Ahern
    } else {
2002 26a9e82a Gerd Hoffmann
        snprintf(str, size, "%04x", val);
2003 2791104c David Ahern
    }
2004 5d0c5750 aliguori
}
2005 5d0c5750 aliguori
2006 376253ec aliguori
void usb_host_info(Monitor *mon)
2007 a594cfbf bellard
{
2008 5d0c5750 aliguori
    struct USBAutoFilter *f;
2009 26a9e82a Gerd Hoffmann
    struct USBHostDevice *s;
2010 5d0c5750 aliguori
2011 179da8af Blue Swirl
    usb_host_scan(mon, usb_host_info_device);
2012 5d0c5750 aliguori
2013 2791104c David Ahern
    if (QTAILQ_EMPTY(&hostdevs)) {
2014 26a9e82a Gerd Hoffmann
        return;
2015 2791104c David Ahern
    }
2016 2791104c David Ahern
2017 26a9e82a Gerd Hoffmann
    monitor_printf(mon, "  Auto filters:\n");
2018 26a9e82a Gerd Hoffmann
    QTAILQ_FOREACH(s, &hostdevs, next) {
2019 5d0c5750 aliguori
        char bus[10], addr[10], vid[10], pid[10];
2020 26a9e82a Gerd Hoffmann
        f = &s->match;
2021 ac4ffb5a aliguori
        dec2str(f->bus_num, bus, sizeof(bus));
2022 ac4ffb5a aliguori
        dec2str(f->addr, addr, sizeof(addr));
2023 ac4ffb5a aliguori
        hex2str(f->vendor_id, vid, sizeof(vid));
2024 ac4ffb5a aliguori
        hex2str(f->product_id, pid, sizeof(pid));
2025 376253ec aliguori
        monitor_printf(mon, "    Device %s.%s ID %s:%s\n",
2026 376253ec aliguori
                       bus, addr, vid, pid);
2027 5d0c5750 aliguori
    }
2028 bb36d470 bellard
}