static int check_usbip_device(struct usbip_vhci_driver *driver, struct sysfs_class_device *cdev) { char clspath[SYSFS_PATH_MAX]; /* /sys/class/video4linux/video0/device */ char devpath[SYSFS_PATH_MAX]; /* /sys/devices/platform/hc.0/usb6/6-1:1.1 */ int ret; snprintf(clspath, sizeof(clspath), "%s/device", cdev->path); ret = sysfs_get_link(clspath, devpath, SYSFS_PATH_MAX); if(!ret) { if(!strncmp(devpath, driver->hc_device->path, strlen(driver->hc_device->path))) { /* found usbip device */ struct class_device *cdev; cdev = calloc(1, sizeof*cdev); if(!cdev) { err("calloc cdev"); return -1; } dlist_unshift(driver->cdev_list, (void*) cdev); strncpy(cdev->clspath, clspath, sizeof(cdev->clspath)); strncpy(cdev->devpath, devpath, sizeof(cdev->clspath)); dbg(" found %s %s", clspath, devpath); } } return 0; }
static struct usbip_imported_device *imported_device_init(struct usbip_vhci_driver *driver, struct usbip_imported_device *idev, char *busid) { struct sysfs_device *sudev; sudev = sysfs_open_device("usb", busid); if(!sudev) { err("sysfs_open_device %s", busid); goto err; } read_usb_device(sudev, &idev->udev); sysfs_close_device(sudev); /* add class devices of this imported device */ struct class_device *cdev; dlist_for_each_data(driver->cdev_list, cdev, struct class_device) { if(!strncmp(cdev->devpath, idev->udev.path, strlen(idev->udev.path))) { struct class_device *new_cdev; /* alloc and copy because dlist is linked from only one list */ new_cdev = calloc(1, sizeof(*new_cdev)); if(!new_cdev) goto err; memcpy(new_cdev, cdev, sizeof(*new_cdev)); dlist_unshift(idev->cdev_list, (void*) new_cdev); } } return idev; err: return NULL; }
static int refresh_exported_devices(void) { struct sysfs_device *suinf; /* sysfs_device of usb_interface */ struct dlist *suinf_list; struct sysfs_device *sudev; /* sysfs_device of usb_device */ struct dlist *sudev_list; sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device), delete_nothing); suinf_list = sysfs_get_driver_devices(stub_driver->sysfs_driver); if (!suinf_list) { printf("Bind usbip.ko to a usb device to be exportable!\n"); goto bye; } /* collect unique USB devices (not interfaces) */ dlist_for_each_data(suinf_list, suinf, struct sysfs_device) { /* get usb device of this usb interface */ sudev = sysfs_get_device_parent(suinf); if (!sudev) { err("get parent dev of %s", suinf->name); continue; } if (check_new(sudev_list, sudev)) { dlist_unshift(sudev_list, sudev); } }
dlist_for_each_data(sudev_list, sudev, struct sysfs_device) { edev = usbip_exported_device_new(sudev->path); if (!edev) { dbg("usbip_exported_device_new failed"); continue; } dlist_unshift(host_driver->edev_list, edev); host_driver->ndevs++; }
dlist_for_each_data(sudev_list, sudev, struct sysfs_device) { struct usbip_exported_device *edev; edev = usbip_exported_device_new(sudev->path); if (!edev) { err("usbip_exported_device new"); continue; } dlist_unshift(stub_driver->edev_list, (void *) edev); stub_driver->ndevs++; }
static struct usbip_imported_device *usbip_imported_device_new(struct usbip_vhci_driver *driver, char *busid) { struct usbip_imported_device *idev = NULL; struct sysfs_device *sudev; idev = (struct usbip_imported_device *) calloc(1, sizeof(*idev)); if(!idev) return NULL; /* * The members of idev->cdev_list are also linked from * driver->cdev_list. They are freed by destroy of driver->cdev_list. * */ idev->cdev_list = dlist_new(sizeof(struct class_device)); if(!idev->cdev_list) goto err; sudev = sysfs_open_device("usb", busid); if(!sudev) { err("sysfs_open_device %s", busid); goto err; } read_usb_device(sudev, &idev->udev); sysfs_close_device(sudev); /* add class devices of this imported device */ struct class_device *cdev; dlist_for_each_data(driver->cdev_list, cdev, struct class_device) { if(!strncmp(cdev->devpath, idev->udev.path, strlen(idev->udev.path))) { struct class_device *new_cdev; new_cdev = calloc(1, sizeof(*new_cdev)); if(!new_cdev) goto err; memcpy(new_cdev, cdev, sizeof(*new_cdev)); dlist_unshift(idev->cdev_list, (void*) new_cdev); } } return idev; err: if(idev->cdev_list) dlist_destroy(idev->cdev_list); if(idev) free(idev); return NULL; }
static int refresh_exported_devices(void) { /* sysfs_device of usb_interface */ struct sysfs_device *suintf; struct dlist *suintf_list; /* sysfs_device of usb_device */ struct sysfs_device *sudev; struct dlist *sudev_list; struct usbip_exported_device *edev; sudev_list = dlist_new_with_delete(sizeof(struct sysfs_device), delete_nothing); suintf_list = sysfs_get_driver_devices(host_driver->sysfs_driver); if (!suintf_list) { /* * Not an error condition. There are simply no devices bound to * the driver yet. */ dbg("bind " USBIP_HOST_DRV_NAME ".ko to a usb device to be " "exportable!"); return 0; } /* collect unique USB devices (not interfaces) */ dlist_for_each_data(suintf_list, suintf, struct sysfs_device) { /* get usb device of this usb interface */ sudev = sysfs_get_device_parent(suintf); if (!sudev) { dbg("sysfs_get_device_parent failed: %s", suintf->name); continue; } if (check_new(sudev_list, sudev)) { /* insert item at head of list */ dlist_unshift(sudev_list, sudev); } }