void usbip_stub_driver_close(void) { if (!stub_driver) return; if (stub_driver->edev_list) dlist_destroy(stub_driver->edev_list); if (stub_driver->sysfs_driver) sysfs_close_driver(stub_driver->sysfs_driver); free(stub_driver); stub_driver = NULL; }
/** * sysfs_open_driver_path: opens and initializes driver structure * @path: path to driver directory * returns struct sysfs_driver with success and NULL with error */ struct sysfs_driver *sysfs_open_driver_path(const char *path) { struct sysfs_driver *driver = NULL; if (!path) { errno = EINVAL; return NULL; } if (sysfs_path_is_dir(path)) { dprintf("Invalid path to driver: %s\n", path); return NULL; } driver = alloc_driver(); if (!driver) { dprintf("Error allocating driver at %s\n", path); return NULL; } if (sysfs_get_name_from_path(path, driver->name, SYSFS_NAME_LEN)) { dprintf("Error getting driver name from path\n"); free(driver); return NULL; } safestrcpy(driver->path, path); if (sysfs_remove_trailing_slash(driver->path)) { dprintf("Invalid path to driver %s\n", driver->path); sysfs_close_driver(driver); return NULL; } if (get_driver_bus(driver)) { dprintf("Could not get the bus driver is on\n"); sysfs_close_driver(driver); return NULL; } return driver; }
int usbip_stub_driver_open(void) { int ret; stub_driver = (struct usbip_stub_driver *) calloc(1, sizeof(*stub_driver)); if (!stub_driver) { err("alloc stub_driver"); return -1; } stub_driver->ndevs = 0; stub_driver->edev_list = dlist_new_with_delete(sizeof(struct usbip_exported_device), usbip_exported_device_delete); if (!stub_driver->edev_list) { err("alloc dlist"); goto err; } stub_driver->sysfs_driver = open_sysfs_stub_driver(); if (!stub_driver->sysfs_driver) goto err; ret = refresh_exported_devices(); if (ret < 0) goto err; return 0; err: if (stub_driver->sysfs_driver) sysfs_close_driver(stub_driver->sysfs_driver); if (stub_driver->edev_list) dlist_destroy(stub_driver->edev_list); free(stub_driver); stub_driver = NULL; return -1; }
static void sysfs_close_drv(void *drv) { sysfs_close_driver((struct sysfs_driver *)drv); }
/* buggy driver may cause dead lock */ static int unbind_other(char *busid) { char bus_type[] = "usb"; char intf_busid[SYSFS_BUS_ID_SIZE]; struct sysfs_device *busid_dev; struct sysfs_device *intf_dev; struct sysfs_driver *intf_drv; struct sysfs_attribute *unbind_attr; struct sysfs_attribute *bConfValue; struct sysfs_attribute *bDevClass; struct sysfs_attribute *bNumIntfs; int i, rc; enum unbind_status status = UNBIND_ST_OK; busid_dev = sysfs_open_device(bus_type, busid); if (!busid_dev) { dbg("sysfs_open_device %s failed: %s", busid, strerror(errno)); return -1; } bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue"); bDevClass = sysfs_get_device_attr(busid_dev, "bDeviceClass"); bNumIntfs = sysfs_get_device_attr(busid_dev, "bNumInterfaces"); if (!bConfValue || !bDevClass || !bNumIntfs) { dbg("problem getting device attributes: %s", strerror(errno)); goto err_close_busid_dev; } if (!strncmp(bDevClass->value, "09", bDevClass->len)) { dbg("skip unbinding of hub"); goto err_close_busid_dev; } for (i = 0; i < atoi(bNumIntfs->value); i++) { snprintf(intf_busid, SYSFS_BUS_ID_SIZE, "%s:%.1s.%d", busid, bConfValue->value, i); intf_dev = sysfs_open_device(bus_type, intf_busid); if (!intf_dev) { dbg("could not open interface device: %s", strerror(errno)); goto err_close_busid_dev; } dbg("%s -> %s", intf_dev->name, intf_dev->driver_name); if (!strncmp("unknown", intf_dev->driver_name, SYSFS_NAME_LEN)) /* unbound interface */ continue; if (!strncmp(USBIP_HOST_DRV_NAME, intf_dev->driver_name, SYSFS_NAME_LEN)) { /* already bound to usbip-host */ status = UNBIND_ST_USBIP_HOST; continue; } /* unbinding */ intf_drv = sysfs_open_driver(bus_type, intf_dev->driver_name); if (!intf_drv) { dbg("could not open interface driver on %s: %s", intf_dev->name, strerror(errno)); goto err_close_intf_dev; } unbind_attr = sysfs_get_driver_attr(intf_drv, "unbind"); if (!unbind_attr) { dbg("problem getting interface driver attribute: %s", strerror(errno)); goto err_close_intf_drv; } rc = sysfs_write_attribute(unbind_attr, intf_dev->bus_id, SYSFS_BUS_ID_SIZE); if (rc < 0) { /* NOTE: why keep unbinding other interfaces? */ dbg("unbind driver at %s failed", intf_dev->bus_id); status = UNBIND_ST_FAILED; } sysfs_close_driver(intf_drv); sysfs_close_device(intf_dev); } goto out; err_close_intf_drv: sysfs_close_driver(intf_drv); err_close_intf_dev: sysfs_close_device(intf_dev); err_close_busid_dev: status = UNBIND_ST_FAILED; out: sysfs_close_device(busid_dev); return status; }