blob: a9030238476ddc40b46357cce44953c3b74ce6ac [file] [log] [blame]
bellardbb36d472005-11-05 14:22:28 +00001/*
2 * Linux host USB redirector
3 *
4 * Copyright (c) 2005 Fabrice Bellard
ths5fafdf22007-09-16 21:08:06 +00005 *
aliguori64838172008-08-21 19:31:10 +00006 * Copyright (c) 2008 Max Krasnyansky
7 * Support for host device auto connect & disconnect
aliguori5d0c5752008-09-14 01:07:41 +00008 * Major rewrite to support fully async operation
aliguori4b096fc2008-08-21 19:28:55 +00009 *
aliguori0f431522008-10-07 20:06:37 +000010 * Copyright 2008 TJ <linux@tjworld.net>
11 * Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition
12 * to the legacy /proc/bus/usb USB device discovery and handling
13 *
bellardbb36d472005-11-05 14:22:28 +000014 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this software and associated documentation files (the "Software"), to deal
16 * in the Software without restriction, including without limitation the rights
17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 * copies of the Software, and to permit persons to whom the Software is
19 * furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 * THE SOFTWARE.
31 */
aliguori446ab122008-09-14 01:06:09 +000032
pbrook87ecb682007-11-17 17:14:51 +000033#include "qemu-common.h"
aliguori1f3870a2008-08-21 19:27:48 +000034#include "qemu-timer.h"
aliguori376253e2009-03-05 23:01:23 +000035#include "monitor.h"
Shahar Havivib373a632010-06-16 15:16:11 +030036#include "sysemu.h"
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +020037#include "trace.h"
bellardbb36d472005-11-05 14:22:28 +000038
bellardbb36d472005-11-05 14:22:28 +000039#include <dirent.h>
40#include <sys/ioctl.h>
bellardbb36d472005-11-05 14:22:28 +000041
aliguori446ab122008-09-14 01:06:09 +000042#include <linux/usbdevice_fs.h>
43#include <linux/version.h>
44#include "hw/usb.h"
bellardbb36d472005-11-05 14:22:28 +000045
blueswir1d9cf1572008-09-15 14:57:11 +000046/* We redefine it to avoid version problems */
47struct usb_ctrltransfer {
48 uint8_t bRequestType;
49 uint8_t bRequest;
50 uint16_t wValue;
51 uint16_t wIndex;
52 uint16_t wLength;
53 uint32_t timeout;
54 void *data;
55};
56
Gerd Hoffmann5557d822011-05-10 11:43:57 +020057typedef int USBScanFunc(void *opaque, int bus_num, int addr, char *port,
Hans de Goede0f5160d2010-11-10 10:06:23 +010058 int class_id, int vendor_id, int product_id,
bellarda594cfb2005-11-06 16:13:29 +000059 const char *product_name, int speed);
Gerd Hoffmann26a9e822009-10-26 15:56:50 +010060
Markus Armbruster0745eb12009-11-27 13:05:53 +010061//#define DEBUG
aliguori64838172008-08-21 19:31:10 +000062
63#ifdef DEBUG
malcd0f2c4c2010-02-07 02:03:50 +030064#define DPRINTF printf
aliguori64838172008-08-21 19:31:10 +000065#else
malcd0f2c4c2010-02-07 02:03:50 +030066#define DPRINTF(...)
aliguori64838172008-08-21 19:31:10 +000067#endif
bellardbb36d472005-11-05 14:22:28 +000068
blueswir15be8e1f2008-10-25 11:47:20 +000069#define USBDBG_DEVOPENED "husb: opened %s/devices\n"
70
aliguori0f431522008-10-07 20:06:37 +000071#define USBPROCBUS_PATH "/proc/bus/usb"
bellard1f6e24e2006-06-26 21:00:51 +000072#define PRODUCT_NAME_SZ 32
Hans de Goede3a4854b2010-11-26 15:02:16 +010073#define MAX_ENDPOINTS 15
Gerd Hoffmann5557d822011-05-10 11:43:57 +020074#define MAX_PORTLEN 16
aliguori0f431522008-10-07 20:06:37 +000075#define USBDEVBUS_PATH "/dev/bus/usb"
76#define USBSYSBUS_PATH "/sys/bus/usb"
77
78static char *usb_host_device_path;
79
80#define USB_FS_NONE 0
81#define USB_FS_PROC 1
82#define USB_FS_DEV 2
83#define USB_FS_SYS 3
84
85static int usb_fs_type;
bellardbb36d472005-11-05 14:22:28 +000086
balrogb9dc0332007-10-04 22:47:34 +000087/* endpoint association data */
Hans de Goede060dc842010-11-26 11:41:08 +010088#define ISO_FRAME_DESC_PER_URB 32
Hans de Goedea0b5fec2010-11-26 14:56:17 +010089#define INVALID_EP_TYPE 255
Hans de Goede060dc842010-11-26 11:41:08 +010090
Gerd Hoffmann71138532011-05-16 10:21:51 +020091/* devio.c limits single requests to 16k */
92#define MAX_USBFS_BUFFER_SIZE 16384
93
Hans de Goede060dc842010-11-26 11:41:08 +010094typedef struct AsyncURB AsyncURB;
95
balrogb9dc0332007-10-04 22:47:34 +000096struct endp_data {
97 uint8_t type;
aliguori64838172008-08-21 19:31:10 +000098 uint8_t halted;
Hans de Goedebb6d5492010-11-26 19:11:03 +010099 uint8_t iso_started;
Hans de Goede060dc842010-11-26 11:41:08 +0100100 AsyncURB *iso_urb;
101 int iso_urb_idx;
Hans de Goedebb6d5492010-11-26 19:11:03 +0100102 int iso_buffer_used;
Hans de Goede060dc842010-11-26 11:41:08 +0100103 int max_packet_size;
Gerd Hoffmann82887262011-06-10 14:00:24 +0200104 int inflight;
balrogb9dc0332007-10-04 22:47:34 +0000105};
106
Gerd Hoffmann26a9e822009-10-26 15:56:50 +0100107struct USBAutoFilter {
108 uint32_t bus_num;
109 uint32_t addr;
Gerd Hoffmann9056a292011-05-10 12:07:42 +0200110 char *port;
Gerd Hoffmann26a9e822009-10-26 15:56:50 +0100111 uint32_t vendor_id;
112 uint32_t product_id;
113};
114
bellardbb36d472005-11-05 14:22:28 +0000115typedef struct USBHostDevice {
116 USBDevice dev;
aliguori64838172008-08-21 19:31:10 +0000117 int fd;
118
Hans de Goedef8ddbfb2011-05-31 11:35:26 +0200119 uint8_t descr[8192];
aliguori64838172008-08-21 19:31:10 +0000120 int descr_len;
121 int configuration;
aliguori446ab122008-09-14 01:06:09 +0000122 int ninterfaces;
aliguori24772c12008-08-21 19:31:52 +0000123 int closing;
Gerd Hoffmannb81bcd82011-06-10 14:03:56 +0200124 uint32_t iso_urb_count;
Shahar Havivib373a632010-06-16 15:16:11 +0300125 Notifier exit;
aliguori64838172008-08-21 19:31:10 +0000126
balrogb9dc0332007-10-04 22:47:34 +0000127 struct endp_data endp_table[MAX_ENDPOINTS];
Gerd Hoffmann7a8fc832011-05-16 09:13:05 +0200128 QLIST_HEAD(, AsyncURB) aurbs;
aliguori4b096fc2008-08-21 19:28:55 +0000129
aliguori4b096fc2008-08-21 19:28:55 +0000130 /* Host side address */
131 int bus_num;
132 int addr;
Gerd Hoffmann5557d822011-05-10 11:43:57 +0200133 char port[MAX_PORTLEN];
Gerd Hoffmann26a9e822009-10-26 15:56:50 +0100134 struct USBAutoFilter match;
Gerd Hoffmann3ee886c2011-08-24 13:45:06 +0200135 int seen, errcount;
aliguori4b096fc2008-08-21 19:28:55 +0000136
Gerd Hoffmann26a9e822009-10-26 15:56:50 +0100137 QTAILQ_ENTRY(USBHostDevice) next;
bellardbb36d472005-11-05 14:22:28 +0000138} USBHostDevice;
139
Gerd Hoffmann26a9e822009-10-26 15:56:50 +0100140static QTAILQ_HEAD(, USBHostDevice) hostdevs = QTAILQ_HEAD_INITIALIZER(hostdevs);
141
142static int usb_host_close(USBHostDevice *dev);
143static int parse_filter(const char *spec, struct USBAutoFilter *f);
144static void usb_host_auto_check(void *unused);
Hans de Goede2cc59d82010-11-10 10:06:25 +0100145static int usb_host_read_file(char *line, size_t line_size,
146 const char *device_file, const char *device_name);
Gerd Hoffmann9b87e192011-08-24 10:55:40 +0200147static int usb_linux_update_endp_table(USBHostDevice *s);
Gerd Hoffmann26a9e822009-10-26 15:56:50 +0100148
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200149static struct endp_data *get_endp(USBHostDevice *s, int ep)
150{
151 return s->endp_table + ep - 1;
152}
153
aliguori64838172008-08-21 19:31:10 +0000154static int is_isoc(USBHostDevice *s, int ep)
155{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200156 return get_endp(s, ep)->type == USBDEVFS_URB_TYPE_ISO;
aliguori64838172008-08-21 19:31:10 +0000157}
158
Hans de Goedea0b5fec2010-11-26 14:56:17 +0100159static int is_valid(USBHostDevice *s, int ep)
160{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200161 return get_endp(s, ep)->type != INVALID_EP_TYPE;
Hans de Goedea0b5fec2010-11-26 14:56:17 +0100162}
163
aliguori64838172008-08-21 19:31:10 +0000164static int is_halted(USBHostDevice *s, int ep)
165{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200166 return get_endp(s, ep)->halted;
aliguori64838172008-08-21 19:31:10 +0000167}
168
169static void clear_halt(USBHostDevice *s, int ep)
170{
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200171 trace_usb_host_ep_clear_halt(s->bus_num, s->addr, ep);
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200172 get_endp(s, ep)->halted = 0;
aliguori64838172008-08-21 19:31:10 +0000173}
174
175static void set_halt(USBHostDevice *s, int ep)
176{
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200177 trace_usb_host_ep_set_halt(s->bus_num, s->addr, ep);
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200178 get_endp(s, ep)->halted = 1;
aliguori64838172008-08-21 19:31:10 +0000179}
180
Hans de Goedebb6d5492010-11-26 19:11:03 +0100181static int is_iso_started(USBHostDevice *s, int ep)
182{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200183 return get_endp(s, ep)->iso_started;
Hans de Goedebb6d5492010-11-26 19:11:03 +0100184}
185
186static void clear_iso_started(USBHostDevice *s, int ep)
187{
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200188 trace_usb_host_ep_stop_iso(s->bus_num, s->addr, ep);
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200189 get_endp(s, ep)->iso_started = 0;
Hans de Goedebb6d5492010-11-26 19:11:03 +0100190}
191
192static void set_iso_started(USBHostDevice *s, int ep)
193{
Gerd Hoffmann82887262011-06-10 14:00:24 +0200194 struct endp_data *e = get_endp(s, ep);
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200195
196 trace_usb_host_ep_start_iso(s->bus_num, s->addr, ep);
Gerd Hoffmann82887262011-06-10 14:00:24 +0200197 if (!e->iso_started) {
198 e->iso_started = 1;
199 e->inflight = 0;
200 }
201}
202
203static int change_iso_inflight(USBHostDevice *s, int ep, int value)
204{
205 struct endp_data *e = get_endp(s, ep);
206
207 e->inflight += value;
208 return e->inflight;
Hans de Goedebb6d5492010-11-26 19:11:03 +0100209}
210
Hans de Goede060dc842010-11-26 11:41:08 +0100211static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb)
212{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200213 get_endp(s, ep)->iso_urb = iso_urb;
Hans de Goede060dc842010-11-26 11:41:08 +0100214}
215
216static AsyncURB *get_iso_urb(USBHostDevice *s, int ep)
217{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200218 return get_endp(s, ep)->iso_urb;
Hans de Goede060dc842010-11-26 11:41:08 +0100219}
220
221static void set_iso_urb_idx(USBHostDevice *s, int ep, int i)
222{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200223 get_endp(s, ep)->iso_urb_idx = i;
Hans de Goede060dc842010-11-26 11:41:08 +0100224}
225
226static int get_iso_urb_idx(USBHostDevice *s, int ep)
227{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200228 return get_endp(s, ep)->iso_urb_idx;
Hans de Goede060dc842010-11-26 11:41:08 +0100229}
230
Hans de Goedebb6d5492010-11-26 19:11:03 +0100231static void set_iso_buffer_used(USBHostDevice *s, int ep, int i)
232{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200233 get_endp(s, ep)->iso_buffer_used = i;
Hans de Goedebb6d5492010-11-26 19:11:03 +0100234}
235
236static int get_iso_buffer_used(USBHostDevice *s, int ep)
237{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200238 return get_endp(s, ep)->iso_buffer_used;
Hans de Goedebb6d5492010-11-26 19:11:03 +0100239}
240
Gerd Hoffmann6dfcdcc2011-05-16 11:30:57 +0200241static void set_max_packet_size(USBHostDevice *s, int ep, uint8_t *descriptor)
242{
243 int raw = descriptor[4] + (descriptor[5] << 8);
244 int size, microframes;
245
246 size = raw & 0x7ff;
247 switch ((raw >> 11) & 3) {
248 case 1: microframes = 2; break;
249 case 2: microframes = 3; break;
250 default: microframes = 1; break;
251 }
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200252 get_endp(s, ep)->max_packet_size = size * microframes;
Gerd Hoffmann6dfcdcc2011-05-16 11:30:57 +0200253}
254
Hans de Goede060dc842010-11-26 11:41:08 +0100255static int get_max_packet_size(USBHostDevice *s, int ep)
256{
Gerd Hoffmannca3a36c2011-06-10 13:34:10 +0200257 return get_endp(s, ep)->max_packet_size;
Hans de Goede060dc842010-11-26 11:41:08 +0100258}
259
David Ahern27911042010-04-24 10:26:22 -0600260/*
aliguori64838172008-08-21 19:31:10 +0000261 * Async URB state.
Hans de Goede060dc842010-11-26 11:41:08 +0100262 * We always allocate iso packet descriptors even for bulk transfers
David Ahern27911042010-04-24 10:26:22 -0600263 * to simplify allocation and casts.
aliguori64838172008-08-21 19:31:10 +0000264 */
Hans de Goede060dc842010-11-26 11:41:08 +0100265struct AsyncURB
balrogb9dc0332007-10-04 22:47:34 +0000266{
aliguori64838172008-08-21 19:31:10 +0000267 struct usbdevfs_urb urb;
Hans de Goede060dc842010-11-26 11:41:08 +0100268 struct usbdevfs_iso_packet_desc isocpd[ISO_FRAME_DESC_PER_URB];
Gerd Hoffmann7a8fc832011-05-16 09:13:05 +0200269 USBHostDevice *hdev;
270 QLIST_ENTRY(AsyncURB) next;
aliguori64838172008-08-21 19:31:10 +0000271
Hans de Goede060dc842010-11-26 11:41:08 +0100272 /* For regular async urbs */
aliguori64838172008-08-21 19:31:10 +0000273 USBPacket *packet;
Gerd Hoffmann71138532011-05-16 10:21:51 +0200274 int more; /* large transfer, more urbs follow */
Hans de Goede060dc842010-11-26 11:41:08 +0100275
276 /* For buffered iso handling */
277 int iso_frame_idx; /* -1 means in flight */
278};
aliguori64838172008-08-21 19:31:10 +0000279
Gerd Hoffmann7a8fc832011-05-16 09:13:05 +0200280static AsyncURB *async_alloc(USBHostDevice *s)
aliguori64838172008-08-21 19:31:10 +0000281{
Anthony Liguori7267c092011-08-20 22:09:37 -0500282 AsyncURB *aurb = g_malloc0(sizeof(AsyncURB));
Gerd Hoffmann7a8fc832011-05-16 09:13:05 +0200283 aurb->hdev = s;
284 QLIST_INSERT_HEAD(&s->aurbs, aurb, next);
285 return aurb;
balrogb9dc0332007-10-04 22:47:34 +0000286}
287
aliguori64838172008-08-21 19:31:10 +0000288static void async_free(AsyncURB *aurb)
balrogb9dc0332007-10-04 22:47:34 +0000289{
Gerd Hoffmann7a8fc832011-05-16 09:13:05 +0200290 QLIST_REMOVE(aurb, next);
Anthony Liguori7267c092011-08-20 22:09:37 -0500291 g_free(aurb);
aliguori64838172008-08-21 19:31:10 +0000292}
balrogb9dc0332007-10-04 22:47:34 +0000293
Gerd Hoffmann41c01ee2011-05-24 16:12:31 +0200294static void do_disconnect(USBHostDevice *s)
295{
Gerd Hoffmann41c01ee2011-05-24 16:12:31 +0200296 usb_host_close(s);
297 usb_host_auto_check(NULL);
298}
299
aliguori64838172008-08-21 19:31:10 +0000300static void async_complete(void *opaque)
301{
302 USBHostDevice *s = opaque;
303 AsyncURB *aurb;
Gerd Hoffmann82887262011-06-10 14:00:24 +0200304 int urbs = 0;
balrogb9dc0332007-10-04 22:47:34 +0000305
aliguori64838172008-08-21 19:31:10 +0000306 while (1) {
David Ahern27911042010-04-24 10:26:22 -0600307 USBPacket *p;
aliguori64838172008-08-21 19:31:10 +0000308
David Ahern27911042010-04-24 10:26:22 -0600309 int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
aliguori64838172008-08-21 19:31:10 +0000310 if (r < 0) {
David Ahern27911042010-04-24 10:26:22 -0600311 if (errno == EAGAIN) {
Gerd Hoffmann82887262011-06-10 14:00:24 +0200312 if (urbs > 2) {
313 fprintf(stderr, "husb: %d iso urbs finished at once\n", urbs);
314 }
aliguori64838172008-08-21 19:31:10 +0000315 return;
David Ahern27911042010-04-24 10:26:22 -0600316 }
Gerd Hoffmann40197c32011-08-22 14:18:21 +0200317 if (errno == ENODEV) {
318 if (!s->closing) {
319 trace_usb_host_disconnect(s->bus_num, s->addr);
320 do_disconnect(s);
321 }
aliguori64838172008-08-21 19:31:10 +0000322 return;
323 }
324
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200325 perror("USBDEVFS_REAPURBNDELAY");
aliguori64838172008-08-21 19:31:10 +0000326 return;
balrogb9dc0332007-10-04 22:47:34 +0000327 }
aliguori64838172008-08-21 19:31:10 +0000328
David Ahern27911042010-04-24 10:26:22 -0600329 DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
aliguori64838172008-08-21 19:31:10 +0000330 aurb, aurb->urb.status, aurb->urb.actual_length);
331
Hans de Goede060dc842010-11-26 11:41:08 +0100332 /* If this is a buffered iso urb mark it as complete and don't do
333 anything else (it is handled further in usb_host_handle_iso_data) */
334 if (aurb->iso_frame_idx == -1) {
Gerd Hoffmann82887262011-06-10 14:00:24 +0200335 int inflight;
Hans de Goede060dc842010-11-26 11:41:08 +0100336 if (aurb->urb.status == -EPIPE) {
337 set_halt(s, aurb->urb.endpoint & 0xf);
338 }
339 aurb->iso_frame_idx = 0;
Gerd Hoffmann82887262011-06-10 14:00:24 +0200340 urbs++;
341 inflight = change_iso_inflight(s, aurb->urb.endpoint & 0xf, -1);
342 if (inflight == 0 && is_iso_started(s, aurb->urb.endpoint & 0xf)) {
343 fprintf(stderr, "husb: out of buffers for iso stream\n");
344 }
Hans de Goede060dc842010-11-26 11:41:08 +0100345 continue;
346 }
347
348 p = aurb->packet;
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200349 trace_usb_host_urb_complete(s->bus_num, s->addr, aurb, aurb->urb.status,
350 aurb->urb.actual_length, aurb->more);
Hans de Goede060dc842010-11-26 11:41:08 +0100351
David Ahern27911042010-04-24 10:26:22 -0600352 if (p) {
aliguori64838172008-08-21 19:31:10 +0000353 switch (aurb->urb.status) {
354 case 0:
Gerd Hoffmann4f4321c2011-07-12 15:22:25 +0200355 p->result += aurb->urb.actual_length;
aliguori64838172008-08-21 19:31:10 +0000356 break;
357
358 case -EPIPE:
359 set_halt(s, p->devep);
Gerd Hoffmann4f4321c2011-07-12 15:22:25 +0200360 p->result = USB_RET_STALL;
David Ahern27911042010-04-24 10:26:22 -0600361 break;
Paul Bolledcc7e252009-10-13 13:40:08 +0200362
aliguori64838172008-08-21 19:31:10 +0000363 default:
Gerd Hoffmann4f4321c2011-07-12 15:22:25 +0200364 p->result = USB_RET_NAK;
aliguori64838172008-08-21 19:31:10 +0000365 break;
366 }
367
Hans de Goede50b79632011-02-02 17:36:29 +0100368 if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200369 trace_usb_host_req_complete(s->bus_num, s->addr, p->result);
Hans de Goede50b79632011-02-02 17:36:29 +0100370 usb_generic_async_ctrl_complete(&s->dev, p);
Gerd Hoffmann71138532011-05-16 10:21:51 +0200371 } else if (!aurb->more) {
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200372 trace_usb_host_req_complete(s->bus_num, s->addr, p->result);
Hans de Goede50b79632011-02-02 17:36:29 +0100373 usb_packet_complete(&s->dev, p);
374 }
David Ahern27911042010-04-24 10:26:22 -0600375 }
aliguori64838172008-08-21 19:31:10 +0000376
377 async_free(aurb);
balrogb9dc0332007-10-04 22:47:34 +0000378 }
balrogb9dc0332007-10-04 22:47:34 +0000379}
380
Gerd Hoffmanneb5e6802011-05-16 10:34:53 +0200381static void usb_host_async_cancel(USBDevice *dev, USBPacket *p)
balrogb9dc0332007-10-04 22:47:34 +0000382{
Gerd Hoffmanneb5e6802011-05-16 10:34:53 +0200383 USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
Gerd Hoffmann227ebeb2011-05-16 09:20:06 +0200384 AsyncURB *aurb;
balrogb9dc0332007-10-04 22:47:34 +0000385
Gerd Hoffmann227ebeb2011-05-16 09:20:06 +0200386 QLIST_FOREACH(aurb, &s->aurbs, next) {
387 if (p != aurb->packet) {
388 continue;
389 }
balrogb9dc0332007-10-04 22:47:34 +0000390
Gerd Hoffmann227ebeb2011-05-16 09:20:06 +0200391 DPRINTF("husb: async cancel: packet %p, aurb %p\n", p, aurb);
aliguori64838172008-08-21 19:31:10 +0000392
Gerd Hoffmann227ebeb2011-05-16 09:20:06 +0200393 /* Mark it as dead (see async_complete above) */
394 aurb->packet = NULL;
395
396 int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb);
397 if (r < 0) {
398 DPRINTF("husb: async. discard urb failed errno %d\n", errno);
399 }
balrogb9dc0332007-10-04 22:47:34 +0000400 }
balrogb9dc0332007-10-04 22:47:34 +0000401}
402
aliguori446ab122008-09-14 01:06:09 +0000403static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
balrogb9dc0332007-10-04 22:47:34 +0000404{
Gerd Hoffmann41c01ee2011-05-24 16:12:31 +0200405 const char *op = NULL;
balrogb9dc0332007-10-04 22:47:34 +0000406 int dev_descr_len, config_descr_len;
Blue Swirld4c4e6f2010-04-25 18:23:04 +0000407 int interface, nb_interfaces;
balrogb9dc0332007-10-04 22:47:34 +0000408 int ret, i;
409
Gerd Hoffmanneb7700b2011-08-24 14:45:07 +0200410 if (configuration == 0) { /* address state - ignore */
411 dev->ninterfaces = 0;
412 dev->configuration = 0;
balrogb9dc0332007-10-04 22:47:34 +0000413 return 1;
Gerd Hoffmanneb7700b2011-08-24 14:45:07 +0200414 }
balrogb9dc0332007-10-04 22:47:34 +0000415
malcd0f2c4c2010-02-07 02:03:50 +0300416 DPRINTF("husb: claiming interfaces. config %d\n", configuration);
aliguori446ab122008-09-14 01:06:09 +0000417
balrogb9dc0332007-10-04 22:47:34 +0000418 i = 0;
419 dev_descr_len = dev->descr[0];
David Ahern27911042010-04-24 10:26:22 -0600420 if (dev_descr_len > dev->descr_len) {
Hans de Goede61c11172011-05-31 11:35:20 +0200421 fprintf(stderr, "husb: update iface failed. descr too short\n");
422 return 0;
David Ahern27911042010-04-24 10:26:22 -0600423 }
balrogb9dc0332007-10-04 22:47:34 +0000424
425 i += dev_descr_len;
426 while (i < dev->descr_len) {
David Ahern27911042010-04-24 10:26:22 -0600427 DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
428 i, dev->descr_len,
balrogb9dc0332007-10-04 22:47:34 +0000429 dev->descr[i], dev->descr[i+1]);
aliguori64838172008-08-21 19:31:10 +0000430
balrogb9dc0332007-10-04 22:47:34 +0000431 if (dev->descr[i+1] != USB_DT_CONFIG) {
432 i += dev->descr[i];
433 continue;
434 }
435 config_descr_len = dev->descr[i];
436
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200437 DPRINTF("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
aliguori1f3870a2008-08-21 19:27:48 +0000438
Gerd Hoffmanneb7700b2011-08-24 14:45:07 +0200439 if (configuration == dev->descr[i + 5]) {
aliguori446ab122008-09-14 01:06:09 +0000440 configuration = dev->descr[i + 5];
balrogb9dc0332007-10-04 22:47:34 +0000441 break;
aliguori446ab122008-09-14 01:06:09 +0000442 }
balrogb9dc0332007-10-04 22:47:34 +0000443
444 i += config_descr_len;
445 }
446
447 if (i >= dev->descr_len) {
David Ahern27911042010-04-24 10:26:22 -0600448 fprintf(stderr,
449 "husb: update iface failed. no matching configuration\n");
Hans de Goede61c11172011-05-31 11:35:20 +0200450 return 0;
balrogb9dc0332007-10-04 22:47:34 +0000451 }
452 nb_interfaces = dev->descr[i + 4];
453
454#ifdef USBDEVFS_DISCONNECT
455 /* earlier Linux 2.4 do not support that */
456 {
457 struct usbdevfs_ioctl ctrl;
458 for (interface = 0; interface < nb_interfaces; interface++) {
459 ctrl.ioctl_code = USBDEVFS_DISCONNECT;
460 ctrl.ifno = interface;
Brad Hards021730f2011-04-13 19:45:32 +1000461 ctrl.data = 0;
Gerd Hoffmann41c01ee2011-05-24 16:12:31 +0200462 op = "USBDEVFS_DISCONNECT";
balrogb9dc0332007-10-04 22:47:34 +0000463 ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
464 if (ret < 0 && errno != ENODATA) {
balrogb9dc0332007-10-04 22:47:34 +0000465 goto fail;
466 }
467 }
468 }
469#endif
470
471 /* XXX: only grab if all interfaces are free */
472 for (interface = 0; interface < nb_interfaces; interface++) {
Gerd Hoffmann41c01ee2011-05-24 16:12:31 +0200473 op = "USBDEVFS_CLAIMINTERFACE";
balrogb9dc0332007-10-04 22:47:34 +0000474 ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
475 if (ret < 0) {
Gerd Hoffmann41c01ee2011-05-24 16:12:31 +0200476 goto fail;
balrogb9dc0332007-10-04 22:47:34 +0000477 }
478 }
479
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200480 trace_usb_host_claim_interfaces(dev->bus_num, dev->addr,
481 nb_interfaces, configuration);
balrogb9dc0332007-10-04 22:47:34 +0000482
aliguori446ab122008-09-14 01:06:09 +0000483 dev->ninterfaces = nb_interfaces;
484 dev->configuration = configuration;
485 return 1;
Gerd Hoffmann41c01ee2011-05-24 16:12:31 +0200486
487fail:
488 if (errno == ENODEV) {
489 do_disconnect(dev);
490 }
491 perror(op);
492 return 0;
aliguori446ab122008-09-14 01:06:09 +0000493}
494
495static int usb_host_release_interfaces(USBHostDevice *s)
496{
497 int ret, i;
498
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200499 trace_usb_host_release_interfaces(s->bus_num, s->addr);
aliguori446ab122008-09-14 01:06:09 +0000500
501 for (i = 0; i < s->ninterfaces; i++) {
502 ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i);
503 if (ret < 0) {
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200504 perror("USBDEVFS_RELEASEINTERFACE");
aliguori446ab122008-09-14 01:06:09 +0000505 return 0;
506 }
507 }
balrogb9dc0332007-10-04 22:47:34 +0000508 return 1;
509}
510
bellard059809e2006-07-19 18:06:15 +0000511static void usb_host_handle_reset(USBDevice *dev)
bellardbb36d472005-11-05 14:22:28 +0000512{
Gerd Hoffmann26a9e822009-10-26 15:56:50 +0100513 USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
aliguori64838172008-08-21 19:31:10 +0000514
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200515 trace_usb_host_reset(s->bus_num, s->addr);
aliguori64838172008-08-21 19:31:10 +0000516
bellardbb36d472005-11-05 14:22:28 +0000517 ioctl(s->fd, USBDEVFS_RESET);
aliguori446ab122008-09-14 01:06:09 +0000518
Gerd Hoffmanneb7700b2011-08-24 14:45:07 +0200519 usb_host_claim_interfaces(s, 0);
Gerd Hoffmann9b87e192011-08-24 10:55:40 +0200520 usb_linux_update_endp_table(s);
ths5fafdf22007-09-16 21:08:06 +0000521}
bellardbb36d472005-11-05 14:22:28 +0000522
bellard059809e2006-07-19 18:06:15 +0000523static void usb_host_handle_destroy(USBDevice *dev)
524{
525 USBHostDevice *s = (USBHostDevice *)dev;
526
Gerd Hoffmann26a9e822009-10-26 15:56:50 +0100527 usb_host_close(s);
528 QTAILQ_REMOVE(&hostdevs, s, next);
Shahar Havivib373a632010-06-16 15:16:11 +0300529 qemu_remove_exit_notifier(&s->exit);
bellard059809e2006-07-19 18:06:15 +0000530}
531
Hans de Goede060dc842010-11-26 11:41:08 +0100532/* iso data is special, we need to keep enough urbs in flight to make sure
533 that the controller never runs out of them, otherwise the device will
534 likely suffer a buffer underrun / overrun. */
535static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, uint8_t ep, int in)
536{
537 AsyncURB *aurb;
538 int i, j, len = get_max_packet_size(s, ep);
539
Anthony Liguori7267c092011-08-20 22:09:37 -0500540 aurb = g_malloc0(s->iso_urb_count * sizeof(*aurb));
Gerd Hoffmannb81bcd82011-06-10 14:03:56 +0200541 for (i = 0; i < s->iso_urb_count; i++) {
Hans de Goede060dc842010-11-26 11:41:08 +0100542 aurb[i].urb.endpoint = ep;
543 aurb[i].urb.buffer_length = ISO_FRAME_DESC_PER_URB * len;
Anthony Liguori7267c092011-08-20 22:09:37 -0500544 aurb[i].urb.buffer = g_malloc(aurb[i].urb.buffer_length);
Hans de Goede060dc842010-11-26 11:41:08 +0100545 aurb[i].urb.type = USBDEVFS_URB_TYPE_ISO;
546 aurb[i].urb.flags = USBDEVFS_URB_ISO_ASAP;
547 aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB;
548 for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++)
549 aurb[i].urb.iso_frame_desc[j].length = len;
550 if (in) {
551 aurb[i].urb.endpoint |= 0x80;
552 /* Mark as fully consumed (idle) */
553 aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB;
554 }
555 }
556 set_iso_urb(s, ep, aurb);
557
558 return aurb;
559}
560
561static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
562{
563 AsyncURB *aurb;
564 int i, ret, killed = 0, free = 1;
565
566 aurb = get_iso_urb(s, ep);
567 if (!aurb) {
568 return;
569 }
570
Gerd Hoffmannb81bcd82011-06-10 14:03:56 +0200571 for (i = 0; i < s->iso_urb_count; i++) {
Hans de Goede060dc842010-11-26 11:41:08 +0100572 /* in flight? */
573 if (aurb[i].iso_frame_idx == -1) {
574 ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]);
575 if (ret < 0) {
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200576 perror("USBDEVFS_DISCARDURB");
Hans de Goede060dc842010-11-26 11:41:08 +0100577 free = 0;
578 continue;
579 }
580 killed++;
581 }
582 }
583
584 /* Make sure any urbs we've killed are reaped before we free them */
585 if (killed) {
586 async_complete(s);
587 }
588
Gerd Hoffmannb81bcd82011-06-10 14:03:56 +0200589 for (i = 0; i < s->iso_urb_count; i++) {
Anthony Liguori7267c092011-08-20 22:09:37 -0500590 g_free(aurb[i].urb.buffer);
Hans de Goede060dc842010-11-26 11:41:08 +0100591 }
592
593 if (free)
Anthony Liguori7267c092011-08-20 22:09:37 -0500594 g_free(aurb);
Hans de Goede060dc842010-11-26 11:41:08 +0100595 else
596 printf("husb: leaking iso urbs because of discard failure\n");
597 set_iso_urb(s, ep, NULL);
Hans de Goedebb6d5492010-11-26 19:11:03 +0100598 set_iso_urb_idx(s, ep, 0);
599 clear_iso_started(s, ep);
Hans de Goede060dc842010-11-26 11:41:08 +0100600}
601
602static int urb_status_to_usb_ret(int status)
603{
604 switch (status) {
605 case -EPIPE:
606 return USB_RET_STALL;
607 default:
608 return USB_RET_NAK;
609 }
610}
611
Hans de Goedebb6d5492010-11-26 19:11:03 +0100612static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
Hans de Goede060dc842010-11-26 11:41:08 +0100613{
614 AsyncURB *aurb;
Hans de Goedebb6d5492010-11-26 19:11:03 +0100615 int i, j, ret, max_packet_size, offset, len = 0;
Gerd Hoffmann4f4321c2011-07-12 15:22:25 +0200616 uint8_t *buf;
Hans de Goede975f2992010-11-26 14:59:35 +0100617
618 max_packet_size = get_max_packet_size(s, p->devep);
619 if (max_packet_size == 0)
620 return USB_RET_NAK;
Hans de Goede060dc842010-11-26 11:41:08 +0100621
622 aurb = get_iso_urb(s, p->devep);
623 if (!aurb) {
Hans de Goedebb6d5492010-11-26 19:11:03 +0100624 aurb = usb_host_alloc_iso(s, p->devep, in);
Hans de Goede060dc842010-11-26 11:41:08 +0100625 }
626
627 i = get_iso_urb_idx(s, p->devep);
628 j = aurb[i].iso_frame_idx;
629 if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
Hans de Goedebb6d5492010-11-26 19:11:03 +0100630 if (in) {
631 /* Check urb status */
632 if (aurb[i].urb.status) {
633 len = urb_status_to_usb_ret(aurb[i].urb.status);
634 /* Move to the next urb */
635 aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
636 /* Check frame status */
637 } else if (aurb[i].urb.iso_frame_desc[j].status) {
638 len = urb_status_to_usb_ret(
639 aurb[i].urb.iso_frame_desc[j].status);
640 /* Check the frame fits */
Gerd Hoffmann4f4321c2011-07-12 15:22:25 +0200641 } else if (aurb[i].urb.iso_frame_desc[j].actual_length
642 > p->iov.size) {
Hans de Goedebb6d5492010-11-26 19:11:03 +0100643 printf("husb: received iso data is larger then packet\n");
644 len = USB_RET_NAK;
645 /* All good copy data over */
646 } else {
647 len = aurb[i].urb.iso_frame_desc[j].actual_length;
Gerd Hoffmann4f4321c2011-07-12 15:22:25 +0200648 buf = aurb[i].urb.buffer +
649 j * aurb[i].urb.iso_frame_desc[0].length;
650 usb_packet_copy(p, buf, len);
Hans de Goedebb6d5492010-11-26 19:11:03 +0100651 }
Hans de Goede060dc842010-11-26 11:41:08 +0100652 } else {
Gerd Hoffmann4f4321c2011-07-12 15:22:25 +0200653 len = p->iov.size;
Hans de Goedebb6d5492010-11-26 19:11:03 +0100654 offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->devep);
655
656 /* Check the frame fits */
657 if (len > max_packet_size) {
658 printf("husb: send iso data is larger then max packet size\n");
659 return USB_RET_NAK;
660 }
661
662 /* All good copy data over */
Gerd Hoffmann4f4321c2011-07-12 15:22:25 +0200663 usb_packet_copy(p, aurb[i].urb.buffer + offset, len);
Hans de Goedebb6d5492010-11-26 19:11:03 +0100664 aurb[i].urb.iso_frame_desc[j].length = len;
665 offset += len;
666 set_iso_buffer_used(s, p->devep, offset);
667
668 /* Start the stream once we have buffered enough data */
669 if (!is_iso_started(s, p->devep) && i == 1 && j == 8) {
670 set_iso_started(s, p->devep);
671 }
Hans de Goede060dc842010-11-26 11:41:08 +0100672 }
673 aurb[i].iso_frame_idx++;
674 if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
Gerd Hoffmannb81bcd82011-06-10 14:03:56 +0200675 i = (i + 1) % s->iso_urb_count;
Hans de Goede060dc842010-11-26 11:41:08 +0100676 set_iso_urb_idx(s, p->devep, i);
677 }
Hans de Goedebb6d5492010-11-26 19:11:03 +0100678 } else {
679 if (in) {
680 set_iso_started(s, p->devep);
681 } else {
682 DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
683 }
Hans de Goede060dc842010-11-26 11:41:08 +0100684 }
685
Hans de Goedebb6d5492010-11-26 19:11:03 +0100686 if (is_iso_started(s, p->devep)) {
687 /* (Re)-submit all fully consumed / filled urbs */
Gerd Hoffmannb81bcd82011-06-10 14:03:56 +0200688 for (i = 0; i < s->iso_urb_count; i++) {
Hans de Goedebb6d5492010-11-26 19:11:03 +0100689 if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
690 ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
691 if (ret < 0) {
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200692 perror("USBDEVFS_SUBMITURB");
Hans de Goedebb6d5492010-11-26 19:11:03 +0100693 if (!in || len == 0) {
694 switch(errno) {
695 case ETIMEDOUT:
696 len = USB_RET_NAK;
Stefan Weil0225e252011-05-07 22:10:53 +0200697 break;
Hans de Goedebb6d5492010-11-26 19:11:03 +0100698 case EPIPE:
699 default:
700 len = USB_RET_STALL;
701 }
Hans de Goede060dc842010-11-26 11:41:08 +0100702 }
Hans de Goedebb6d5492010-11-26 19:11:03 +0100703 break;
Hans de Goede060dc842010-11-26 11:41:08 +0100704 }
Hans de Goedebb6d5492010-11-26 19:11:03 +0100705 aurb[i].iso_frame_idx = -1;
Gerd Hoffmann82887262011-06-10 14:00:24 +0200706 change_iso_inflight(s, p->devep, +1);
Hans de Goede060dc842010-11-26 11:41:08 +0100707 }
Hans de Goede060dc842010-11-26 11:41:08 +0100708 }
709 }
710
711 return len;
712}
713
Hans de Goede50b79632011-02-02 17:36:29 +0100714static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
bellardbb36d472005-11-05 14:22:28 +0000715{
Hans de Goede50b79632011-02-02 17:36:29 +0100716 USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
aliguori64838172008-08-21 19:31:10 +0000717 struct usbdevfs_urb *urb;
aliguori446ab122008-09-14 01:06:09 +0000718 AsyncURB *aurb;
Gerd Hoffmannb621bab2011-07-13 11:28:17 +0200719 int ret, rem, prem, v;
Gerd Hoffmann71138532011-05-16 10:21:51 +0200720 uint8_t *pbuf;
Hans de Goede060dc842010-11-26 11:41:08 +0100721 uint8_t ep;
722
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200723 trace_usb_host_req_data(s->bus_num, s->addr,
724 p->pid == USB_TOKEN_IN,
725 p->devep, p->iov.size);
726
Hans de Goedea0b5fec2010-11-26 14:56:17 +0100727 if (!is_valid(s, p->devep)) {
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200728 trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
Hans de Goedea0b5fec2010-11-26 14:56:17 +0100729 return USB_RET_NAK;
730 }
731
Hans de Goede060dc842010-11-26 11:41:08 +0100732 if (p->pid == USB_TOKEN_IN) {
733 ep = p->devep | 0x80;
734 } else {
735 ep = p->devep;
736 }
737
738 if (is_halted(s, p->devep)) {
Gerd Hoffmann9b87e192011-08-24 10:55:40 +0200739 unsigned int arg = ep;
740 ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &arg);
Hans de Goede060dc842010-11-26 11:41:08 +0100741 if (ret < 0) {
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200742 perror("USBDEVFS_CLEAR_HALT");
743 trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
Hans de Goede060dc842010-11-26 11:41:08 +0100744 return USB_RET_NAK;
745 }
746 clear_halt(s, p->devep);
747 }
748
Hans de Goedebb6d5492010-11-26 19:11:03 +0100749 if (is_isoc(s, p->devep)) {
750 return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
751 }
bellardbb36d472005-11-05 14:22:28 +0000752
Gerd Hoffmannb621bab2011-07-13 11:28:17 +0200753 v = 0;
754 prem = p->iov.iov[v].iov_len;
755 pbuf = p->iov.iov[v].iov_base;
756 rem = p->iov.size;
Gerd Hoffmann71138532011-05-16 10:21:51 +0200757 while (rem) {
Gerd Hoffmannb621bab2011-07-13 11:28:17 +0200758 if (prem == 0) {
759 v++;
760 assert(v < p->iov.niov);
761 prem = p->iov.iov[v].iov_len;
762 pbuf = p->iov.iov[v].iov_base;
763 assert(prem <= rem);
764 }
Gerd Hoffmann71138532011-05-16 10:21:51 +0200765 aurb = async_alloc(s);
766 aurb->packet = p;
balrogb9dc0332007-10-04 22:47:34 +0000767
Gerd Hoffmann71138532011-05-16 10:21:51 +0200768 urb = &aurb->urb;
769 urb->endpoint = ep;
770 urb->type = USBDEVFS_URB_TYPE_BULK;
771 urb->usercontext = s;
772 urb->buffer = pbuf;
Gerd Hoffmannb621bab2011-07-13 11:28:17 +0200773 urb->buffer_length = prem;
aliguori64838172008-08-21 19:31:10 +0000774
Gerd Hoffmannb621bab2011-07-13 11:28:17 +0200775 if (urb->buffer_length > MAX_USBFS_BUFFER_SIZE) {
Gerd Hoffmann71138532011-05-16 10:21:51 +0200776 urb->buffer_length = MAX_USBFS_BUFFER_SIZE;
Gerd Hoffmann71138532011-05-16 10:21:51 +0200777 }
778 pbuf += urb->buffer_length;
Gerd Hoffmannb621bab2011-07-13 11:28:17 +0200779 prem -= urb->buffer_length;
Gerd Hoffmann71138532011-05-16 10:21:51 +0200780 rem -= urb->buffer_length;
Gerd Hoffmannb621bab2011-07-13 11:28:17 +0200781 if (rem) {
782 aurb->more = 1;
783 }
aliguori64838172008-08-21 19:31:10 +0000784
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200785 trace_usb_host_urb_submit(s->bus_num, s->addr, aurb,
786 urb->buffer_length, aurb->more);
Gerd Hoffmann71138532011-05-16 10:21:51 +0200787 ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
aliguori64838172008-08-21 19:31:10 +0000788
Gerd Hoffmann71138532011-05-16 10:21:51 +0200789 DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n",
790 urb->endpoint, urb->buffer_length, aurb->more, p, aurb);
aliguori64838172008-08-21 19:31:10 +0000791
Gerd Hoffmann71138532011-05-16 10:21:51 +0200792 if (ret < 0) {
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200793 perror("USBDEVFS_SUBMITURB");
Gerd Hoffmann71138532011-05-16 10:21:51 +0200794 async_free(aurb);
aliguori64838172008-08-21 19:31:10 +0000795
Gerd Hoffmann71138532011-05-16 10:21:51 +0200796 switch(errno) {
797 case ETIMEDOUT:
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200798 trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_NAK);
Gerd Hoffmann71138532011-05-16 10:21:51 +0200799 return USB_RET_NAK;
800 case EPIPE:
801 default:
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200802 trace_usb_host_req_complete(s->bus_num, s->addr, USB_RET_STALL);
Gerd Hoffmann71138532011-05-16 10:21:51 +0200803 return USB_RET_STALL;
804 }
balrogb9dc0332007-10-04 22:47:34 +0000805 }
806 }
aliguori64838172008-08-21 19:31:10 +0000807
balrogb9dc0332007-10-04 22:47:34 +0000808 return USB_RET_ASYNC;
balrogb9dc0332007-10-04 22:47:34 +0000809}
810
aliguori446ab122008-09-14 01:06:09 +0000811static int ctrl_error(void)
812{
David Ahern27911042010-04-24 10:26:22 -0600813 if (errno == ETIMEDOUT) {
aliguori446ab122008-09-14 01:06:09 +0000814 return USB_RET_NAK;
David Ahern27911042010-04-24 10:26:22 -0600815 } else {
aliguori446ab122008-09-14 01:06:09 +0000816 return USB_RET_STALL;
David Ahern27911042010-04-24 10:26:22 -0600817 }
aliguori446ab122008-09-14 01:06:09 +0000818}
819
820static int usb_host_set_address(USBHostDevice *s, int addr)
821{
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200822 trace_usb_host_set_address(s->bus_num, s->addr, addr);
aliguori446ab122008-09-14 01:06:09 +0000823 s->dev.addr = addr;
824 return 0;
825}
826
827static int usb_host_set_config(USBHostDevice *s, int config)
828{
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200829 trace_usb_host_set_config(s->bus_num, s->addr, config);
830
aliguori446ab122008-09-14 01:06:09 +0000831 usb_host_release_interfaces(s);
832
833 int ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
David Ahern27911042010-04-24 10:26:22 -0600834
malcd0f2c4c2010-02-07 02:03:50 +0300835 DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno);
David Ahern27911042010-04-24 10:26:22 -0600836
837 if (ret < 0) {
aliguori446ab122008-09-14 01:06:09 +0000838 return ctrl_error();
David Ahern27911042010-04-24 10:26:22 -0600839 }
aliguori446ab122008-09-14 01:06:09 +0000840 usb_host_claim_interfaces(s, config);
Gerd Hoffmanneb7700b2011-08-24 14:45:07 +0200841 usb_linux_update_endp_table(s);
aliguori446ab122008-09-14 01:06:09 +0000842 return 0;
843}
844
845static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
846{
847 struct usbdevfs_setinterface si;
Hans de Goede060dc842010-11-26 11:41:08 +0100848 int i, ret;
849
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200850 trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt);
851
Hans de Goede3a4854b2010-11-26 15:02:16 +0100852 for (i = 1; i <= MAX_ENDPOINTS; i++) {
Hans de Goede060dc842010-11-26 11:41:08 +0100853 if (is_isoc(s, i)) {
854 usb_host_stop_n_free_iso(s, i);
855 }
856 }
aliguori446ab122008-09-14 01:06:09 +0000857
858 si.interface = iface;
859 si.altsetting = alt;
860 ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
aliguori446ab122008-09-14 01:06:09 +0000861
David Ahern27911042010-04-24 10:26:22 -0600862 DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
863 iface, alt, ret, errno);
864
865 if (ret < 0) {
866 return ctrl_error();
867 }
aliguori446ab122008-09-14 01:06:09 +0000868 usb_linux_update_endp_table(s);
869 return 0;
870}
871
Hans de Goede50b79632011-02-02 17:36:29 +0100872static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
873 int request, int value, int index, int length, uint8_t *data)
aliguori446ab122008-09-14 01:06:09 +0000874{
Hans de Goede50b79632011-02-02 17:36:29 +0100875 USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
aliguori446ab122008-09-14 01:06:09 +0000876 struct usbdevfs_urb *urb;
877 AsyncURB *aurb;
Hans de Goede50b79632011-02-02 17:36:29 +0100878 int ret;
aliguori446ab122008-09-14 01:06:09 +0000879
David Ahern27911042010-04-24 10:26:22 -0600880 /*
aliguori446ab122008-09-14 01:06:09 +0000881 * Process certain standard device requests.
882 * These are infrequent and are processed synchronously.
883 */
aliguori446ab122008-09-14 01:06:09 +0000884
Hans de Goede50b79632011-02-02 17:36:29 +0100885 /* Note request is (bRequestType << 8) | bRequest */
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200886 trace_usb_host_req_control(s->bus_num, s->addr, request, value, index);
aliguori446ab122008-09-14 01:06:09 +0000887
Hans de Goede50b79632011-02-02 17:36:29 +0100888 switch (request) {
889 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
890 return usb_host_set_address(s, value);
aliguori446ab122008-09-14 01:06:09 +0000891
Hans de Goede50b79632011-02-02 17:36:29 +0100892 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
893 return usb_host_set_config(s, value & 0xff);
aliguori446ab122008-09-14 01:06:09 +0000894
Hans de Goede50b79632011-02-02 17:36:29 +0100895 case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
aliguori446ab122008-09-14 01:06:09 +0000896 return usb_host_set_interface(s, index, value);
David Ahern27911042010-04-24 10:26:22 -0600897 }
aliguori446ab122008-09-14 01:06:09 +0000898
899 /* The rest are asynchronous */
900
Hans de Goede50b79632011-02-02 17:36:29 +0100901 if (length > sizeof(dev->data_buf)) {
902 fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n",
903 length, sizeof(dev->data_buf));
malcb2e3b6e2009-09-12 03:18:18 +0400904 return USB_RET_STALL;
Jim Parisc4c0e232009-08-24 14:56:12 -0400905 }
906
Gerd Hoffmann7a8fc832011-05-16 09:13:05 +0200907 aurb = async_alloc(s);
aliguori446ab122008-09-14 01:06:09 +0000908 aurb->packet = p;
909
David Ahern27911042010-04-24 10:26:22 -0600910 /*
aliguori446ab122008-09-14 01:06:09 +0000911 * Setup ctrl transfer.
912 *
Brad Hardsa0102082011-04-13 19:45:33 +1000913 * s->ctrl is laid out such that data buffer immediately follows
aliguori446ab122008-09-14 01:06:09 +0000914 * 'req' struct which is exactly what usbdevfs expects.
David Ahern27911042010-04-24 10:26:22 -0600915 */
aliguori446ab122008-09-14 01:06:09 +0000916 urb = &aurb->urb;
917
918 urb->type = USBDEVFS_URB_TYPE_CONTROL;
919 urb->endpoint = p->devep;
920
Hans de Goede50b79632011-02-02 17:36:29 +0100921 urb->buffer = &dev->setup_buf;
922 urb->buffer_length = length + 8;
aliguori446ab122008-09-14 01:06:09 +0000923
924 urb->usercontext = s;
925
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +0200926 trace_usb_host_urb_submit(s->bus_num, s->addr, aurb,
927 urb->buffer_length, aurb->more);
aliguori446ab122008-09-14 01:06:09 +0000928 ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
929
malcd0f2c4c2010-02-07 02:03:50 +0300930 DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb->buffer_length, aurb);
aliguori446ab122008-09-14 01:06:09 +0000931
932 if (ret < 0) {
malcd0f2c4c2010-02-07 02:03:50 +0300933 DPRINTF("husb: submit failed. errno %d\n", errno);
aliguori446ab122008-09-14 01:06:09 +0000934 async_free(aurb);
935
936 switch(errno) {
937 case ETIMEDOUT:
938 return USB_RET_NAK;
939 case EPIPE:
940 default:
941 return USB_RET_STALL;
942 }
943 }
944
aliguori446ab122008-09-14 01:06:09 +0000945 return USB_RET_ASYNC;
946}
947
Hans de Goedeed3a3282010-11-24 12:50:00 +0100948static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
949 uint8_t configuration, uint8_t interface)
950{
951 uint8_t alt_setting;
952 struct usb_ctrltransfer ct;
953 int ret;
954
Hans de Goedec43831f2010-11-24 12:57:59 +0100955 if (usb_fs_type == USB_FS_SYS) {
956 char device_name[64], line[1024];
957 int alt_setting;
958
Gerd Hoffmann5557d822011-05-10 11:43:57 +0200959 sprintf(device_name, "%d-%s:%d.%d", s->bus_num, s->port,
Hans de Goedec43831f2010-11-24 12:57:59 +0100960 (int)configuration, (int)interface);
961
962 if (!usb_host_read_file(line, sizeof(line), "bAlternateSetting",
963 device_name)) {
964 goto usbdevfs;
965 }
966 if (sscanf(line, "%d", &alt_setting) != 1) {
967 goto usbdevfs;
968 }
969 return alt_setting;
970 }
971
972usbdevfs:
Hans de Goedeed3a3282010-11-24 12:50:00 +0100973 ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
974 ct.bRequest = USB_REQ_GET_INTERFACE;
975 ct.wValue = 0;
976 ct.wIndex = interface;
977 ct.wLength = 1;
978 ct.data = &alt_setting;
979 ct.timeout = 50;
980 ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
981 if (ret < 0) {
982 /* Assume alt 0 on error */
983 return 0;
984 }
985
986 return alt_setting;
987}
988
Hans de Goede71d71bb2010-11-10 10:06:24 +0100989/* returns 1 on problem encountered or 0 for success */
990static int usb_linux_update_endp_table(USBHostDevice *s)
991{
992 uint8_t *descriptors;
Gerd Hoffmanneb7700b2011-08-24 14:45:07 +0200993 uint8_t devep, type, alt_interface;
Hans de Goedeed3a3282010-11-24 12:50:00 +0100994 int interface, length, i;
Hans de Goede71d71bb2010-11-10 10:06:24 +0100995
Hans de Goedea0b5fec2010-11-26 14:56:17 +0100996 for (i = 0; i < MAX_ENDPOINTS; i++)
997 s->endp_table[i].type = INVALID_EP_TYPE;
998
Gerd Hoffmanneb7700b2011-08-24 14:45:07 +0200999 if (s->configuration == 0) {
1000 /* not configured yet -- leave all endpoints disabled */
1001 return 0;
1002 }
Hans de Goede71d71bb2010-11-10 10:06:24 +01001003
balrogb9dc0332007-10-04 22:47:34 +00001004 /* get the desired configuration, interface, and endpoint descriptors
1005 * from device description */
1006 descriptors = &s->descr[18];
1007 length = s->descr_len - 18;
1008 i = 0;
1009
1010 if (descriptors[i + 1] != USB_DT_CONFIG ||
Gerd Hoffmanneb7700b2011-08-24 14:45:07 +02001011 descriptors[i + 5] != s->configuration) {
1012 fprintf(stderr, "invalid descriptor data - configuration %d\n",
1013 s->configuration);
balrogb9dc0332007-10-04 22:47:34 +00001014 return 1;
1015 }
1016 i += descriptors[i];
1017
1018 while (i < length) {
1019 if (descriptors[i + 1] != USB_DT_INTERFACE ||
1020 (descriptors[i + 1] == USB_DT_INTERFACE &&
1021 descriptors[i + 4] == 0)) {
1022 i += descriptors[i];
1023 continue;
1024 }
1025
1026 interface = descriptors[i + 2];
Gerd Hoffmanneb7700b2011-08-24 14:45:07 +02001027 alt_interface = usb_linux_get_alt_setting(s, s->configuration,
1028 interface);
balrogb9dc0332007-10-04 22:47:34 +00001029
1030 /* the current interface descriptor is the active interface
1031 * and has endpoints */
1032 if (descriptors[i + 3] != alt_interface) {
1033 i += descriptors[i];
1034 continue;
1035 }
1036
1037 /* advance to the endpoints */
David Ahern27911042010-04-24 10:26:22 -06001038 while (i < length && descriptors[i +1] != USB_DT_ENDPOINT) {
balrogb9dc0332007-10-04 22:47:34 +00001039 i += descriptors[i];
David Ahern27911042010-04-24 10:26:22 -06001040 }
balrogb9dc0332007-10-04 22:47:34 +00001041
1042 if (i >= length)
1043 break;
1044
1045 while (i < length) {
David Ahern27911042010-04-24 10:26:22 -06001046 if (descriptors[i + 1] != USB_DT_ENDPOINT) {
balrogb9dc0332007-10-04 22:47:34 +00001047 break;
David Ahern27911042010-04-24 10:26:22 -06001048 }
balrogb9dc0332007-10-04 22:47:34 +00001049
1050 devep = descriptors[i + 2];
Hans de Goede130314f2011-05-31 11:35:22 +02001051 if ((devep & 0x0f) == 0) {
1052 fprintf(stderr, "usb-linux: invalid ep descriptor, ep == 0\n");
1053 return 1;
1054 }
1055
balrogb9dc0332007-10-04 22:47:34 +00001056 switch (descriptors[i + 3] & 0x3) {
1057 case 0x00:
1058 type = USBDEVFS_URB_TYPE_CONTROL;
1059 break;
1060 case 0x01:
1061 type = USBDEVFS_URB_TYPE_ISO;
Gerd Hoffmann6dfcdcc2011-05-16 11:30:57 +02001062 set_max_packet_size(s, (devep & 0xf), descriptors + i);
balrogb9dc0332007-10-04 22:47:34 +00001063 break;
1064 case 0x02:
1065 type = USBDEVFS_URB_TYPE_BULK;
1066 break;
1067 case 0x03:
1068 type = USBDEVFS_URB_TYPE_INTERRUPT;
1069 break;
Anthony Liguoriddbda432010-03-17 16:00:24 -05001070 default:
1071 DPRINTF("usb_host: malformed endpoint type\n");
1072 type = USBDEVFS_URB_TYPE_BULK;
balrogb9dc0332007-10-04 22:47:34 +00001073 }
1074 s->endp_table[(devep & 0xf) - 1].type = type;
aliguori64838172008-08-21 19:31:10 +00001075 s->endp_table[(devep & 0xf) - 1].halted = 0;
balrogb9dc0332007-10-04 22:47:34 +00001076
1077 i += descriptors[i];
1078 }
1079 }
1080 return 0;
1081}
1082
Hans de Goedee4b17762011-05-30 11:40:45 +02001083/*
1084 * Check if we can safely redirect a usb2 device to a usb1 virtual controller,
1085 * this function assumes this is safe, if:
1086 * 1) There are no isoc endpoints
1087 * 2) There are no interrupt endpoints with a max_packet_size > 64
1088 * Note bulk endpoints with a max_packet_size > 64 in theory also are not
1089 * usb1 compatible, but in practice this seems to work fine.
1090 */
1091static int usb_linux_full_speed_compat(USBHostDevice *dev)
1092{
1093 int i, packet_size;
1094
1095 /*
1096 * usb_linux_update_endp_table only registers info about ep in the current
1097 * interface altsettings, so we need to parse the descriptors again.
1098 */
1099 for (i = 0; (i + 5) < dev->descr_len; i += dev->descr[i]) {
1100 if (dev->descr[i + 1] == USB_DT_ENDPOINT) {
1101 switch (dev->descr[i + 3] & 0x3) {
1102 case 0x00: /* CONTROL */
1103 break;
1104 case 0x01: /* ISO */
1105 return 0;
1106 case 0x02: /* BULK */
1107 break;
1108 case 0x03: /* INTERRUPT */
1109 packet_size = dev->descr[i + 4] + (dev->descr[i + 5] << 8);
1110 if (packet_size > 64)
1111 return 0;
1112 break;
1113 }
1114 }
1115 }
1116 return 1;
1117}
1118
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001119static int usb_host_open(USBHostDevice *dev, int bus_num,
Hans de Goede3991c352011-05-31 11:35:18 +02001120 int addr, char *port, const char *prod_name, int speed)
bellardbb36d472005-11-05 14:22:28 +00001121{
balrogb9dc0332007-10-04 22:47:34 +00001122 int fd = -1, ret;
bellarda594cfb2005-11-06 16:13:29 +00001123 char buf[1024];
aliguori1f3870a2008-08-21 19:27:48 +00001124
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +02001125 trace_usb_host_open_started(bus_num, addr);
1126
David Ahern27911042010-04-24 10:26:22 -06001127 if (dev->fd != -1) {
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001128 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001129 }
aliguori1f3870a2008-08-21 19:27:48 +00001130
aliguori0f431522008-10-07 20:06:37 +00001131 if (!usb_host_device_path) {
1132 perror("husb: USB Host Device Path not set");
1133 goto fail;
1134 }
1135 snprintf(buf, sizeof(buf), "%s/%03d/%03d", usb_host_device_path,
bellarda594cfb2005-11-06 16:13:29 +00001136 bus_num, addr);
balrogb9dc0332007-10-04 22:47:34 +00001137 fd = open(buf, O_RDWR | O_NONBLOCK);
bellardbb36d472005-11-05 14:22:28 +00001138 if (fd < 0) {
bellarda594cfb2005-11-06 16:13:29 +00001139 perror(buf);
aliguori1f3870a2008-08-21 19:27:48 +00001140 goto fail;
bellardbb36d472005-11-05 14:22:28 +00001141 }
malcd0f2c4c2010-02-07 02:03:50 +03001142 DPRINTF("husb: opened %s\n", buf);
bellardbb36d472005-11-05 14:22:28 +00001143
Gerd Hoffmann806b6022009-08-31 14:23:59 +02001144 dev->bus_num = bus_num;
1145 dev->addr = addr;
Gerd Hoffmann5557d822011-05-10 11:43:57 +02001146 strcpy(dev->port, port);
Gerd Hoffmann22f84e72009-09-25 16:55:28 +02001147 dev->fd = fd;
Gerd Hoffmann806b6022009-08-31 14:23:59 +02001148
balrogb9dc0332007-10-04 22:47:34 +00001149 /* read the device description */
1150 dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
1151 if (dev->descr_len <= 0) {
aliguori64838172008-08-21 19:31:10 +00001152 perror("husb: reading device data failed");
bellardbb36d472005-11-05 14:22:28 +00001153 goto fail;
1154 }
ths3b46e622007-09-17 08:09:54 +00001155
balrogb9dc0332007-10-04 22:47:34 +00001156#ifdef DEBUG
bellard868bfe22005-11-13 21:53:15 +00001157 {
balrogb9dc0332007-10-04 22:47:34 +00001158 int x;
1159 printf("=== begin dumping device descriptor data ===\n");
David Ahern27911042010-04-24 10:26:22 -06001160 for (x = 0; x < dev->descr_len; x++) {
balrogb9dc0332007-10-04 22:47:34 +00001161 printf("%02x ", dev->descr[x]);
David Ahern27911042010-04-24 10:26:22 -06001162 }
balrogb9dc0332007-10-04 22:47:34 +00001163 printf("\n=== end dumping device descriptor data ===\n");
bellarda594cfb2005-11-06 16:13:29 +00001164 }
1165#endif
1166
balrogb9dc0332007-10-04 22:47:34 +00001167
Gerd Hoffmanneb7700b2011-08-24 14:45:07 +02001168 /* start unconfigured -- we'll wait for the guest to set a configuration */
1169 if (!usb_host_claim_interfaces(dev, 0)) {
balrogb9dc0332007-10-04 22:47:34 +00001170 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001171 }
bellardbb36d472005-11-05 14:22:28 +00001172
balrogb9dc0332007-10-04 22:47:34 +00001173 ret = usb_linux_update_endp_table(dev);
David Ahern27911042010-04-24 10:26:22 -06001174 if (ret) {
bellardbb36d472005-11-05 14:22:28 +00001175 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001176 }
balrogb9dc0332007-10-04 22:47:34 +00001177
Hans de Goede3991c352011-05-31 11:35:18 +02001178 if (speed == -1) {
1179 struct usbdevfs_connectinfo ci;
1180
1181 ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
1182 if (ret < 0) {
1183 perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
1184 goto fail;
1185 }
1186
1187 if (ci.slow) {
1188 speed = USB_SPEED_LOW;
1189 } else {
1190 speed = USB_SPEED_HIGH;
1191 }
David Ahern27911042010-04-24 10:26:22 -06001192 }
Hans de Goede3991c352011-05-31 11:35:18 +02001193 dev->dev.speed = speed;
Hans de Goedeba3f9bf2011-05-27 14:27:18 +02001194 dev->dev.speedmask = (1 << speed);
Hans de Goedee4b17762011-05-30 11:40:45 +02001195 if (dev->dev.speed == USB_SPEED_HIGH && usb_linux_full_speed_compat(dev)) {
1196 dev->dev.speedmask |= USB_SPEED_MASK_FULL;
1197 }
Hans de Goede3991c352011-05-31 11:35:18 +02001198
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +02001199 trace_usb_host_open_success(bus_num, addr);
bellardbb36d472005-11-05 14:22:28 +00001200
David Ahern27911042010-04-24 10:26:22 -06001201 if (!prod_name || prod_name[0] == '\0') {
Markus Armbruster0fe6d122009-12-09 17:07:51 +01001202 snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
aliguori4b096fc2008-08-21 19:28:55 +00001203 "host:%d.%d", bus_num, addr);
David Ahern27911042010-04-24 10:26:22 -06001204 } else {
Markus Armbruster0fe6d122009-12-09 17:07:51 +01001205 pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
aliguori4b096fc2008-08-21 19:28:55 +00001206 prod_name);
David Ahern27911042010-04-24 10:26:22 -06001207 }
bellard1f6e24e2006-06-26 21:00:51 +00001208
Hans de Goedefa19bf82011-05-27 19:05:15 +02001209 ret = usb_device_attach(&dev->dev);
1210 if (ret) {
1211 goto fail;
1212 }
1213
aliguori64838172008-08-21 19:31:10 +00001214 /* USB devio uses 'write' flag to check for async completions */
1215 qemu_set_fd_handler(dev->fd, NULL, async_complete, dev);
aliguori1f3870a2008-08-21 19:27:48 +00001216
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001217 return 0;
aliguori4b096fc2008-08-21 19:28:55 +00001218
balrogb9dc0332007-10-04 22:47:34 +00001219fail:
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +02001220 trace_usb_host_open_failure(bus_num, addr);
Gerd Hoffmann1f45a812011-06-06 09:45:20 +02001221 if (dev->fd != -1) {
1222 close(dev->fd);
1223 dev->fd = -1;
David Ahern27911042010-04-24 10:26:22 -06001224 }
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001225 return -1;
1226}
1227
1228static int usb_host_close(USBHostDevice *dev)
1229{
Hans de Goede060dc842010-11-26 11:41:08 +01001230 int i;
1231
Gerd Hoffmann1f45a812011-06-06 09:45:20 +02001232 if (dev->fd == -1 || !dev->dev.attached) {
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001233 return -1;
David Ahern27911042010-04-24 10:26:22 -06001234 }
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001235
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +02001236 trace_usb_host_close(dev->bus_num, dev->addr);
1237
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001238 qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
1239 dev->closing = 1;
Hans de Goede3a4854b2010-11-26 15:02:16 +01001240 for (i = 1; i <= MAX_ENDPOINTS; i++) {
Hans de Goede060dc842010-11-26 11:41:08 +01001241 if (is_isoc(dev, i)) {
1242 usb_host_stop_n_free_iso(dev, i);
1243 }
1244 }
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001245 async_complete(dev);
1246 dev->closing = 0;
1247 usb_device_detach(&dev->dev);
Shahar Havivi00ff2272010-06-16 15:15:37 +03001248 ioctl(dev->fd, USBDEVFS_RESET);
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001249 close(dev->fd);
1250 dev->fd = -1;
1251 return 0;
1252}
1253
Jan Kiszka9e8dd452011-06-20 14:06:26 +02001254static void usb_host_exit_notifier(struct Notifier *n, void *data)
Shahar Havivib373a632010-06-16 15:16:11 +03001255{
1256 USBHostDevice *s = container_of(n, USBHostDevice, exit);
1257
1258 if (s->fd != -1) {
1259 ioctl(s->fd, USBDEVFS_RESET);
1260 }
1261}
1262
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001263static int usb_host_initfn(USBDevice *dev)
1264{
1265 USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
1266
1267 dev->auto_attach = 0;
1268 s->fd = -1;
1269 QTAILQ_INSERT_TAIL(&hostdevs, s, next);
Shahar Havivib373a632010-06-16 15:16:11 +03001270 s->exit.notify = usb_host_exit_notifier;
1271 qemu_add_exit_notifier(&s->exit);
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001272 usb_host_auto_check(NULL);
1273 return 0;
bellardbb36d472005-11-05 14:22:28 +00001274}
1275
Gerd Hoffmann806b6022009-08-31 14:23:59 +02001276static struct USBDeviceInfo usb_host_dev_info = {
Markus Armbruster06384692009-12-09 17:07:52 +01001277 .product_desc = "USB Host Device",
Markus Armbruster556cd092009-12-09 17:07:53 +01001278 .qdev.name = "usb-host",
Gerd Hoffmann806b6022009-08-31 14:23:59 +02001279 .qdev.size = sizeof(USBHostDevice),
1280 .init = usb_host_initfn,
Hans de Goede50b79632011-02-02 17:36:29 +01001281 .handle_packet = usb_generic_handle_packet,
Gerd Hoffmanneb5e6802011-05-16 10:34:53 +02001282 .cancel_packet = usb_host_async_cancel,
Hans de Goede50b79632011-02-02 17:36:29 +01001283 .handle_data = usb_host_handle_data,
1284 .handle_control = usb_host_handle_control,
Gerd Hoffmann806b6022009-08-31 14:23:59 +02001285 .handle_reset = usb_host_handle_reset,
Gerd Hoffmann806b6022009-08-31 14:23:59 +02001286 .handle_destroy = usb_host_handle_destroy,
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001287 .usbdevice_name = "host",
1288 .usbdevice_init = usb_host_device_open,
1289 .qdev.props = (Property[]) {
1290 DEFINE_PROP_UINT32("hostbus", USBHostDevice, match.bus_num, 0),
1291 DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr, 0),
Gerd Hoffmann9056a292011-05-10 12:07:42 +02001292 DEFINE_PROP_STRING("hostport", USBHostDevice, match.port),
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001293 DEFINE_PROP_HEX32("vendorid", USBHostDevice, match.vendor_id, 0),
1294 DEFINE_PROP_HEX32("productid", USBHostDevice, match.product_id, 0),
Gerd Hoffmannb81bcd82011-06-10 14:03:56 +02001295 DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4),
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001296 DEFINE_PROP_END_OF_LIST(),
1297 },
Gerd Hoffmann806b6022009-08-31 14:23:59 +02001298};
1299
1300static void usb_host_register_devices(void)
1301{
1302 usb_qdev_register(&usb_host_dev_info);
1303}
1304device_init(usb_host_register_devices)
1305
aliguori4b096fc2008-08-21 19:28:55 +00001306USBDevice *usb_host_device_open(const char *devname)
1307{
Markus Armbruster0745eb12009-11-27 13:05:53 +01001308 struct USBAutoFilter filter;
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001309 USBDevice *dev;
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001310 char *p;
1311
Markus Armbruster556cd092009-12-09 17:07:53 +01001312 dev = usb_create(NULL /* FIXME */, "usb-host");
aliguori4b096fc2008-08-21 19:28:55 +00001313
aliguori5d0c5752008-09-14 01:07:41 +00001314 if (strstr(devname, "auto:")) {
David Ahern27911042010-04-24 10:26:22 -06001315 if (parse_filter(devname, &filter) < 0) {
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001316 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001317 }
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001318 } else {
1319 if ((p = strchr(devname, '.'))) {
Markus Armbruster0745eb12009-11-27 13:05:53 +01001320 filter.bus_num = strtoul(devname, NULL, 0);
1321 filter.addr = strtoul(p + 1, NULL, 0);
1322 filter.vendor_id = 0;
1323 filter.product_id = 0;
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001324 } else if ((p = strchr(devname, ':'))) {
Markus Armbruster0745eb12009-11-27 13:05:53 +01001325 filter.bus_num = 0;
1326 filter.addr = 0;
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001327 filter.vendor_id = strtoul(devname, NULL, 16);
Markus Armbruster0745eb12009-11-27 13:05:53 +01001328 filter.product_id = strtoul(p + 1, NULL, 16);
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001329 } else {
1330 goto fail;
1331 }
aliguori5d0c5752008-09-14 01:07:41 +00001332 }
1333
Markus Armbruster0745eb12009-11-27 13:05:53 +01001334 qdev_prop_set_uint32(&dev->qdev, "hostbus", filter.bus_num);
1335 qdev_prop_set_uint32(&dev->qdev, "hostaddr", filter.addr);
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001336 qdev_prop_set_uint32(&dev->qdev, "vendorid", filter.vendor_id);
1337 qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id);
Kevin Wolfbeb6f0d2010-01-15 12:56:41 +01001338 qdev_init_nofail(&dev->qdev);
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001339 return dev;
aliguori4b096fc2008-08-21 19:28:55 +00001340
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001341fail:
1342 qdev_free(&dev->qdev);
1343 return NULL;
aliguori4b096fc2008-08-21 19:28:55 +00001344}
aliguori5d0c5752008-09-14 01:07:41 +00001345
1346int usb_host_device_close(const char *devname)
1347{
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001348#if 0
aliguori5d0c5752008-09-14 01:07:41 +00001349 char product_name[PRODUCT_NAME_SZ];
1350 int bus_num, addr;
1351 USBHostDevice *s;
1352
David Ahern27911042010-04-24 10:26:22 -06001353 if (strstr(devname, "auto:")) {
aliguori5d0c5752008-09-14 01:07:41 +00001354 return usb_host_auto_del(devname);
David Ahern27911042010-04-24 10:26:22 -06001355 }
1356 if (usb_host_find_device(&bus_num, &addr, product_name,
1357 sizeof(product_name), devname) < 0) {
aliguori5d0c5752008-09-14 01:07:41 +00001358 return -1;
David Ahern27911042010-04-24 10:26:22 -06001359 }
aliguori5d0c5752008-09-14 01:07:41 +00001360 s = hostdev_find(bus_num, addr);
1361 if (s) {
Gerd Hoffmanna5d2f722009-08-31 14:24:00 +02001362 usb_device_delete_addr(s->bus_num, s->dev.addr);
aliguori5d0c5752008-09-14 01:07:41 +00001363 return 0;
1364 }
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001365#endif
aliguori5d0c5752008-09-14 01:07:41 +00001366
1367 return -1;
1368}
Gerd Hoffmanna5d2f722009-08-31 14:24:00 +02001369
bellarda594cfb2005-11-06 16:13:29 +00001370static int get_tag_value(char *buf, int buf_size,
ths5fafdf22007-09-16 21:08:06 +00001371 const char *str, const char *tag,
bellarda594cfb2005-11-06 16:13:29 +00001372 const char *stopchars)
bellardbb36d472005-11-05 14:22:28 +00001373{
bellarda594cfb2005-11-06 16:13:29 +00001374 const char *p;
1375 char *q;
1376 p = strstr(str, tag);
David Ahern27911042010-04-24 10:26:22 -06001377 if (!p) {
bellarda594cfb2005-11-06 16:13:29 +00001378 return -1;
David Ahern27911042010-04-24 10:26:22 -06001379 }
bellarda594cfb2005-11-06 16:13:29 +00001380 p += strlen(tag);
David Ahern27911042010-04-24 10:26:22 -06001381 while (qemu_isspace(*p)) {
bellarda594cfb2005-11-06 16:13:29 +00001382 p++;
David Ahern27911042010-04-24 10:26:22 -06001383 }
bellarda594cfb2005-11-06 16:13:29 +00001384 q = buf;
1385 while (*p != '\0' && !strchr(stopchars, *p)) {
David Ahern27911042010-04-24 10:26:22 -06001386 if ((q - buf) < (buf_size - 1)) {
bellarda594cfb2005-11-06 16:13:29 +00001387 *q++ = *p;
David Ahern27911042010-04-24 10:26:22 -06001388 }
bellarda594cfb2005-11-06 16:13:29 +00001389 p++;
1390 }
1391 *q = '\0';
1392 return q - buf;
1393}
bellardbb36d472005-11-05 14:22:28 +00001394
aliguori0f431522008-10-07 20:06:37 +00001395/*
1396 * Use /proc/bus/usb/devices or /dev/bus/usb/devices file to determine
1397 * host's USB devices. This is legacy support since many distributions
1398 * are moving to /sys/bus/usb
1399 */
1400static int usb_host_scan_dev(void *opaque, USBScanFunc *func)
bellarda594cfb2005-11-06 16:13:29 +00001401{
Blue Swirl660f11b2009-07-31 21:16:51 +00001402 FILE *f = NULL;
bellarda594cfb2005-11-06 16:13:29 +00001403 char line[1024];
1404 char buf[1024];
1405 int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
bellarda594cfb2005-11-06 16:13:29 +00001406 char product_name[512];
aliguori0f431522008-10-07 20:06:37 +00001407 int ret = 0;
ths3b46e622007-09-17 08:09:54 +00001408
aliguori0f431522008-10-07 20:06:37 +00001409 if (!usb_host_device_path) {
1410 perror("husb: USB Host Device Path not set");
1411 goto the_end;
bellarda594cfb2005-11-06 16:13:29 +00001412 }
aliguori0f431522008-10-07 20:06:37 +00001413 snprintf(line, sizeof(line), "%s/devices", usb_host_device_path);
1414 f = fopen(line, "r");
1415 if (!f) {
1416 perror("husb: cannot open devices file");
1417 goto the_end;
1418 }
1419
bellarda594cfb2005-11-06 16:13:29 +00001420 device_count = 0;
Hans de Goede3991c352011-05-31 11:35:18 +02001421 bus_num = addr = class_id = product_id = vendor_id = 0;
1422 speed = -1; /* Can't get the speed from /[proc|dev]/bus/usb/devices */
bellardbb36d472005-11-05 14:22:28 +00001423 for(;;) {
David Ahern27911042010-04-24 10:26:22 -06001424 if (fgets(line, sizeof(line), f) == NULL) {
bellardbb36d472005-11-05 14:22:28 +00001425 break;
David Ahern27911042010-04-24 10:26:22 -06001426 }
1427 if (strlen(line) > 0) {
bellarda594cfb2005-11-06 16:13:29 +00001428 line[strlen(line) - 1] = '\0';
David Ahern27911042010-04-24 10:26:22 -06001429 }
bellarda594cfb2005-11-06 16:13:29 +00001430 if (line[0] == 'T' && line[1] == ':') {
pbrook38ca0f62006-03-11 18:03:38 +00001431 if (device_count && (vendor_id || product_id)) {
1432 /* New device. Add the previously discovered device. */
Hans de Goede0f5160d2010-11-10 10:06:23 +01001433 ret = func(opaque, bus_num, addr, 0, class_id, vendor_id,
bellarda594cfb2005-11-06 16:13:29 +00001434 product_id, product_name, speed);
David Ahern27911042010-04-24 10:26:22 -06001435 if (ret) {
bellarda594cfb2005-11-06 16:13:29 +00001436 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001437 }
bellarda594cfb2005-11-06 16:13:29 +00001438 }
David Ahern27911042010-04-24 10:26:22 -06001439 if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0) {
bellarda594cfb2005-11-06 16:13:29 +00001440 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001441 }
bellarda594cfb2005-11-06 16:13:29 +00001442 bus_num = atoi(buf);
David Ahern27911042010-04-24 10:26:22 -06001443 if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0) {
bellarda594cfb2005-11-06 16:13:29 +00001444 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001445 }
bellarda594cfb2005-11-06 16:13:29 +00001446 addr = atoi(buf);
David Ahern27911042010-04-24 10:26:22 -06001447 if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0) {
bellarda594cfb2005-11-06 16:13:29 +00001448 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001449 }
Hans de Goedef264cfb2011-05-31 11:35:19 +02001450 if (!strcmp(buf, "5000")) {
1451 speed = USB_SPEED_SUPER;
1452 } else if (!strcmp(buf, "480")) {
bellarda594cfb2005-11-06 16:13:29 +00001453 speed = USB_SPEED_HIGH;
David Ahern27911042010-04-24 10:26:22 -06001454 } else if (!strcmp(buf, "1.5")) {
bellarda594cfb2005-11-06 16:13:29 +00001455 speed = USB_SPEED_LOW;
David Ahern27911042010-04-24 10:26:22 -06001456 } else {
bellarda594cfb2005-11-06 16:13:29 +00001457 speed = USB_SPEED_FULL;
David Ahern27911042010-04-24 10:26:22 -06001458 }
bellarda594cfb2005-11-06 16:13:29 +00001459 product_name[0] = '\0';
1460 class_id = 0xff;
1461 device_count++;
1462 product_id = 0;
1463 vendor_id = 0;
1464 } else if (line[0] == 'P' && line[1] == ':') {
David Ahern27911042010-04-24 10:26:22 -06001465 if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0) {
bellarda594cfb2005-11-06 16:13:29 +00001466 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001467 }
bellarda594cfb2005-11-06 16:13:29 +00001468 vendor_id = strtoul(buf, NULL, 16);
David Ahern27911042010-04-24 10:26:22 -06001469 if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0) {
bellarda594cfb2005-11-06 16:13:29 +00001470 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001471 }
bellarda594cfb2005-11-06 16:13:29 +00001472 product_id = strtoul(buf, NULL, 16);
1473 } else if (line[0] == 'S' && line[1] == ':') {
David Ahern27911042010-04-24 10:26:22 -06001474 if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0) {
bellarda594cfb2005-11-06 16:13:29 +00001475 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001476 }
bellarda594cfb2005-11-06 16:13:29 +00001477 pstrcpy(product_name, sizeof(product_name), buf);
1478 } else if (line[0] == 'D' && line[1] == ':') {
David Ahern27911042010-04-24 10:26:22 -06001479 if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0) {
bellarda594cfb2005-11-06 16:13:29 +00001480 goto fail;
David Ahern27911042010-04-24 10:26:22 -06001481 }
bellarda594cfb2005-11-06 16:13:29 +00001482 class_id = strtoul(buf, NULL, 16);
1483 }
1484 fail: ;
1485 }
pbrook38ca0f62006-03-11 18:03:38 +00001486 if (device_count && (vendor_id || product_id)) {
1487 /* Add the last device. */
Hans de Goede0f5160d2010-11-10 10:06:23 +01001488 ret = func(opaque, bus_num, addr, 0, class_id, vendor_id,
bellarda594cfb2005-11-06 16:13:29 +00001489 product_id, product_name, speed);
1490 }
1491 the_end:
David Ahern27911042010-04-24 10:26:22 -06001492 if (f) {
aliguori0f431522008-10-07 20:06:37 +00001493 fclose(f);
David Ahern27911042010-04-24 10:26:22 -06001494 }
aliguori0f431522008-10-07 20:06:37 +00001495 return ret;
1496}
1497
1498/*
1499 * Read sys file-system device file
1500 *
1501 * @line address of buffer to put file contents in
1502 * @line_size size of line
1503 * @device_file path to device file (printf format string)
1504 * @device_name device being opened (inserted into device_file)
1505 *
1506 * @return 0 failed, 1 succeeded ('line' contains data)
1507 */
David Ahern27911042010-04-24 10:26:22 -06001508static int usb_host_read_file(char *line, size_t line_size,
1509 const char *device_file, const char *device_name)
aliguori0f431522008-10-07 20:06:37 +00001510{
1511 FILE *f;
1512 int ret = 0;
1513 char filename[PATH_MAX];
1514
blueswir1b4e237a2008-12-28 15:45:20 +00001515 snprintf(filename, PATH_MAX, USBSYSBUS_PATH "/devices/%s/%s", device_name,
1516 device_file);
aliguori0f431522008-10-07 20:06:37 +00001517 f = fopen(filename, "r");
1518 if (f) {
Kirill A. Shutemov9f99cee2010-01-20 00:56:17 +01001519 ret = fgets(line, line_size, f) != NULL;
aliguori0f431522008-10-07 20:06:37 +00001520 fclose(f);
aliguori0f431522008-10-07 20:06:37 +00001521 }
1522
1523 return ret;
1524}
1525
1526/*
1527 * Use /sys/bus/usb/devices/ directory to determine host's USB
1528 * devices.
1529 *
1530 * This code is based on Robert Schiele's original patches posted to
1531 * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950
1532 */
1533static int usb_host_scan_sys(void *opaque, USBScanFunc *func)
1534{
Blue Swirl660f11b2009-07-31 21:16:51 +00001535 DIR *dir = NULL;
aliguori0f431522008-10-07 20:06:37 +00001536 char line[1024];
Gerd Hoffmann5557d822011-05-10 11:43:57 +02001537 int bus_num, addr, speed, class_id, product_id, vendor_id;
aliguori0f431522008-10-07 20:06:37 +00001538 int ret = 0;
Gerd Hoffmann5557d822011-05-10 11:43:57 +02001539 char port[MAX_PORTLEN];
aliguori0f431522008-10-07 20:06:37 +00001540 char product_name[512];
1541 struct dirent *de;
1542
1543 dir = opendir(USBSYSBUS_PATH "/devices");
1544 if (!dir) {
1545 perror("husb: cannot open devices directory");
1546 goto the_end;
1547 }
1548
1549 while ((de = readdir(dir))) {
1550 if (de->d_name[0] != '.' && !strchr(de->d_name, ':')) {
Gerd Hoffmann5557d822011-05-10 11:43:57 +02001551 if (sscanf(de->d_name, "%d-%7[0-9.]", &bus_num, port) < 2) {
1552 continue;
Hans de Goede0f5160d2010-11-10 10:06:23 +01001553 }
aliguori0f431522008-10-07 20:06:37 +00001554
David Ahern27911042010-04-24 10:26:22 -06001555 if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name)) {
aliguori0f431522008-10-07 20:06:37 +00001556 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001557 }
1558 if (sscanf(line, "%d", &addr) != 1) {
aliguori0f431522008-10-07 20:06:37 +00001559 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001560 }
blueswir1b4e237a2008-12-28 15:45:20 +00001561 if (!usb_host_read_file(line, sizeof(line), "bDeviceClass",
David Ahern27911042010-04-24 10:26:22 -06001562 de->d_name)) {
aliguori0f431522008-10-07 20:06:37 +00001563 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001564 }
1565 if (sscanf(line, "%x", &class_id) != 1) {
aliguori0f431522008-10-07 20:06:37 +00001566 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001567 }
aliguori0f431522008-10-07 20:06:37 +00001568
David Ahern27911042010-04-24 10:26:22 -06001569 if (!usb_host_read_file(line, sizeof(line), "idVendor",
1570 de->d_name)) {
aliguori0f431522008-10-07 20:06:37 +00001571 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001572 }
1573 if (sscanf(line, "%x", &vendor_id) != 1) {
aliguori0f431522008-10-07 20:06:37 +00001574 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001575 }
blueswir1b4e237a2008-12-28 15:45:20 +00001576 if (!usb_host_read_file(line, sizeof(line), "idProduct",
David Ahern27911042010-04-24 10:26:22 -06001577 de->d_name)) {
aliguori0f431522008-10-07 20:06:37 +00001578 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001579 }
1580 if (sscanf(line, "%x", &product_id) != 1) {
aliguori0f431522008-10-07 20:06:37 +00001581 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001582 }
blueswir1b4e237a2008-12-28 15:45:20 +00001583 if (!usb_host_read_file(line, sizeof(line), "product",
1584 de->d_name)) {
aliguori0f431522008-10-07 20:06:37 +00001585 *product_name = 0;
1586 } else {
David Ahern27911042010-04-24 10:26:22 -06001587 if (strlen(line) > 0) {
aliguori0f431522008-10-07 20:06:37 +00001588 line[strlen(line) - 1] = '\0';
David Ahern27911042010-04-24 10:26:22 -06001589 }
aliguori0f431522008-10-07 20:06:37 +00001590 pstrcpy(product_name, sizeof(product_name), line);
1591 }
1592
David Ahern27911042010-04-24 10:26:22 -06001593 if (!usb_host_read_file(line, sizeof(line), "speed", de->d_name)) {
aliguori0f431522008-10-07 20:06:37 +00001594 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001595 }
Hans de Goedef264cfb2011-05-31 11:35:19 +02001596 if (!strcmp(line, "5000\n")) {
1597 speed = USB_SPEED_SUPER;
1598 } else if (!strcmp(line, "480\n")) {
aliguori0f431522008-10-07 20:06:37 +00001599 speed = USB_SPEED_HIGH;
David Ahern27911042010-04-24 10:26:22 -06001600 } else if (!strcmp(line, "1.5\n")) {
aliguori0f431522008-10-07 20:06:37 +00001601 speed = USB_SPEED_LOW;
David Ahern27911042010-04-24 10:26:22 -06001602 } else {
aliguori0f431522008-10-07 20:06:37 +00001603 speed = USB_SPEED_FULL;
David Ahern27911042010-04-24 10:26:22 -06001604 }
aliguori0f431522008-10-07 20:06:37 +00001605
Gerd Hoffmann5557d822011-05-10 11:43:57 +02001606 ret = func(opaque, bus_num, addr, port, class_id, vendor_id,
aliguori0f431522008-10-07 20:06:37 +00001607 product_id, product_name, speed);
David Ahern27911042010-04-24 10:26:22 -06001608 if (ret) {
aliguori0f431522008-10-07 20:06:37 +00001609 goto the_end;
David Ahern27911042010-04-24 10:26:22 -06001610 }
aliguori0f431522008-10-07 20:06:37 +00001611 }
1612 }
1613 the_end:
David Ahern27911042010-04-24 10:26:22 -06001614 if (dir) {
aliguori0f431522008-10-07 20:06:37 +00001615 closedir(dir);
David Ahern27911042010-04-24 10:26:22 -06001616 }
aliguori0f431522008-10-07 20:06:37 +00001617 return ret;
1618}
1619
1620/*
1621 * Determine how to access the host's USB devices and call the
1622 * specific support function.
1623 */
1624static int usb_host_scan(void *opaque, USBScanFunc *func)
1625{
aliguori376253e2009-03-05 23:01:23 +00001626 Monitor *mon = cur_mon;
Blue Swirl660f11b2009-07-31 21:16:51 +00001627 FILE *f = NULL;
1628 DIR *dir = NULL;
aliguori0f431522008-10-07 20:06:37 +00001629 int ret = 0;
aliguori0f431522008-10-07 20:06:37 +00001630 const char *fs_type[] = {"unknown", "proc", "dev", "sys"};
1631 char devpath[PATH_MAX];
1632
1633 /* only check the host once */
1634 if (!usb_fs_type) {
Mark McLoughlin55496242009-07-03 09:28:02 +01001635 dir = opendir(USBSYSBUS_PATH "/devices");
1636 if (dir) {
1637 /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
1638 strcpy(devpath, USBDEVBUS_PATH);
1639 usb_fs_type = USB_FS_SYS;
1640 closedir(dir);
malcd0f2c4c2010-02-07 02:03:50 +03001641 DPRINTF(USBDBG_DEVOPENED, USBSYSBUS_PATH);
Mark McLoughlin55496242009-07-03 09:28:02 +01001642 goto found_devices;
1643 }
aliguori0f431522008-10-07 20:06:37 +00001644 f = fopen(USBPROCBUS_PATH "/devices", "r");
1645 if (f) {
1646 /* devices found in /proc/bus/usb/ */
1647 strcpy(devpath, USBPROCBUS_PATH);
1648 usb_fs_type = USB_FS_PROC;
1649 fclose(f);
malcd0f2c4c2010-02-07 02:03:50 +03001650 DPRINTF(USBDBG_DEVOPENED, USBPROCBUS_PATH);
aliguorif16a0db2008-10-21 16:34:20 +00001651 goto found_devices;
aliguori0f431522008-10-07 20:06:37 +00001652 }
1653 /* try additional methods if an access method hasn't been found yet */
1654 f = fopen(USBDEVBUS_PATH "/devices", "r");
aliguorif16a0db2008-10-21 16:34:20 +00001655 if (f) {
aliguori0f431522008-10-07 20:06:37 +00001656 /* devices found in /dev/bus/usb/ */
1657 strcpy(devpath, USBDEVBUS_PATH);
1658 usb_fs_type = USB_FS_DEV;
1659 fclose(f);
malcd0f2c4c2010-02-07 02:03:50 +03001660 DPRINTF(USBDBG_DEVOPENED, USBDEVBUS_PATH);
aliguorif16a0db2008-10-21 16:34:20 +00001661 goto found_devices;
aliguori0f431522008-10-07 20:06:37 +00001662 }
aliguorif16a0db2008-10-21 16:34:20 +00001663 found_devices:
aliguori22babeb2008-10-21 16:27:28 +00001664 if (!usb_fs_type) {
David Ahern27911042010-04-24 10:26:22 -06001665 if (mon) {
Gerd Hoffmanneba6fe82009-12-15 11:43:02 +01001666 monitor_printf(mon, "husb: unable to access USB devices\n");
David Ahern27911042010-04-24 10:26:22 -06001667 }
aliguorif16a0db2008-10-21 16:34:20 +00001668 return -ENOENT;
aliguori0f431522008-10-07 20:06:37 +00001669 }
1670
1671 /* the module setting (used later for opening devices) */
Anthony Liguori7267c092011-08-20 22:09:37 -05001672 usb_host_device_path = g_malloc0(strlen(devpath)+1);
aliguori1eec6142009-02-05 22:06:18 +00001673 strcpy(usb_host_device_path, devpath);
David Ahern27911042010-04-24 10:26:22 -06001674 if (mon) {
Gerd Hoffmanneba6fe82009-12-15 11:43:02 +01001675 monitor_printf(mon, "husb: using %s file-system with %s\n",
1676 fs_type[usb_fs_type], usb_host_device_path);
David Ahern27911042010-04-24 10:26:22 -06001677 }
aliguori0f431522008-10-07 20:06:37 +00001678 }
1679
1680 switch (usb_fs_type) {
1681 case USB_FS_PROC:
1682 case USB_FS_DEV:
1683 ret = usb_host_scan_dev(opaque, func);
1684 break;
1685 case USB_FS_SYS:
1686 ret = usb_host_scan_sys(opaque, func);
1687 break;
aliguorif16a0db2008-10-21 16:34:20 +00001688 default:
1689 ret = -EINVAL;
1690 break;
aliguori0f431522008-10-07 20:06:37 +00001691 }
bellarda594cfb2005-11-06 16:13:29 +00001692 return ret;
1693}
1694
aliguori4b096fc2008-08-21 19:28:55 +00001695static QEMUTimer *usb_auto_timer;
aliguori4b096fc2008-08-21 19:28:55 +00001696
Gerd Hoffmann5557d822011-05-10 11:43:57 +02001697static int usb_host_auto_scan(void *opaque, int bus_num, int addr, char *port,
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001698 int class_id, int vendor_id, int product_id,
1699 const char *product_name, int speed)
aliguori4b096fc2008-08-21 19:28:55 +00001700{
1701 struct USBAutoFilter *f;
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001702 struct USBHostDevice *s;
aliguori4b096fc2008-08-21 19:28:55 +00001703
1704 /* Ignore hubs */
1705 if (class_id == 9)
1706 return 0;
1707
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001708 QTAILQ_FOREACH(s, &hostdevs, next) {
1709 f = &s->match;
1710
David Ahern27911042010-04-24 10:26:22 -06001711 if (f->bus_num > 0 && f->bus_num != bus_num) {
aliguori4b096fc2008-08-21 19:28:55 +00001712 continue;
David Ahern27911042010-04-24 10:26:22 -06001713 }
1714 if (f->addr > 0 && f->addr != addr) {
aliguori4b096fc2008-08-21 19:28:55 +00001715 continue;
David Ahern27911042010-04-24 10:26:22 -06001716 }
Gerd Hoffmann9056a292011-05-10 12:07:42 +02001717 if (f->port != NULL && (port == NULL || strcmp(f->port, port) != 0)) {
1718 continue;
1719 }
aliguori4b096fc2008-08-21 19:28:55 +00001720
David Ahern27911042010-04-24 10:26:22 -06001721 if (f->vendor_id > 0 && f->vendor_id != vendor_id) {
aliguori4b096fc2008-08-21 19:28:55 +00001722 continue;
David Ahern27911042010-04-24 10:26:22 -06001723 }
aliguori4b096fc2008-08-21 19:28:55 +00001724
David Ahern27911042010-04-24 10:26:22 -06001725 if (f->product_id > 0 && f->product_id != product_id) {
aliguori4b096fc2008-08-21 19:28:55 +00001726 continue;
David Ahern27911042010-04-24 10:26:22 -06001727 }
aliguori4b096fc2008-08-21 19:28:55 +00001728 /* We got a match */
Gerd Hoffmann3ee886c2011-08-24 13:45:06 +02001729 s->seen++;
1730 if (s->errcount >= 3) {
1731 return 0;
1732 }
aliguori4b096fc2008-08-21 19:28:55 +00001733
Markus Armbruster33e66b82009-10-07 01:15:57 +02001734 /* Already attached ? */
David Ahern27911042010-04-24 10:26:22 -06001735 if (s->fd != -1) {
aliguori4b096fc2008-08-21 19:28:55 +00001736 return 0;
David Ahern27911042010-04-24 10:26:22 -06001737 }
malcd0f2c4c2010-02-07 02:03:50 +03001738 DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr);
aliguori4b096fc2008-08-21 19:28:55 +00001739
Gerd Hoffmann3ee886c2011-08-24 13:45:06 +02001740 if (usb_host_open(s, bus_num, addr, port, product_name, speed) < 0) {
1741 s->errcount++;
1742 }
Hans de Goede97f86162011-05-31 11:35:24 +02001743 break;
aliguori4b096fc2008-08-21 19:28:55 +00001744 }
1745
1746 return 0;
1747}
1748
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001749static void usb_host_auto_check(void *unused)
aliguori4b096fc2008-08-21 19:28:55 +00001750{
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001751 struct USBHostDevice *s;
1752 int unconnected = 0;
1753
aliguori4b096fc2008-08-21 19:28:55 +00001754 usb_host_scan(NULL, usb_host_auto_scan);
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001755
1756 QTAILQ_FOREACH(s, &hostdevs, next) {
David Ahern27911042010-04-24 10:26:22 -06001757 if (s->fd == -1) {
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001758 unconnected++;
David Ahern27911042010-04-24 10:26:22 -06001759 }
Gerd Hoffmann3ee886c2011-08-24 13:45:06 +02001760 if (s->seen == 0) {
1761 s->errcount = 0;
1762 }
1763 s->seen = 0;
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001764 }
1765
1766 if (unconnected == 0) {
1767 /* nothing to watch */
David Ahern27911042010-04-24 10:26:22 -06001768 if (usb_auto_timer) {
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001769 qemu_del_timer(usb_auto_timer);
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +02001770 trace_usb_host_auto_scan_disabled();
David Ahern27911042010-04-24 10:26:22 -06001771 }
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001772 return;
1773 }
1774
1775 if (!usb_auto_timer) {
Paolo Bonzini7bd427d2011-03-11 16:47:48 +01001776 usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL);
David Ahern27911042010-04-24 10:26:22 -06001777 if (!usb_auto_timer) {
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001778 return;
David Ahern27911042010-04-24 10:26:22 -06001779 }
Gerd Hoffmanne6a2f502011-08-22 14:13:20 +02001780 trace_usb_host_auto_scan_enabled();
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001781 }
Paolo Bonzini7bd427d2011-03-11 16:47:48 +01001782 qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000);
aliguori4b096fc2008-08-21 19:28:55 +00001783}
1784
1785/*
aliguori5d0c5752008-09-14 01:07:41 +00001786 * Autoconnect filter
1787 * Format:
1788 * auto:bus:dev[:vid:pid]
1789 * auto:bus.dev[:vid:pid]
1790 *
1791 * bus - bus number (dec, * means any)
1792 * dev - device number (dec, * means any)
1793 * vid - vendor id (hex, * means any)
1794 * pid - product id (hex, * means any)
1795 *
1796 * See 'lsusb' output.
aliguori4b096fc2008-08-21 19:28:55 +00001797 */
aliguori5d0c5752008-09-14 01:07:41 +00001798static int parse_filter(const char *spec, struct USBAutoFilter *f)
aliguori4b096fc2008-08-21 19:28:55 +00001799{
aliguori5d0c5752008-09-14 01:07:41 +00001800 enum { BUS, DEV, VID, PID, DONE };
1801 const char *p = spec;
1802 int i;
1803
Markus Armbruster0745eb12009-11-27 13:05:53 +01001804 f->bus_num = 0;
1805 f->addr = 0;
1806 f->vendor_id = 0;
1807 f->product_id = 0;
aliguori5d0c5752008-09-14 01:07:41 +00001808
1809 for (i = BUS; i < DONE; i++) {
David Ahern27911042010-04-24 10:26:22 -06001810 p = strpbrk(p, ":.");
1811 if (!p) {
1812 break;
1813 }
aliguori5d0c5752008-09-14 01:07:41 +00001814 p++;
aliguori5d0c5752008-09-14 01:07:41 +00001815
David Ahern27911042010-04-24 10:26:22 -06001816 if (*p == '*') {
1817 continue;
1818 }
aliguori5d0c5752008-09-14 01:07:41 +00001819 switch(i) {
1820 case BUS: f->bus_num = strtol(p, NULL, 10); break;
1821 case DEV: f->addr = strtol(p, NULL, 10); break;
1822 case VID: f->vendor_id = strtol(p, NULL, 16); break;
1823 case PID: f->product_id = strtol(p, NULL, 16); break;
1824 }
aliguori4b096fc2008-08-21 19:28:55 +00001825 }
1826
aliguori5d0c5752008-09-14 01:07:41 +00001827 if (i < DEV) {
1828 fprintf(stderr, "husb: invalid auto filter spec %s\n", spec);
1829 return -1;
1830 }
1831
1832 return 0;
1833}
1834
bellarda594cfb2005-11-06 16:13:29 +00001835/**********************/
1836/* USB host device info */
bellardbb36d472005-11-05 14:22:28 +00001837
bellarda594cfb2005-11-06 16:13:29 +00001838struct usb_class_info {
1839 int class;
1840 const char *class_name;
1841};
1842
1843static const struct usb_class_info usb_class_info[] = {
1844 { USB_CLASS_AUDIO, "Audio"},
1845 { USB_CLASS_COMM, "Communication"},
1846 { USB_CLASS_HID, "HID"},
1847 { USB_CLASS_HUB, "Hub" },
1848 { USB_CLASS_PHYSICAL, "Physical" },
1849 { USB_CLASS_PRINTER, "Printer" },
1850 { USB_CLASS_MASS_STORAGE, "Storage" },
1851 { USB_CLASS_CDC_DATA, "Data" },
1852 { USB_CLASS_APP_SPEC, "Application Specific" },
1853 { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
1854 { USB_CLASS_STILL_IMAGE, "Still Image" },
balrogb9dc0332007-10-04 22:47:34 +00001855 { USB_CLASS_CSCID, "Smart Card" },
bellarda594cfb2005-11-06 16:13:29 +00001856 { USB_CLASS_CONTENT_SEC, "Content Security" },
1857 { -1, NULL }
1858};
1859
1860static const char *usb_class_str(uint8_t class)
1861{
1862 const struct usb_class_info *p;
1863 for(p = usb_class_info; p->class != -1; p++) {
David Ahern27911042010-04-24 10:26:22 -06001864 if (p->class == class) {
bellardbb36d472005-11-05 14:22:28 +00001865 break;
David Ahern27911042010-04-24 10:26:22 -06001866 }
bellardbb36d472005-11-05 14:22:28 +00001867 }
bellarda594cfb2005-11-06 16:13:29 +00001868 return p->class_name;
bellardbb36d472005-11-05 14:22:28 +00001869}
1870
Gerd Hoffmann5557d822011-05-10 11:43:57 +02001871static void usb_info_device(Monitor *mon, int bus_num, int addr, char *port,
1872 int class_id, int vendor_id, int product_id,
pbrook9596ebb2007-11-18 01:44:38 +00001873 const char *product_name,
1874 int speed)
bellardbb36d472005-11-05 14:22:28 +00001875{
bellarda594cfb2005-11-06 16:13:29 +00001876 const char *class_str, *speed_str;
1877
1878 switch(speed) {
ths5fafdf22007-09-16 21:08:06 +00001879 case USB_SPEED_LOW:
1880 speed_str = "1.5";
bellarda594cfb2005-11-06 16:13:29 +00001881 break;
ths5fafdf22007-09-16 21:08:06 +00001882 case USB_SPEED_FULL:
1883 speed_str = "12";
bellarda594cfb2005-11-06 16:13:29 +00001884 break;
ths5fafdf22007-09-16 21:08:06 +00001885 case USB_SPEED_HIGH:
1886 speed_str = "480";
bellarda594cfb2005-11-06 16:13:29 +00001887 break;
Hans de Goedef264cfb2011-05-31 11:35:19 +02001888 case USB_SPEED_SUPER:
1889 speed_str = "5000";
1890 break;
bellarda594cfb2005-11-06 16:13:29 +00001891 default:
ths5fafdf22007-09-16 21:08:06 +00001892 speed_str = "?";
bellarda594cfb2005-11-06 16:13:29 +00001893 break;
bellardbb36d472005-11-05 14:22:28 +00001894 }
bellarda594cfb2005-11-06 16:13:29 +00001895
Gerd Hoffmann5557d822011-05-10 11:43:57 +02001896 monitor_printf(mon, " Bus %d, Addr %d, Port %s, Speed %s Mb/s\n",
1897 bus_num, addr, port, speed_str);
bellarda594cfb2005-11-06 16:13:29 +00001898 class_str = usb_class_str(class_id);
David Ahern27911042010-04-24 10:26:22 -06001899 if (class_str) {
aliguori376253e2009-03-05 23:01:23 +00001900 monitor_printf(mon, " %s:", class_str);
David Ahern27911042010-04-24 10:26:22 -06001901 } else {
aliguori376253e2009-03-05 23:01:23 +00001902 monitor_printf(mon, " Class %02x:", class_id);
David Ahern27911042010-04-24 10:26:22 -06001903 }
aliguori376253e2009-03-05 23:01:23 +00001904 monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
David Ahern27911042010-04-24 10:26:22 -06001905 if (product_name[0] != '\0') {
aliguori376253e2009-03-05 23:01:23 +00001906 monitor_printf(mon, ", %s", product_name);
David Ahern27911042010-04-24 10:26:22 -06001907 }
aliguori376253e2009-03-05 23:01:23 +00001908 monitor_printf(mon, "\n");
bellarda594cfb2005-11-06 16:13:29 +00001909}
1910
ths5fafdf22007-09-16 21:08:06 +00001911static int usb_host_info_device(void *opaque, int bus_num, int addr,
Gerd Hoffmann5557d822011-05-10 11:43:57 +02001912 char *path, int class_id,
ths5fafdf22007-09-16 21:08:06 +00001913 int vendor_id, int product_id,
bellarda594cfb2005-11-06 16:13:29 +00001914 const char *product_name,
1915 int speed)
1916{
Blue Swirl179da8a2009-09-07 19:00:18 +00001917 Monitor *mon = opaque;
1918
Gerd Hoffmann5557d822011-05-10 11:43:57 +02001919 usb_info_device(mon, bus_num, addr, path, class_id, vendor_id, product_id,
bellarda594cfb2005-11-06 16:13:29 +00001920 product_name, speed);
1921 return 0;
1922}
1923
aliguoriac4ffb52008-09-22 15:04:31 +00001924static void dec2str(int val, char *str, size_t size)
aliguori5d0c5752008-09-14 01:07:41 +00001925{
David Ahern27911042010-04-24 10:26:22 -06001926 if (val == 0) {
aliguoriac4ffb52008-09-22 15:04:31 +00001927 snprintf(str, size, "*");
David Ahern27911042010-04-24 10:26:22 -06001928 } else {
1929 snprintf(str, size, "%d", val);
1930 }
aliguori5d0c5752008-09-14 01:07:41 +00001931}
1932
aliguoriac4ffb52008-09-22 15:04:31 +00001933static void hex2str(int val, char *str, size_t size)
aliguori5d0c5752008-09-14 01:07:41 +00001934{
David Ahern27911042010-04-24 10:26:22 -06001935 if (val == 0) {
aliguoriac4ffb52008-09-22 15:04:31 +00001936 snprintf(str, size, "*");
David Ahern27911042010-04-24 10:26:22 -06001937 } else {
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001938 snprintf(str, size, "%04x", val);
David Ahern27911042010-04-24 10:26:22 -06001939 }
aliguori5d0c5752008-09-14 01:07:41 +00001940}
1941
aliguori376253e2009-03-05 23:01:23 +00001942void usb_host_info(Monitor *mon)
bellarda594cfb2005-11-06 16:13:29 +00001943{
aliguori5d0c5752008-09-14 01:07:41 +00001944 struct USBAutoFilter *f;
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001945 struct USBHostDevice *s;
aliguori5d0c5752008-09-14 01:07:41 +00001946
Blue Swirl179da8a2009-09-07 19:00:18 +00001947 usb_host_scan(mon, usb_host_info_device);
aliguori5d0c5752008-09-14 01:07:41 +00001948
David Ahern27911042010-04-24 10:26:22 -06001949 if (QTAILQ_EMPTY(&hostdevs)) {
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001950 return;
David Ahern27911042010-04-24 10:26:22 -06001951 }
1952
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001953 monitor_printf(mon, " Auto filters:\n");
1954 QTAILQ_FOREACH(s, &hostdevs, next) {
aliguori5d0c5752008-09-14 01:07:41 +00001955 char bus[10], addr[10], vid[10], pid[10];
Gerd Hoffmann26a9e822009-10-26 15:56:50 +01001956 f = &s->match;
aliguoriac4ffb52008-09-22 15:04:31 +00001957 dec2str(f->bus_num, bus, sizeof(bus));
1958 dec2str(f->addr, addr, sizeof(addr));
1959 hex2str(f->vendor_id, vid, sizeof(vid));
1960 hex2str(f->product_id, pid, sizeof(pid));
Gerd Hoffmann9056a292011-05-10 12:07:42 +02001961 monitor_printf(mon, " Bus %s, Addr %s, Port %s, ID %s:%s\n",
1962 bus, addr, f->port ? f->port : "*", vid, pid);
aliguori5d0c5752008-09-14 01:07:41 +00001963 }
bellardbb36d472005-11-05 14:22:28 +00001964}