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) {