2
* Copyright (C) 2005-2007 Takahiro Hirofuchi
11
/* kernel module name */
12
static const char *usbip_stub_driver_name = "usbip-host";
15
struct usbip_stub_driver *stub_driver;
17
static struct sysfs_driver *open_sysfs_stub_driver(void)
21
char sysfs_mntpath[SYSFS_PATH_MAX];
22
char stub_driver_path[SYSFS_PATH_MAX];
23
struct sysfs_driver *stub_driver;
26
ret = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
28
err("sysfs must be mounted");
32
snprintf(stub_driver_path, SYSFS_PATH_MAX, "%s/%s/usb/%s/%s",
33
sysfs_mntpath, SYSFS_BUS_NAME, SYSFS_DRIVERS_NAME,
34
usbip_stub_driver_name);
36
stub_driver = sysfs_open_driver_path(stub_driver_path);
38
err("usbip-core.ko and usbip-host.ko must be loaded");
46
#define SYSFS_OPEN_RETRIES 100
48
/* only the first interface value is true! */
49
static int32_t read_attr_usbip_status(struct usb_device *udev)
51
char attrpath[SYSFS_PATH_MAX];
52
struct sysfs_attribute *attr;
56
int retries = SYSFS_OPEN_RETRIES;
58
/* This access is racy!
60
* Just after detach, our driver removes the sysfs
61
* files and recreates them.
63
* We may try and fail to open the usbip_status of
64
* an exported device in the (short) window where
65
* it has been removed and not yet recreated.
67
* This is a bug in the interface. Nothing we can do
68
* except work around it here by polling for the sysfs
69
* usbip_status to reappear.
72
snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status",
73
udev->path, udev->busid,
74
udev->bConfigurationValue,
78
if (stat(attrpath, &s) == 0)
81
if (errno != ENOENT) {
82
err("error stat'ing %s", attrpath);
86
usleep(10000); /* 10ms */
91
err("usbip_status not ready after %d retries",
93
else if (retries < SYSFS_OPEN_RETRIES)
94
info("warning: usbip_status ready after %d retries",
95
SYSFS_OPEN_RETRIES - retries);
97
attr = sysfs_open_attribute(attrpath);
99
err("open %s", attrpath);
103
ret = sysfs_read_attribute(attr);
105
err("read %s", attrpath);
106
sysfs_close_attribute(attr);
110
value = atoi(attr->value);
112
sysfs_close_attribute(attr);
118
static void usbip_exported_device_delete(void *dev)
120
struct usbip_exported_device *edev =
121
(struct usbip_exported_device *) dev;
123
sysfs_close_device(edev->sudev);
128
static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath)
130
struct usbip_exported_device *edev = NULL;
132
edev = (struct usbip_exported_device *) calloc(1, sizeof(*edev));
138
edev->sudev = sysfs_open_device_path(sdevpath);
140
err("open %s", sdevpath);
144
read_usb_device(edev->sudev, &edev->udev);
146
edev->status = read_attr_usbip_status(&edev->udev);
147
if (edev->status < 0)
150
/* reallocate buffer to include usb interface data */
151
size_t size = sizeof(*edev) + edev->udev.bNumInterfaces * sizeof(struct usb_interface);
152
edev = (struct usbip_exported_device *) realloc(edev, size);
158
for (int i=0; i < edev->udev.bNumInterfaces; i++)
159
read_usb_interface(&edev->udev, i, &edev->uinf[i]);
164
if (edev && edev->sudev)
165
sysfs_close_device(edev->sudev);
172
static int check_new(struct dlist *dlist, struct sysfs_device *target)
174
struct sysfs_device *dev;
176
dlist_for_each_data(dlist, dev, struct sysfs_device) {
177
if (!strncmp(dev->bus_id, target->bus_id, SYSFS_BUS_ID_SIZE))
185
static void delete_nothing(void *dev __attribute__((unused)))
187
/* do not delete anything. but, its container will be deleted. */
190
static int refresh_exported_devices(void)
192
struct sysfs_device *suinf; /* sysfs_device of usb_interface */
193
struct dlist *suinf_list;
195
struct sysfs_device *sudev; /* sysfs_device of usb_device */
196
struct dlist *sudev_list;
199
sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device), delete_nothing);
201
suinf_list = sysfs_get_driver_devices(stub_driver->sysfs_driver);
203
printf("Bind usbip-host.ko to a usb device to be exportable!\n");
207
/* collect unique USB devices (not interfaces) */
208
dlist_for_each_data(suinf_list, suinf, struct sysfs_device) {
210
/* get usb device of this usb interface */
211
sudev = sysfs_get_device_parent(suinf);
213
err("get parent dev of %s", suinf->name);
217
if (check_new(sudev_list, sudev)) {
218
dlist_unshift(sudev_list, sudev);
222
dlist_for_each_data(sudev_list, sudev, struct sysfs_device) {
223
struct usbip_exported_device *edev;
225
edev = usbip_exported_device_new(sudev->path);
227
err("usbip_exported_device new");
231
dlist_unshift(stub_driver->edev_list, (void *) edev);
232
stub_driver->ndevs++;
236
dlist_destroy(sudev_list);
243
int usbip_stub_refresh_device_list(void)
247
if (stub_driver->edev_list)
248
dlist_destroy(stub_driver->edev_list);
250
stub_driver->ndevs = 0;
252
stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device),
253
usbip_exported_device_delete);
254
if (!stub_driver->edev_list) {
259
ret = refresh_exported_devices();
266
int usbip_stub_driver_open(void)
271
stub_driver = (struct usbip_stub_driver *) calloc(1, sizeof(*stub_driver));
273
err("alloc stub_driver");
277
stub_driver->ndevs = 0;
279
stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device),
280
usbip_exported_device_delete);
281
if (!stub_driver->edev_list) {
286
stub_driver->sysfs_driver = open_sysfs_stub_driver();
287
if (!stub_driver->sysfs_driver)
290
ret = refresh_exported_devices();
298
if (stub_driver->sysfs_driver)
299
sysfs_close_driver(stub_driver->sysfs_driver);
300
if (stub_driver->edev_list)
301
dlist_destroy(stub_driver->edev_list);
309
void usbip_stub_driver_close(void)
314
if (stub_driver->edev_list)
315
dlist_destroy(stub_driver->edev_list);
316
if (stub_driver->sysfs_driver)
317
sysfs_close_driver(stub_driver->sysfs_driver);
323
int usbip_stub_export_device(struct usbip_exported_device *edev, int sockfd)
325
char attrpath[SYSFS_PATH_MAX];
326
struct sysfs_attribute *attr;
327
char sockfd_buff[30];
331
if (edev->status != SDEV_ST_AVAILABLE) {
332
info("device not available, %s", edev->udev.busid);
333
switch( edev->status ) {
335
info(" status SDEV_ST_ERROR");
338
info(" status SDEV_ST_USED");
341
info(" status unknown: 0x%x", edev->status);
346
/* only the first interface is true */
347
snprintf(attrpath, sizeof(attrpath), "%s/%s:%d.%d/%s",
350
edev->udev.bConfigurationValue, 0,
353
attr = sysfs_open_attribute(attrpath);
355
err("open %s", attrpath);
359
snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
361
dbg("write: %s", sockfd_buff);
363
ret = sysfs_write_attribute(attr, sockfd_buff, strlen(sockfd_buff));
365
err("write sockfd %s to %s", sockfd_buff, attrpath);
366
goto err_write_sockfd;
369
info("connect %s", edev->udev.busid);
372
sysfs_close_attribute(attr);
377
struct usbip_exported_device *usbip_stub_get_device(int num)
379
struct usbip_exported_device *edev;
380
struct dlist *dlist = stub_driver->edev_list;
383
dlist_for_each_data(dlist, edev, struct usbip_exported_device) {