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 dbg("sysfs_get_mnt_path failed");
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 dbg("sysfs_open_driver_path failed");
48 #define SYSFS_OPEN_RETRIES 100
50 /* only the first interface value is true! */
51 static int32_t read_attr_usbip_status(struct usbip_usb_device
*udev
)
53 char attrpath
[SYSFS_PATH_MAX
];
54 struct sysfs_attribute
*attr
;
58 int retries
= SYSFS_OPEN_RETRIES
;
60 /* This access is racy!
62 * Just after detach, our driver removes the sysfs
63 * files and recreates them.
65 * We may try and fail to open the usbip_status of
66 * an exported device in the (short) window where
67 * it has been removed and not yet recreated.
69 * This is a bug in the interface. Nothing we can do
70 * except work around it here by polling for the sysfs
71 * usbip_status to reappear.
74 snprintf(attrpath
, SYSFS_PATH_MAX
, "%s/%s:%d.%d/usbip_status",
75 udev
->path
, udev
->busid
,
76 udev
->bConfigurationValue
,
80 if (stat(attrpath
, &s
) == 0)
83 if (errno
!= ENOENT
) {
84 dbg("stat failed: %s", attrpath
);
88 usleep(10000); /* 10ms */
93 dbg("usbip_status not ready after %d retries",
95 else if (retries
< SYSFS_OPEN_RETRIES
)
96 dbg("warning: usbip_status ready after %d retries",
97 SYSFS_OPEN_RETRIES
- retries
);
99 attr
= sysfs_open_attribute(attrpath
);
101 dbg("sysfs_open_attribute failed: %s", attrpath
);
105 ret
= sysfs_read_attribute(attr
);
107 dbg("sysfs_read_attribute failed: %s", attrpath
);
108 sysfs_close_attribute(attr
);
112 value
= atoi(attr
->value
);
114 sysfs_close_attribute(attr
);
120 static void usbip_exported_device_delete(void *dev
)
122 struct usbip_exported_device
*edev
=
123 (struct usbip_exported_device
*) dev
;
125 sysfs_close_device(edev
->sudev
);
130 static struct usbip_exported_device
*usbip_exported_device_new(char *sdevpath
)
132 struct usbip_exported_device
*edev
= NULL
;
134 edev
= (struct usbip_exported_device
*) calloc(1, sizeof(*edev
));
136 dbg("calloc failed");
140 edev
->sudev
= sysfs_open_device_path(sdevpath
);
142 dbg("sysfs_open_device_path failed: %s", sdevpath
);
146 read_usb_device(edev
->sudev
, &edev
->udev
);
148 edev
->status
= read_attr_usbip_status(&edev
->udev
);
149 if (edev
->status
< 0)
152 /* reallocate buffer to include usb interface data */
153 size_t size
= sizeof(*edev
) + edev
->udev
.bNumInterfaces
*
154 sizeof(struct usbip_usb_interface
);
155 edev
= (struct usbip_exported_device
*) realloc(edev
, size
);
157 dbg("realloc failed");
161 for (int i
=0; i
< edev
->udev
.bNumInterfaces
; i
++)
162 read_usb_interface(&edev
->udev
, i
, &edev
->uinf
[i
]);
167 if (edev
&& edev
->sudev
)
168 sysfs_close_device(edev
->sudev
);
175 static int check_new(struct dlist
*dlist
, struct sysfs_device
*target
)
177 struct sysfs_device
*dev
;
179 dlist_for_each_data(dlist
, dev
, struct sysfs_device
) {
180 if (!strncmp(dev
->bus_id
, target
->bus_id
, SYSFS_BUS_ID_SIZE
))
188 static void delete_nothing(void *dev
__attribute__((unused
)))
190 /* do not delete anything. but, its container will be deleted. */
193 static int refresh_exported_devices(void)
195 struct sysfs_device
*suinf
; /* sysfs_device of usb_interface */
196 struct dlist
*suinf_list
;
198 struct sysfs_device
*sudev
; /* sysfs_device of usb_device */
199 struct dlist
*sudev_list
;
202 sudev_list
= dlist_new_with_delete(sizeof(struct sysfs_device
), delete_nothing
);
204 suinf_list
= sysfs_get_driver_devices(stub_driver
->sysfs_driver
);
206 dbg("bind " USBIP_HOST_DRV_NAME
".ko to a usb device to be "
211 /* collect unique USB devices (not interfaces) */
212 dlist_for_each_data(suinf_list
, suinf
, struct sysfs_device
) {
214 /* get usb device of this usb interface */
215 sudev
= sysfs_get_device_parent(suinf
);
217 dbg("sysfs_get_device_parent failed: %s", suinf
->name
);
221 if (check_new(sudev_list
, sudev
)) {
222 dlist_unshift(sudev_list
, sudev
);
226 dlist_for_each_data(sudev_list
, sudev
, struct sysfs_device
) {
227 struct usbip_exported_device
*edev
;
229 edev
= usbip_exported_device_new(sudev
->path
);
231 dbg("usbip_exported_device_new failed");
235 dlist_unshift(stub_driver
->edev_list
, (void *) edev
);
236 stub_driver
->ndevs
++;
240 dlist_destroy(sudev_list
);
247 int usbip_stub_refresh_device_list(void)
251 if (stub_driver
->edev_list
)
252 dlist_destroy(stub_driver
->edev_list
);
254 stub_driver
->ndevs
= 0;
256 stub_driver
->edev_list
= dlist_new_with_delete(sizeof(struct usbip_exported_device
),
257 usbip_exported_device_delete
);
258 if (!stub_driver
->edev_list
) {
259 dbg("dlist_new_with_delete failed");
263 ret
= refresh_exported_devices();
270 int usbip_stub_driver_open(void)
275 stub_driver
= (struct usbip_stub_driver
*) calloc(1, sizeof(*stub_driver
));
277 dbg("calloc failed");
281 stub_driver
->ndevs
= 0;
283 stub_driver
->edev_list
= dlist_new_with_delete(sizeof(struct usbip_exported_device
),
284 usbip_exported_device_delete
);
285 if (!stub_driver
->edev_list
) {
286 dbg("dlist_new_with_delete failed");
290 stub_driver
->sysfs_driver
= open_sysfs_stub_driver();
291 if (!stub_driver
->sysfs_driver
)
294 ret
= refresh_exported_devices();
302 if (stub_driver
->sysfs_driver
)
303 sysfs_close_driver(stub_driver
->sysfs_driver
);
304 if (stub_driver
->edev_list
)
305 dlist_destroy(stub_driver
->edev_list
);
313 void usbip_stub_driver_close(void)
318 if (stub_driver
->edev_list
)
319 dlist_destroy(stub_driver
->edev_list
);
320 if (stub_driver
->sysfs_driver
)
321 sysfs_close_driver(stub_driver
->sysfs_driver
);
327 int usbip_stub_export_device(struct usbip_exported_device
*edev
, int sockfd
)
329 char attrpath
[SYSFS_PATH_MAX
];
330 struct sysfs_attribute
*attr
;
331 char sockfd_buff
[30];
335 if (edev
->status
!= SDEV_ST_AVAILABLE
) {
336 dbg("device not available: %s", edev
->udev
.busid
);
337 switch( edev
->status
) {
339 dbg("status SDEV_ST_ERROR");
342 dbg("status SDEV_ST_USED");
345 dbg("status unknown: 0x%x", edev
->status
);
350 /* only the first interface is true */
351 snprintf(attrpath
, sizeof(attrpath
), "%s/%s:%d.%d/%s",
354 edev
->udev
.bConfigurationValue
, 0,
357 attr
= sysfs_open_attribute(attrpath
);
359 dbg("sysfs_open_attribute failed: %s", attrpath
);
363 snprintf(sockfd_buff
, sizeof(sockfd_buff
), "%d\n", sockfd
);
365 dbg("write: %s", sockfd_buff
);
366 ret
= sysfs_write_attribute(attr
, sockfd_buff
, strlen(sockfd_buff
));
368 dbg("sysfs_write_attribute failed: sockfd %s to %s",
369 sockfd_buff
, attrpath
);
370 goto err_write_sockfd
;
373 dbg("connect: %s", edev
->udev
.busid
);
376 sysfs_close_attribute(attr
);
381 struct usbip_exported_device
*usbip_stub_get_device(int num
)
383 struct usbip_exported_device
*edev
;
384 struct dlist
*dlist
= stub_driver
->edev_list
;
387 dlist_for_each_data(dlist
, edev
, struct usbip_exported_device
) {