2 * Copyright (C) 2005-2007 Takahiro Hirofuchi
11 static const char *usbip_stub_driver_name = "usbip";
14 struct usbip_stub_driver *stub_driver;
16 static struct sysfs_driver *open_sysfs_stub_driver(void)
20 char sysfs_mntpath[SYSFS_PATH_MAX];
21 char stub_driver_path[SYSFS_PATH_MAX];
22 struct sysfs_driver *stub_driver;
25 ret = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
27 err("sysfs must be mounted");
31 snprintf(stub_driver_path, SYSFS_PATH_MAX, "%s/%s/usb/%s/%s",
32 sysfs_mntpath, SYSFS_BUS_NAME, SYSFS_DRIVERS_NAME,
33 usbip_stub_driver_name);
35 stub_driver = sysfs_open_driver_path(stub_driver_path);
37 err("usbip_common_mod.ko and usbip.ko must be loaded");
45 #define SYSFS_OPEN_RETRIES 100
47 /* only the first interface value is true! */
48 static int32_t read_attr_usbip_status(struct usb_device *udev)
50 char attrpath[SYSFS_PATH_MAX];
51 struct sysfs_attribute *attr;
55 int retries = SYSFS_OPEN_RETRIES;
57 /* This access is racy!
59 * Just after detach, our driver removes the sysfs
60 * files and recreates them.
62 * We may try and fail to open the usbip_status of
63 * an exported device in the (short) window where
64 * it has been removed and not yet recreated.
66 * This is a bug in the interface. Nothing we can do
67 * except work around it here by polling for the sysfs
68 * usbip_status to reappear.
71 snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status",
72 udev->path, udev->busid,
73 udev->bConfigurationValue,
77 if (stat(attrpath, &s) == 0)
80 if (errno != ENOENT) {
81 err("error stat'ing %s", attrpath);
85 usleep(10000); /* 10ms */
90 err("usbip_status not ready after %d retries",
92 else if (retries < SYSFS_OPEN_RETRIES)
93 info("warning: usbip_status ready after %d retries",
94 SYSFS_OPEN_RETRIES - retries);
96 attr = sysfs_open_attribute(attrpath);
98 err("open %s", attrpath);
102 ret = sysfs_read_attribute(attr);
104 err("read %s", attrpath);
105 sysfs_close_attribute(attr);
109 value = atoi(attr->value);
111 sysfs_close_attribute(attr);
117 static void usbip_exported_device_delete(void *dev)
119 struct usbip_exported_device *edev =
120 (struct usbip_exported_device *) dev;
122 sysfs_close_device(edev->sudev);
127 static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath)
129 struct usbip_exported_device *edev = NULL;
131 edev = (struct usbip_exported_device *) calloc(1, sizeof(*edev));
137 edev->sudev = sysfs_open_device_path(sdevpath);
139 err("open %s", sdevpath);
143 read_usb_device(edev->sudev, &edev->udev);
145 edev->status = read_attr_usbip_status(&edev->udev);
146 if (edev->status < 0)
149 /* reallocate buffer to include usb interface data */
150 size_t size = sizeof(*edev) + edev->udev.bNumInterfaces * sizeof(struct usb_interface);
151 edev = (struct usbip_exported_device *) realloc(edev, size);
157 for (int i=0; i < edev->udev.bNumInterfaces; i++)
158 read_usb_interface(&edev->udev, i, &edev->uinf[i]);
163 if (edev && edev->sudev)
164 sysfs_close_device(edev->sudev);
171 static int check_new(struct dlist *dlist, struct sysfs_device *target)
173 struct sysfs_device *dev;
175 dlist_for_each_data(dlist, dev, struct sysfs_device) {
176 if (!strncmp(dev->bus_id, target->bus_id, SYSFS_BUS_ID_SIZE))
184 static void delete_nothing(void *dev)
186 /* do not delete anything. but, its container will be deleted. */
189 static int refresh_exported_devices(void)
191 struct sysfs_device *suinf; /* sysfs_device of usb_interface */
192 struct dlist *suinf_list;
194 struct sysfs_device *sudev; /* sysfs_device of usb_device */
195 struct dlist *sudev_list;
198 sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device), delete_nothing);
200 suinf_list = sysfs_get_driver_devices(stub_driver->sysfs_driver);
202 printf("Bind usbip.ko to a usb device to be exportable!\n");
206 /* collect unique USB devices (not interfaces) */
207 dlist_for_each_data(suinf_list, suinf, struct sysfs_device) {
209 /* get usb device of this usb interface */
210 sudev = sysfs_get_device_parent(suinf);
212 err("get parent dev of %s", suinf->name);
216 if (check_new(sudev_list, sudev)) {
217 dlist_unshift(sudev_list, sudev);
221 dlist_for_each_data(sudev_list, sudev, struct sysfs_device) {
222 struct usbip_exported_device *edev;
224 edev = usbip_exported_device_new(sudev->path);
226 err("usbip_exported_device new");
230 dlist_unshift(stub_driver->edev_list, (void *) edev);
231 stub_driver->ndevs++;
235 dlist_destroy(sudev_list);
242 int usbip_stub_refresh_device_list(void)
246 if (stub_driver->edev_list)
247 dlist_destroy(stub_driver->edev_list);
249 stub_driver->ndevs = 0;
251 stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device),
252 usbip_exported_device_delete);
253 if (!stub_driver->edev_list) {
258 ret = refresh_exported_devices();
265 int usbip_stub_driver_open(void)
270 stub_driver = (struct usbip_stub_driver *) calloc(1, sizeof(*stub_driver));
272 err("alloc stub_driver");
276 stub_driver->ndevs = 0;
278 stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device),
279 usbip_exported_device_delete);
280 if (!stub_driver->edev_list) {
285 stub_driver->sysfs_driver = open_sysfs_stub_driver();
286 if (!stub_driver->sysfs_driver)
289 ret = refresh_exported_devices();
297 if (stub_driver->sysfs_driver)
298 sysfs_close_driver(stub_driver->sysfs_driver);
299 if (stub_driver->edev_list)
300 dlist_destroy(stub_driver->edev_list);
308 void usbip_stub_driver_close(void)
313 if (stub_driver->edev_list)
314 dlist_destroy(stub_driver->edev_list);
315 if (stub_driver->sysfs_driver)
316 sysfs_close_driver(stub_driver->sysfs_driver);
322 int usbip_stub_export_device(struct usbip_exported_device *edev, int sockfd)
324 char attrpath[SYSFS_PATH_MAX];
325 struct sysfs_attribute *attr;
326 char sockfd_buff[30];
330 if (edev->status != SDEV_ST_AVAILABLE) {
331 info("device not available, %s", edev->udev.busid);
332 switch( edev->status ) {
334 info(" status SDEV_ST_ERROR");
337 info(" status SDEV_ST_USED");
340 info(" status unknown: 0x%x", edev->status);
345 /* only the first interface is true */
346 snprintf(attrpath, sizeof(attrpath), "%s/%s:%d.%d/%s",
349 edev->udev.bConfigurationValue, 0,
352 attr = sysfs_open_attribute(attrpath);
354 err("open %s", attrpath);
358 snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
360 dbg("write: %s", sockfd_buff);
362 ret = sysfs_write_attribute(attr, sockfd_buff, strlen(sockfd_buff));
364 err("write sockfd %s to %s", sockfd_buff, attrpath);
365 goto err_write_sockfd;
368 info("connect %s", edev->udev.busid);
371 sysfs_close_attribute(attr);
376 struct usbip_exported_device *usbip_stub_get_device(int num)
378 struct usbip_exported_device *edev;
379 struct dlist *dlist = stub_driver->edev_list;
382 dlist_for_each_data(dlist, edev, struct usbip_exported_device) {