]>
git.ipfire.org Git - thirdparty/qemu.git/blob - usb-linux.c
2 * Linux host USB redirector
4 * Copyright (c) 2005 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #if defined(__linux__)
28 #include <sys/ioctl.h>
29 #include <linux/usbdevice_fs.h>
30 #include <linux/version.h>
32 /* We redefine it to avoid version problems */
33 struct usb_ctrltransfer
{
47 #define USBDEVFS_PATH "/proc/bus/usb"
49 typedef struct USBHostDevice
{
54 typedef struct USBHostHubState
{
56 USBPort
*hub_ports
[MAX_DEVICES
];
57 USBDevice
*hub_devices
[MAX_DEVICES
];
60 static void usb_host_handle_reset(USBDevice
*dev
)
63 USBHostDevice
*s
= (USBHostDevice
*)dev
;
64 /* USBDEVFS_RESET, but not the first time as it has already be
65 done by the host OS */
66 ioctl(s
->fd
, USBDEVFS_RESET
);
70 static int usb_host_handle_control(USBDevice
*dev
,
77 USBHostDevice
*s
= (USBHostDevice
*)dev
;
78 struct usb_ctrltransfer ct
;
81 if (request
== (DeviceOutRequest
| USB_REQ_SET_ADDRESS
)) {
82 /* specific SET_ADDRESS support */
86 ct
.bRequestType
= request
>> 8;
87 ct
.bRequest
= request
;
93 ret
= ioctl(s
->fd
, USBDEVFS_CONTROL
, &ct
);
107 static int usb_host_handle_data(USBDevice
*dev
, int pid
,
109 uint8_t *data
, int len
)
111 USBHostDevice
*s
= (USBHostDevice
*)dev
;
112 struct usbdevfs_bulktransfer bt
;
115 /* XXX: optimize and handle all data types by looking at the
117 if (pid
== USB_TOKEN_IN
)
123 ret
= ioctl(s
->fd
, USBDEVFS_BULK
, &bt
);
131 printf("handle_data: errno=%d\n", errno
);
133 return USB_RET_STALL
;
140 static int usb_host_handle_packet(USBDevice
*dev
, int pid
,
141 uint8_t devaddr
, uint8_t devep
,
142 uint8_t *data
, int len
)
144 return usb_generic_handle_packet(dev
, pid
, devaddr
, devep
, data
, len
);
147 /* XXX: exclude high speed devices or implement EHCI */
148 static void scan_host_device(USBHostHubState
*s
, const char *filename
)
150 int fd
, interface
, ret
, i
;
152 struct usbdevfs_connectinfo ci
;
154 int descr_len
, dev_descr_len
, config_descr_len
, nb_interfaces
;
157 printf("scanning %s\n", filename
);
159 fd
= open(filename
, O_RDWR
);
165 /* read the config description */
166 descr_len
= read(fd
, descr
, sizeof(descr
));
167 if (descr_len
<= 0) {
168 perror("read descr");
173 dev_descr_len
= descr
[0];
174 if (dev_descr_len
> descr_len
)
177 config_descr_len
= descr
[i
];
178 if (i
+ config_descr_len
> descr_len
)
180 nb_interfaces
= descr
[i
+ 4];
181 if (nb_interfaces
!= 1) {
182 /* NOTE: currently we grab only one interface */
185 /* XXX: only grab if all interfaces are free */
187 ret
= ioctl(fd
, USBDEVFS_CLAIMINTERFACE
, &interface
);
189 if (errno
== EBUSY
) {
191 printf("%s already grabbed\n", filename
);
194 perror("USBDEVFS_CLAIMINTERFACE");
201 ret
= ioctl(fd
, USBDEVFS_CONNECTINFO
, &ci
);
203 perror("USBDEVFS_CONNECTINFO");
208 printf("%s grabbed\n", filename
);
211 /* find a free slot */
212 for(i
= 0; i
< MAX_DEVICES
; i
++) {
213 if (!s
->hub_devices
[i
])
216 if (i
== MAX_DEVICES
) {
218 printf("too many host devices\n");
223 dev
= qemu_mallocz(sizeof(USBHostDevice
));
228 dev
->dev
.speed
= USB_SPEED_LOW
;
230 dev
->dev
.speed
= USB_SPEED_HIGH
;
231 dev
->dev
.handle_packet
= usb_host_handle_packet
;
233 dev
->dev
.handle_reset
= usb_host_handle_reset
;
234 dev
->dev
.handle_control
= usb_host_handle_control
;
235 dev
->dev
.handle_data
= usb_host_handle_data
;
237 s
->hub_devices
[i
] = (USBDevice
*)dev
;
239 /* activate device on hub */
240 usb_attach(s
->hub_ports
[i
], s
->hub_devices
[i
]);
243 static void scan_host_devices(USBHostHubState
*s
, const char *bus_path
)
249 d
= opendir(bus_path
);
256 if (de
->d_name
[0] != '.') {
257 snprintf(buf
, sizeof(buf
), "%s/%s", bus_path
, de
->d_name
);
258 scan_host_device(s
, buf
);
264 static void scan_host_buses(USBHostHubState
*s
)
270 d
= opendir(USBDEVFS_PATH
);
277 if (isdigit(de
->d_name
[0])) {
278 snprintf(buf
, sizeof(buf
), "%s/%s", USBDEVFS_PATH
, de
->d_name
);
279 scan_host_devices(s
, buf
);
285 /* virtual hub containing the USB devices of the host */
286 USBDevice
*usb_host_hub_init(void)
289 s
= qemu_mallocz(sizeof(USBHostHubState
));
292 s
->hub_dev
= usb_hub_init(s
->hub_ports
, MAX_DEVICES
);
303 /* XXX: modify configure to compile the right host driver */
304 USBDevice
*usb_host_hub_init(void)