2
* Copyright (C) 2005-2007 Takahiro Hirofuchi
5
#include "usbip_common.h"
6
#include "vhci_driver.h"
9
#define PROGNAME "libusbip"
11
struct usbip_vhci_driver *vhci_driver;
13
static struct usbip_imported_device *imported_device_init(struct usbip_imported_device *idev, char *busid)
15
struct sysfs_device *sudev;
17
sudev = sysfs_open_device("usb", busid);
19
dbg("sysfs_open_device failed: %s", busid);
22
read_usb_device(sudev, &idev->udev);
23
sysfs_close_device(sudev);
25
/* add class devices of this imported device */
26
struct usbip_class_device *cdev;
27
dlist_for_each_data(vhci_driver->cdev_list, cdev,
28
struct usbip_class_device) {
29
if (!strncmp(cdev->dev_path, idev->udev.path,
30
strlen(idev->udev.path))) {
31
struct usbip_class_device *new_cdev;
33
/* alloc and copy because dlist is linked from only one list */
34
new_cdev = calloc(1, sizeof(*new_cdev));
38
memcpy(new_cdev, cdev, sizeof(*new_cdev));
39
dlist_unshift(idev->cdev_list, (void*) new_cdev);
51
static int parse_status(char *value)
57
for (int i = 0; i < vhci_driver->nports; i++)
58
memset(&vhci_driver->idev[i], 0, sizeof(vhci_driver->idev[i]));
61
/* skip a header line */
62
c = strchr(value, '\n') + 1;
65
int port, status, speed, devid;
67
char lbusid[SYSFS_BUS_ID_SIZE];
69
ret = sscanf(c, "%d %d %d %x %lx %s\n",
70
&port, &status, &speed,
71
&devid, &socket, lbusid);
74
dbg("sscanf failed: %d", ret);
78
dbg("port %d status %d speed %d devid %x",
79
port, status, speed, devid);
80
dbg("socket %lx lbusid %s", socket, lbusid);
83
/* if a device is connected, look at it */
85
struct usbip_imported_device *idev = &vhci_driver->idev[port];
88
idev->status = status;
92
idev->busnum = (devid >> 16);
93
idev->devnum = (devid & 0x0000ffff);
95
idev->cdev_list = dlist_new(sizeof(struct usbip_class_device));
96
if (!idev->cdev_list) {
97
dbg("dlist_new failed");
101
if (idev->status != VDEV_ST_NULL && idev->status != VDEV_ST_NOTASSIGNED) {
102
idev = imported_device_init(idev, lbusid);
104
dbg("imported_device_init failed");
111
/* go to the next line */
112
c = strchr(c, '\n') + 1;
121
static int check_usbip_device(struct sysfs_class_device *cdev)
123
char class_path[SYSFS_PATH_MAX]; /* /sys/class/video4linux/video0/device */
124
char dev_path[SYSFS_PATH_MAX]; /* /sys/devices/platform/vhci_hcd/usb6/6-1:1.1 */
126
struct usbip_class_device *usbip_cdev;
128
snprintf(class_path, sizeof(class_path), "%s/device", cdev->path);
130
ret = sysfs_get_link(class_path, dev_path, sizeof(dev_path));
132
if (!strncmp(dev_path, vhci_driver->hc_device->path,
133
strlen(vhci_driver->hc_device->path))) {
134
/* found usbip device */
135
usbip_cdev = calloc(1, sizeof(*usbip_cdev));
137
dbg("calloc failed");
140
dlist_unshift(vhci_driver->cdev_list, usbip_cdev);
141
strncpy(usbip_cdev->class_path, class_path,
142
sizeof(usbip_cdev->class_path));
143
strncpy(usbip_cdev->dev_path, dev_path,
144
sizeof(usbip_cdev->dev_path));
145
dbg("found: %s %s", class_path, dev_path);
153
static int search_class_for_usbip_device(char *cname)
155
struct sysfs_class *class;
156
struct dlist *cdev_list;
157
struct sysfs_class_device *cdev;
160
class = sysfs_open_class(cname);
162
dbg("sysfs_open_class failed");
166
dbg("class: %s", class->name);
168
cdev_list = sysfs_get_class_devices(class);
173
dlist_for_each_data(cdev_list, cdev, struct sysfs_class_device) {
174
dbg("cdev: %s", cdev->name);
175
ret = check_usbip_device(cdev);
181
sysfs_close_class(class);
187
static int refresh_class_device_list(void)
190
struct dlist *cname_list;
192
char sysfs_mntpath[SYSFS_PATH_MAX];
193
char class_path[SYSFS_PATH_MAX];
195
ret = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX);
197
dbg("sysfs_get_mnt_path failed");
201
snprintf(class_path, sizeof(class_path), "%s/%s", sysfs_mntpath,
204
/* search under /sys/class */
205
cname_list = sysfs_open_directory_list(class_path);
207
dbg("sysfs_open_directory failed");
211
dlist_for_each_data(cname_list, cname, char) {
212
ret = search_class_for_usbip_device(cname);
214
sysfs_close_list(cname_list);
219
sysfs_close_list(cname_list);
221
/* seach under /sys/block */
222
ret = search_class_for_usbip_device(SYSFS_BLOCK_NAME);
230
static int refresh_imported_device_list(void)
232
struct sysfs_attribute *attr_status;
235
attr_status = sysfs_get_device_attr(vhci_driver->hc_device, "status");
237
dbg("sysfs_get_device_attr(\"status\") failed: %s",
238
vhci_driver->hc_device->name);
242
dbg("name: %s path: %s len: %d method: %d value: %s",
243
attr_status->name, attr_status->path, attr_status->len,
244
attr_status->method, attr_status->value);
246
return parse_status(attr_status->value);
249
static int get_nports(void)
253
struct sysfs_attribute *attr_status;
255
attr_status = sysfs_get_device_attr(vhci_driver->hc_device, "status");
257
dbg("sysfs_get_device_attr(\"status\") failed: %s",
258
vhci_driver->hc_device->name);
262
dbg("name: %s path: %s len: %d method: %d value: %s",
263
attr_status->name, attr_status->path, attr_status->len,
264
attr_status->method, attr_status->value);
266
/* skip a header line */
267
c = strchr(attr_status->value, '\n') + 1;
270
/* go to the next line */
271
c = strchr(c, '\n') + 1;
278
static int get_hc_busid(char *sysfs_mntpath, char *hc_busid)
280
struct sysfs_driver *sdriver;
281
char sdriver_path[SYSFS_PATH_MAX];
283
struct sysfs_device *hc_dev;
284
struct dlist *hc_devs;
288
snprintf(sdriver_path, SYSFS_PATH_MAX, "%s/%s/%s/%s/%s", sysfs_mntpath,
289
SYSFS_BUS_NAME, USBIP_VHCI_BUS_TYPE, SYSFS_DRIVERS_NAME,
290
USBIP_VHCI_DRV_NAME);
292
sdriver = sysfs_open_driver_path(sdriver_path);
294
dbg("sysfs_open_driver_path failed: %s", sdriver_path);
295
dbg("make sure " USBIP_CORE_MOD_NAME ".ko and "
296
USBIP_VHCI_DRV_NAME ".ko are loaded!");
300
hc_devs = sysfs_get_driver_devices(sdriver);
302
dbg("sysfs_get_driver failed");
306
/* assume only one vhci_hcd */
307
dlist_for_each_data(hc_devs, hc_dev, struct sysfs_device) {
308
strncpy(hc_busid, hc_dev->bus_id, SYSFS_BUS_ID_SIZE);
313
sysfs_close_driver(sdriver);
318
dbg("%s not found", hc_busid);
323
/* ---------------------------------------------------------------------- */
325
int usbip_vhci_driver_open(void)
328
char hc_busid[SYSFS_BUS_ID_SIZE];
330
vhci_driver = (struct usbip_vhci_driver *) calloc(1, sizeof(*vhci_driver));
332
dbg("calloc failed");
336
ret = sysfs_get_mnt_path(vhci_driver->sysfs_mntpath, SYSFS_PATH_MAX);
338
dbg("sysfs_get_mnt_path failed");
342
ret = get_hc_busid(vhci_driver->sysfs_mntpath, hc_busid);
346
/* will be freed in usbip_driver_close() */
347
vhci_driver->hc_device = sysfs_open_device(USBIP_VHCI_BUS_TYPE,
349
if (!vhci_driver->hc_device) {
350
dbg("sysfs_open_device failed");
354
vhci_driver->nports = get_nports();
356
dbg("available ports: %d", vhci_driver->nports);
358
vhci_driver->cdev_list = dlist_new(sizeof(struct usbip_class_device));
359
if (!vhci_driver->cdev_list)
362
if (refresh_class_device_list())
365
if (refresh_imported_device_list())
373
if (vhci_driver->cdev_list)
374
dlist_destroy(vhci_driver->cdev_list);
375
if (vhci_driver->hc_device)
376
sysfs_close_device(vhci_driver->hc_device);
385
void usbip_vhci_driver_close()
390
if (vhci_driver->cdev_list)
391
dlist_destroy(vhci_driver->cdev_list);
393
for (int i = 0; i < vhci_driver->nports; i++) {
394
if (vhci_driver->idev[i].cdev_list)
395
dlist_destroy(vhci_driver->idev[i].cdev_list);
398
if (vhci_driver->hc_device)
399
sysfs_close_device(vhci_driver->hc_device);
406
int usbip_vhci_refresh_device_list(void)
408
if (vhci_driver->cdev_list)
409
dlist_destroy(vhci_driver->cdev_list);
412
for (int i = 0; i < vhci_driver->nports; i++) {
413
if (vhci_driver->idev[i].cdev_list)
414
dlist_destroy(vhci_driver->idev[i].cdev_list);
417
vhci_driver->cdev_list = dlist_new(sizeof(struct usbip_class_device));
418
if (!vhci_driver->cdev_list)
421
if (refresh_class_device_list())
424
if (refresh_imported_device_list())
429
if (vhci_driver->cdev_list)
430
dlist_destroy(vhci_driver->cdev_list);
432
for (int i = 0; i < vhci_driver->nports; i++) {
433
if (vhci_driver->idev[i].cdev_list)
434
dlist_destroy(vhci_driver->idev[i].cdev_list);
437
dbg("failed to refresh device list");
442
int usbip_vhci_get_free_port(void)
444
for (int i = 0; i < vhci_driver->nports; i++) {
445
if (vhci_driver->idev[i].status == VDEV_ST_NULL)
452
int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
454
struct sysfs_attribute *attr_attach;
455
char buff[200]; /* what size should be ? */
458
attr_attach = sysfs_get_device_attr(vhci_driver->hc_device, "attach");
460
dbg("sysfs_get_device_attr(\"attach\") failed: %s",
461
vhci_driver->hc_device->name);
465
snprintf(buff, sizeof(buff), "%u %u %u %u",
466
port, sockfd, devid, speed);
467
dbg("writing: %s", buff);
469
ret = sysfs_write_attribute(attr_attach, buff, strlen(buff));
471
dbg("sysfs_write_attribute failed");
475
dbg("attached port: %d", port);
480
static unsigned long get_devid(uint8_t busnum, uint8_t devnum)
482
return (busnum << 16) | devnum;
485
/* will be removed */
486
int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
487
uint8_t devnum, uint32_t speed)
489
int devid = get_devid(busnum, devnum);
491
return usbip_vhci_attach_device2(port, sockfd, devid, speed);
494
int usbip_vhci_detach_device(uint8_t port)
496
struct sysfs_attribute *attr_detach;
497
char buff[200]; /* what size should be ? */
500
attr_detach = sysfs_get_device_attr(vhci_driver->hc_device, "detach");
502
dbg("sysfs_get_device_attr(\"detach\") failed: %s",
503
vhci_driver->hc_device->name);
507
snprintf(buff, sizeof(buff), "%u", port);
508
dbg("writing: %s", buff);
510
ret = sysfs_write_attribute(attr_detach, buff, strlen(buff));
512
dbg("sysfs_write_attribute failed");
516
dbg("detached port: %d", port);