2 * Copyright (C) 2005-2007 Takahiro Hirofuchi
11 #include "usbip_common.h"
12 #include "stub_driver.h"
15 #define PROGNAME "libusbip"
17 struct usbip_stub_driver *stub_driver;
19 static struct sysfs_driver *open_sysfs_stub_driver(void)
23 char sysfs_mntpath[SYSFS_PATH_MAX];
24 char stub_driver_path[SYSFS_PATH_MAX];
25 struct sysfs_driver *stub_driver;
28 ret = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
30 err("sysfs must be mounted");
34 snprintf(stub_driver_path, SYSFS_PATH_MAX, "%s/%s/usb/%s/%s",
35 sysfs_mntpath, SYSFS_BUS_NAME, SYSFS_DRIVERS_NAME,
38 stub_driver = sysfs_open_driver_path(stub_driver_path);
40 err(USBIP_CORE_MOD_NAME ".ko and " USBIP_HOST_DRV_NAME
41 ".ko must be loaded");
49 #define SYSFS_OPEN_RETRIES 100
51 /* only the first interface value is true! */
52 static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
54 char attrpath[SYSFS_PATH_MAX];
55 struct sysfs_attribute *attr;
59 int retries = SYSFS_OPEN_RETRIES;
61 /* This access is racy!
63 * Just after detach, our driver removes the sysfs
64 * files and recreates them.
66 * We may try and fail to open the usbip_status of
67 * an exported device in the (short) window where
68 * it has been removed and not yet recreated.
70 * This is a bug in the interface. Nothing we can do
71 * except work around it here by polling for the sysfs
72 * usbip_status to reappear.
75 snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status",
76 udev->path, udev->busid,
77 udev->bConfigurationValue,
81 if (stat(attrpath, &s) == 0)
84 if (errno != ENOENT) {
85 err("error stat'ing %s", attrpath);
89 usleep(10000); /* 10ms */
94 err("usbip_status not ready after %d retries",
96 else if (retries < SYSFS_OPEN_RETRIES)
97 info("warning: usbip_status ready after %d retries",
98 SYSFS_OPEN_RETRIES - retries);
100 attr = sysfs_open_attribute(attrpath);
102 err("open %s", attrpath);
106 ret = sysfs_read_attribute(attr);
108 err("read %s", attrpath);
109 sysfs_close_attribute(attr);
113 value = atoi(attr->value);
115 sysfs_close_attribute(attr);
121 static void usbip_exported_device_delete(void *dev)
123 struct usbip_exported_device *edev =
124 (struct usbip_exported_device *) dev;
126 sysfs_close_device(edev->sudev);
131 static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath)
133 struct usbip_exported_device *edev = NULL;
135 edev = (struct usbip_exported_device *) calloc(1, sizeof(*edev));
141 edev->sudev = sysfs_open_device_path(sdevpath);
143 err("open %s", sdevpath);
147 read_usb_device(edev->sudev, &edev->udev);
149 edev->status = read_attr_usbip_status(&edev->udev);
150 if (edev->status < 0)
153 /* reallocate buffer to include usb interface data */
154 size_t size = sizeof(*edev) + edev->udev.bNumInterfaces *
155 sizeof(struct usbip_usb_interface);
156 edev = (struct usbip_exported_device *) realloc(edev, size);
162 for (int i=0; i < edev->udev.bNumInterfaces; i++)
163 read_usb_interface(&edev->udev, i, &edev->uinf[i]);
168 if (edev && edev->sudev)
169 sysfs_close_device(edev->sudev);
176 static int check_new(struct dlist *dlist, struct sysfs_device *target)
178 struct sysfs_device *dev;
180 dlist_for_each_data(dlist, dev, struct sysfs_device) {
181 if (!strncmp(dev->bus_id, target->bus_id, SYSFS_BUS_ID_SIZE))
189 static void delete_nothing(void *dev __attribute__((unused)))
191 /* do not delete anything. but, its container will be deleted. */
194 static int refresh_exported_devices(void)
196 struct sysfs_device *suinf; /* sysfs_device of usb_interface */
197 struct dlist *suinf_list;
199 struct sysfs_device *sudev; /* sysfs_device of usb_device */
200 struct dlist *sudev_list;
203 sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device), delete_nothing);
205 suinf_list = sysfs_get_driver_devices(stub_driver->sysfs_driver);
207 info("bind " USBIP_HOST_DRV_NAME ".ko to a usb device to be "
212 /* collect unique USB devices (not interfaces) */
213 dlist_for_each_data(suinf_list, suinf, struct sysfs_device) {
215 /* get usb device of this usb interface */
216 sudev = sysfs_get_device_parent(suinf);
218 err("get parent dev of %s", suinf->name);
222 if (check_new(sudev_list, sudev)) {
223 dlist_unshift(sudev_list, sudev);
227 dlist_for_each_data(sudev_list, sudev, struct sysfs_device) {
228 struct usbip_exported_device *edev;
230 edev = usbip_exported_device_new(sudev->path);
232 err("usbip_exported_device new");
236 dlist_unshift(stub_driver->edev_list, (void *) edev);
237 stub_driver->ndevs++;
241 dlist_destroy(sudev_list);
248 int usbip_stub_refresh_device_list(void)
252 if (stub_driver->edev_list)
253 dlist_destroy(stub_driver->edev_list);
255 stub_driver->ndevs = 0;
257 stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device),
258 usbip_exported_device_delete);
259 if (!stub_driver->edev_list) {
264 ret = refresh_exported_devices();
271 int usbip_stub_driver_open(void)
276 stub_driver = (struct usbip_stub_driver *) calloc(1, sizeof(*stub_driver));
278 err("alloc stub_driver");
282 stub_driver->ndevs = 0;
284 stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device),
285 usbip_exported_device_delete);
286 if (!stub_driver->edev_list) {
291 stub_driver->sysfs_driver = open_sysfs_stub_driver();
292 if (!stub_driver->sysfs_driver)
295 ret = refresh_exported_devices();
303 if (stub_driver->sysfs_driver)
304 sysfs_close_driver(stub_driver->sysfs_driver);
305 if (stub_driver->edev_list)
306 dlist_destroy(stub_driver->edev_list);
314 void usbip_stub_driver_close(void)
319 if (stub_driver->edev_list)
320 dlist_destroy(stub_driver->edev_list);
321 if (stub_driver->sysfs_driver)
322 sysfs_close_driver(stub_driver->sysfs_driver);
328 int usbip_stub_export_device(struct usbip_exported_device *edev, int sockfd)
330 char attrpath[SYSFS_PATH_MAX];
331 struct sysfs_attribute *attr;
332 char sockfd_buff[30];
336 if (edev->status != SDEV_ST_AVAILABLE) {
337 info("device not available, %s", edev->udev.busid);
338 switch( edev->status ) {
340 info(" status SDEV_ST_ERROR");
343 info(" status SDEV_ST_USED");
346 info(" status unknown: 0x%x", edev->status);
351 /* only the first interface is true */
352 snprintf(attrpath, sizeof(attrpath), "%s/%s:%d.%d/%s",
355 edev->udev.bConfigurationValue, 0,
358 attr = sysfs_open_attribute(attrpath);
360 err("open %s", attrpath);
364 snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
366 dbg("write: %s", sockfd_buff);
368 ret = sysfs_write_attribute(attr, sockfd_buff, strlen(sockfd_buff));
370 err("write sockfd %s to %s", sockfd_buff, attrpath);
371 goto err_write_sockfd;
374 info("connect %s", edev->udev.busid);
377 sysfs_close_attribute(attr);
382 struct usbip_exported_device *usbip_stub_get_device(int num)
384 struct usbip_exported_device *edev;
385 struct dlist *dlist = stub_driver->edev_list;
388 dlist_for_each_data(dlist, edev, struct usbip_exported_device) {