/** * sysfs_get_class_device: get specific class device using the device's id * @cls: sysfs_class to find the device on * @name: name of the class device to look for * * Returns sysfs_class_device * on success and NULL on failure */ struct sysfs_class_device *sysfs_get_class_device(struct sysfs_class *cls, const char *name) { char path[SYSFS_PATH_MAX]; struct sysfs_class_device *cdev = NULL; if (!cls || !name) { errno = EINVAL; return NULL; } if (cls->devices) { cdev = (struct sysfs_class_device *)dlist_find_custom (cls->devices, (void *)name, cdev_name_equal); if (cdev) return cdev; } safestrcpy(path, cls->path); safestrcat(path, "/"); safestrcat(path, name); cdev = sysfs_open_class_device_path(path); if (!cdev) { dprintf("Error opening class device at %s\n", path); return NULL; } if (!cls->devices) cls->devices = dlist_new_with_delete (sizeof(struct sysfs_class_device), sysfs_close_cls_dev); dlist_unshift_sorted(cls->devices, cdev, sort_list); return cdev; }
/** * Add class devices to list */ static void add_cdevs_to_classlist(struct sysfs_class *cls, struct dlist *list) { char path[SYSFS_PATH_MAX], *cdev_name; struct sysfs_class_device *cdev = NULL; if (cls == NULL || list == NULL) return; dlist_for_each_data(list, cdev_name, char) { if (cls->devices) { cdev = (struct sysfs_class_device *) dlist_find_custom(cls->devices, (void *)cdev_name, cdev_name_equal); if (cdev) continue; } safestrcpy(path, cls->path); safestrcat(path, "/"); safestrcat(path, cdev_name); cdev = sysfs_open_class_device_path(path); if (cdev) { if (!cls->devices) cls->devices = dlist_new_with_delete (sizeof(struct sysfs_class_device), sysfs_close_cls_dev); dlist_unshift_sorted(cls->devices, cdev, sort_list); } } }
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); } }
/** * sysfs_get_bus_driver: Get specific driver on bus using driver name * @bus: bus to find driver on * @drvname: name of driver * returns struct sysfs_driver reference or NULL if not found. */ struct sysfs_driver *sysfs_get_bus_driver(struct sysfs_bus *bus, const char *drvname) { struct sysfs_driver *drv; char drvpath[SYSFS_PATH_MAX]; if (!bus || !drvname) { errno = EINVAL; return NULL; } if (bus->drivers) { drv = (struct sysfs_driver *)dlist_find_custom (bus->drivers, (void *)drvname, name_equal); if (drv) return drv; } safestrcpy(drvpath, bus->path); safestrcat(drvpath, "/"); safestrcat(drvpath, SYSFS_DRIVERS_NAME); safestrcat(drvpath, "/"); safestrcat(drvpath, drvname); drv = sysfs_open_driver_path(drvpath); if (!drv) { dprintf("Error opening driver at %s\n", drvpath); return NULL; } if (!bus->drivers) bus->drivers = dlist_new_with_delete (sizeof(struct sysfs_driver), sysfs_close_drv); dlist_unshift_sorted(bus->drivers, drv, sort_list); return drv; }
/** * add_attribute: open and add attribute at path to given directory * @dev: device whose attribute is to be added * @path: path to attribute * returns pointer to attr added with success and NULL with error. */ static struct sysfs_attribute *add_attribute(void *dev, const char *path) { struct sysfs_attribute *attr; attr = sysfs_open_attribute(path); if (!attr) { dprintf("Error opening attribute %s\n", path); return NULL; } if (attr->method & SYSFS_METHOD_SHOW) { if (sysfs_read_attribute(attr)) { dprintf("Error reading attribute %s\n", path); sysfs_close_attribute(attr); return NULL; } } if (!((struct sysfs_device *)dev)->attrlist) { ((struct sysfs_device *)dev)->attrlist = dlist_new_with_delete (sizeof(struct sysfs_attribute), sysfs_del_attribute); } dlist_unshift_sorted(((struct sysfs_device *)dev)->attrlist, attr, sort_list); return attr; }
/** * sysfs_get_bus_devices: gets all devices for bus * @bus: bus to get devices for * returns dlist of devices with success and NULL with failure */ struct dlist *sysfs_get_bus_devices(struct sysfs_bus *bus) { struct sysfs_device *dev; struct dlist *linklist; char path[SYSFS_PATH_MAX], devpath[SYSFS_PATH_MAX]; char target[SYSFS_PATH_MAX]; char *curlink; if (!bus) { errno = EINVAL; return NULL; } memset(path, 0, SYSFS_PATH_MAX); safestrcpy(path, bus->path); safestrcat(path, "/"); safestrcat(path, SYSFS_DEVICES_NAME); linklist = read_dir_links(path); if (linklist) { dlist_for_each_data(linklist, curlink, char) { if (bus->devices) { dev = (struct sysfs_device *) dlist_find_custom(bus->devices, (void *)curlink, name_equal); if (dev) continue; } safestrcpy(devpath, path); safestrcat(devpath, "/"); safestrcat(devpath, curlink); if (sysfs_get_link(devpath, target, SYSFS_PATH_MAX)) { dprintf("Error getting link - %s\n", devpath); continue; } dev = sysfs_open_device_path(target); if (!dev) { dprintf("Error opening device at %s\n", target); continue; } if (!bus->devices) bus->devices = dlist_new_with_delete (sizeof(struct sysfs_device), sysfs_close_dev); dlist_unshift_sorted(bus->devices, dev, sort_list); } sysfs_close_list(linklist); } return (bus->devices); }
/** * sysfs_get_bus_drivers: gets all drivers for bus * @bus: bus to get devices for * returns dlist of devices with success and NULL with failure */ struct dlist *sysfs_get_bus_drivers(struct sysfs_bus *bus) { struct sysfs_driver *drv; struct dlist *dirlist; char path[SYSFS_PATH_MAX], drvpath[SYSFS_PATH_MAX]; char *curdir; if (!bus) { errno = EINVAL; return NULL; } memset(path, 0, SYSFS_PATH_MAX); safestrcpy(path, bus->path); safestrcat(path, "/"); safestrcat(path, SYSFS_DRIVERS_NAME); dirlist = read_dir_subdirs(path); if (dirlist) { dlist_for_each_data(dirlist, curdir, char) { if (bus->drivers) { drv = (struct sysfs_driver *) dlist_find_custom(bus->drivers, (void *)curdir, name_equal); if (drv) continue; } safestrcpy(drvpath, path); safestrcat(drvpath, "/"); safestrcat(drvpath, curdir); drv = sysfs_open_driver_path(drvpath); if (!drv) { dprintf("Error opening driver at %s\n", drvpath); continue; } if (!bus->drivers) bus->drivers = dlist_new_with_delete (sizeof(struct sysfs_driver), sysfs_close_drv); dlist_unshift_sorted(bus->drivers, drv, sort_list); } sysfs_close_list(dirlist); } return (bus->drivers); }
int add_subdirectory(struct sysfs_device *dev, char *path) { struct sysfs_device *newdev; if (!path) return -1; newdev = sysfs_open_device_path(path); if (newdev == NULL) return -1; if (dev->children == NULL) dev->children = dlist_new_with_delete( sizeof(struct sysfs_device), sysfs_close_dev_tree); dlist_unshift_sorted(dev->children, newdev, sort_list); return 0; }
/** * read_dir_subdirs: grabs subdirs in a specific directory * @sysdir: sysfs directory to read * returns list of directory names with success and NULL with error. */ struct dlist *read_dir_subdirs(const char *path) { DIR *dir = NULL; struct dirent *dirent = NULL; char file_path[SYSFS_PATH_MAX], *dir_name; struct dlist *dirlist = NULL; if (!path) { errno = EINVAL; return NULL; } dir = opendir(path); if (!dir) { dprintf("Error opening directory %s\n", path); return NULL; } while ((dirent = readdir(dir)) != NULL) { if (0 == strcmp(dirent->d_name, ".")) continue; if (0 == strcmp(dirent->d_name, "..")) continue; memset(file_path, 0, SYSFS_PATH_MAX); safestrcpy(file_path, path); safestrcat(file_path, "/"); safestrcat(file_path, dirent->d_name); if (!sysfs_path_is_dir(file_path)) { if (!dirlist) { dirlist = dlist_new_with_delete (SYSFS_NAME_LEN, sysfs_del_name); if (!dirlist) { dprintf("Error creating list\n"); return NULL; } } dir_name = (char *)calloc(1, SYSFS_NAME_LEN); safestrcpymax(dir_name, dirent->d_name, SYSFS_NAME_LEN); dlist_unshift_sorted(dirlist, dir_name, sort_char); } } closedir(dir); return dirlist; }
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; }
/** * get_attributes_list: build a list of attributes for the given path * @path: grab attributes at the given path * returns dlist of attributes on success and NULL on failure */ struct dlist *get_attributes_list(struct dlist *alist, const char *path) { DIR *dir = NULL; struct dirent *dirent = NULL; char file_path[SYSFS_PATH_MAX]; if (!path) { errno = EINVAL; return NULL; } dir = opendir(path); if (!dir) { dprintf("Error opening directory %s\n", path); return NULL; } while ((dirent = readdir(dir)) != NULL) { if (0 == strcmp(dirent->d_name, ".")) continue; if (0 == strcmp(dirent->d_name, "..")) continue; memset(file_path, 0, SYSFS_PATH_MAX); safestrcpy(file_path, path); safestrcat(file_path, "/"); safestrcat(file_path, dirent->d_name); if (!sysfs_path_is_file(file_path)) { if (!alist) { alist = dlist_new_with_delete (sizeof(struct sysfs_attribute), sysfs_del_attribute); if (!alist) { dprintf("Error creating list\n"); return NULL; } } add_attribute_to_list(alist, file_path); } } closedir(dir); return alist; }
/** * sysfs_get_driver_devices: gets list of devices that use the driver * @drv: sysfs_driver whose device list is needed * Returns dlist of struct sysfs_device on success and NULL on failure */ struct dlist *sysfs_get_driver_devices(struct sysfs_driver *drv) { char *ln = NULL; struct dlist *linklist = NULL; struct sysfs_device *dev = NULL; if (!drv) { errno = EINVAL; return NULL; } linklist = read_dir_links(drv->path); if (linklist) { dlist_for_each_data(linklist, ln, char) { if (!strncmp(ln, SYSFS_MODULE_NAME, strlen(ln))) continue; dev = sysfs_open_device(drv->bus, ln); if (!dev) { dprintf("Error opening driver's device\n"); sysfs_close_list(linklist); return NULL; } if (!drv->devices) { drv->devices = dlist_new_with_delete (sizeof(struct sysfs_device), sysfs_close_driver_device); if (!drv->devices) { dprintf("Error creating device list\n"); sysfs_close_list(linklist); return NULL; } } dlist_unshift_sorted(drv->devices, dev, sort_list); } sysfs_close_list(linklist); } return drv->devices; }
/** * sysfs_get_bus_device: Get specific device on bus using device's id * @bus: bus to find device on * @id: bus_id for device * returns struct sysfs_device reference or NULL if not found. */ struct sysfs_device *sysfs_get_bus_device(struct sysfs_bus *bus, const char *id) { struct sysfs_device *dev = NULL; char devpath[SYSFS_PATH_MAX], target[SYSFS_PATH_MAX]; if (!bus || !id) { errno = EINVAL; return NULL; } if (bus->devices) { dev = (struct sysfs_device *)dlist_find_custom (bus->devices, (void *)id, name_equal); if (dev) return dev; } safestrcpy(devpath, bus->path); safestrcat(devpath, "/"); safestrcat(devpath, SYSFS_DEVICES_NAME); safestrcat(devpath, "/"); safestrcat(devpath, id); if (sysfs_path_is_link(devpath)) { dprintf("No such device %s on bus %s?\n", id, bus->name); return NULL; } if (!sysfs_get_link(devpath, target, SYSFS_PATH_MAX)) { dev = sysfs_open_device_path(target); if (!dev) { dprintf("Error opening device at %s\n", target); return NULL; } if (!bus->devices) bus->devices = dlist_new_with_delete (sizeof(struct sysfs_device), sysfs_close_dev); dlist_unshift_sorted(bus->devices, dev, sort_list); } return dev; }
int usbip_stub_refresh_device_list(void) { int ret; if (stub_driver->edev_list) dlist_destroy(stub_driver->edev_list); 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"); return -1; } ret = refresh_exported_devices(); if (ret < 0) return ret; return 0; }
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); } }