diff options
Diffstat (limited to 'drivers/staging/usbip/userspace')
21 files changed, 631 insertions, 966 deletions
diff --git a/drivers/staging/usbip/userspace/README b/drivers/staging/usbip/userspace/README index 00a1658..f528ba4 100644 --- a/drivers/staging/usbip/userspace/README +++ b/drivers/staging/usbip/userspace/README @@ -9,8 +9,8 @@ - USB/IP device drivers Found in the staging directory of the Linux kernel. - - sysfsutils >= 2.0.0 - sysfsutils library + - libudev >= 2.0 + libudev library - libwrap0-dev tcp wrapper library @@ -19,6 +19,10 @@ - libtool, automake >= 1.9, autoconf >= 2.5.0, pkg-config +[Optional] + - hwdata + Contains USB device identification data. + [Install] 0. Generate configuration scripts. diff --git a/drivers/staging/usbip/userspace/configure.ac b/drivers/staging/usbip/userspace/configure.ac index 0ee5d92..607d05c 100644 --- a/drivers/staging/usbip/userspace/configure.ac +++ b/drivers/staging/usbip/userspace/configure.ac @@ -1,7 +1,7 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT([usbip-utils], [1.1.1], [linux-usb@vger.kernel.org]) +AC_INIT([usbip-utils], [2.0], [linux-usb@vger.kernel.org]) AC_DEFINE([USBIP_VERSION], [0x00000111], [binary-coded decimal version number]) CURRENT=0 @@ -44,11 +44,11 @@ AC_FUNC_REALLOC AC_CHECK_FUNCS([memset mkdir regcomp socket strchr strerror strstr dnl strtoul]) -AC_CHECK_HEADER([sysfs/libsysfs.h], - [AC_CHECK_LIB([sysfs], [sysfs_open_directory_list], - [LIBS="$LIBS -lsysfs"], - [AC_MSG_ERROR([Missing sysfs2 library!])])], - [AC_MSG_ERROR([Missing /usr/include/sysfs/libsysfs.h])]) +AC_CHECK_HEADER([libudev.h], + [AC_CHECK_LIB([udev], [udev_new], + [LIBS="$LIBS -ludev"], + [AC_MSG_ERROR([Missing udev library!])])], + [AC_MSG_ERROR([Missing /usr/include/libudev.h])]) # Checks for libwrap library. AC_MSG_CHECKING([whether to use the libwrap (TCP wrappers) library]) diff --git a/drivers/staging/usbip/userspace/libsrc/Makefile.am b/drivers/staging/usbip/userspace/libsrc/Makefile.am index 4921189..7c8f8a4 100644 --- a/drivers/staging/usbip/userspace/libsrc/Makefile.am +++ b/drivers/staging/usbip/userspace/libsrc/Makefile.am @@ -4,4 +4,5 @@ libusbip_la_LDFLAGS = -version-info @LIBUSBIP_VERSION@ lib_LTLIBRARIES := libusbip.la libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \ - usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h + usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h \ + sysfs_utils.c sysfs_utils.h diff --git a/drivers/staging/usbip/userspace/libsrc/list.h b/drivers/staging/usbip/userspace/libsrc/list.h new file mode 100644 index 0000000..8d0c936 --- /dev/null +++ b/drivers/staging/usbip/userspace/libsrc/list.h @@ -0,0 +1,136 @@ +#ifndef _LIST_H +#define _LIST_H + +/* Stripped down implementation of linked list taken + * from the Linux Kernel. + */ + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +#define POISON_POINTER_DELTA 0 +#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA) +#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA) + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void __list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +#endif diff --git a/drivers/staging/usbip/userspace/libsrc/sysfs_utils.c b/drivers/staging/usbip/userspace/libsrc/sysfs_utils.c new file mode 100644 index 0000000..36ac88e --- /dev/null +++ b/drivers/staging/usbip/userspace/libsrc/sysfs_utils.c @@ -0,0 +1,31 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + +#include "sysfs_utils.h" +#include "usbip_common.h" + +int write_sysfs_attribute(const char *attr_path, const char *new_value, + size_t len) +{ + int fd; + int length; + + fd = open(attr_path, O_WRONLY); + if (fd < 0) { + dbg("error opening attribute %s", attr_path); + return -1; + } + + length = write(fd, new_value, len); + if (length < 0) { + dbg("error writing to attribute %s", attr_path); + close(fd); + return -1; + } + + close(fd); + + return 0; +} diff --git a/drivers/staging/usbip/userspace/libsrc/sysfs_utils.h b/drivers/staging/usbip/userspace/libsrc/sysfs_utils.h new file mode 100644 index 0000000..32ac1d1 --- /dev/null +++ b/drivers/staging/usbip/userspace/libsrc/sysfs_utils.h @@ -0,0 +1,8 @@ + +#ifndef __SYSFS_UTILS_H +#define __SYSFS_UTILS_H + +int write_sysfs_attribute(const char *attr_path, const char *new_value, + size_t len); + +#endif diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.c b/drivers/staging/usbip/userspace/libsrc/usbip_common.c index 66f03cc..238bf5b 100644 --- a/drivers/staging/usbip/userspace/libsrc/usbip_common.c +++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.c @@ -2,6 +2,7 @@ * Copyright (C) 2005-2007 Takahiro Hirofuchi */ +#include <libudev.h> #include "usbip_common.h" #include "names.h" @@ -12,6 +13,8 @@ int usbip_use_syslog; int usbip_use_stderr; int usbip_use_debug; +extern struct udev *udev_context; + struct speed_string { int num; char *speed; @@ -23,6 +26,8 @@ static const struct speed_string speed_strings[] = { { USB_SPEED_LOW, "1.5", "Low Speed(1.5Mbps)" }, { USB_SPEED_FULL, "12", "Full Speed(12Mbps)" }, { USB_SPEED_HIGH, "480", "High Speed(480Mbps)" }, + { USB_SPEED_WIRELESS, "53.3-480", "Wireless"}, + { USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" }, { 0, NULL, NULL } }; @@ -109,75 +114,61 @@ void dump_usb_device(struct usbip_usb_device *udev) } -int read_attr_value(struct sysfs_device *dev, const char *name, +int read_attr_value(struct udev_device *dev, const char *name, const char *format) { - char attrpath[SYSFS_PATH_MAX]; - struct sysfs_attribute *attr; + const char *attr; int num = 0; int ret; - snprintf(attrpath, sizeof(attrpath), "%s/%s", dev->path, name); - - attr = sysfs_open_attribute(attrpath); + attr = udev_device_get_sysattr_value(dev, name); if (!attr) { - dbg("sysfs_open_attribute failed: %s", attrpath); - return 0; - } - - ret = sysfs_read_attribute(attr); - if (ret < 0) { - dbg("sysfs_read_attribute failed"); + err("udev_device_get_sysattr_value failed"); goto err; } - ret = sscanf(attr->value, format, &num); + /* The client chooses the device configuration + * when attaching it so right after being bound + * to usbip-host on the server the device will + * have no configuration. + * Therefore, attributes such as bConfigurationValue + * and bNumInterfaces will not exist and sscanf will + * fail. Check for these cases and don't treat them + * as errors. + */ + + ret = sscanf(attr, format, &num); if (ret < 1) { - dbg("sscanf failed"); - goto err; + if (strcmp(name, "bConfigurationValue") && + strcmp(name, "bNumInterfaces")) { + err("sscanf failed for attribute %s", name); + goto err; + } } err: - sysfs_close_attribute(attr); return num; } -int read_attr_speed(struct sysfs_device *dev) +int read_attr_speed(struct udev_device *dev) { - char attrpath[SYSFS_PATH_MAX]; - struct sysfs_attribute *attr; - char speed[100]; - int ret; - - snprintf(attrpath, sizeof(attrpath), "%s/%s", dev->path, "speed"); - - attr = sysfs_open_attribute(attrpath); - if (!attr) { - dbg("sysfs_open_attribute failed: %s", attrpath); - return 0; - } + const char *speed; - ret = sysfs_read_attribute(attr); - if (ret < 0) { - dbg("sysfs_read_attribute failed"); + speed = udev_device_get_sysattr_value(dev, "speed"); + if (!speed) { + err("udev_device_get_sysattr_value failed"); goto err; } - ret = sscanf(attr->value, "%99s\n", speed); - if (ret < 1) { - dbg("sscanf failed"); - goto err; - } -err: - sysfs_close_attribute(attr); - for (int i = 0; speed_strings[i].speed != NULL; i++) { if (!strcmp(speed, speed_strings[i].speed)) return speed_strings[i].num; } +err: + return USB_SPEED_UNKNOWN; } @@ -188,9 +179,10 @@ err: } while (0) -int read_usb_device(struct sysfs_device *sdev, struct usbip_usb_device *udev) +int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev) { uint32_t busnum, devnum; + const char *path, *name; READ_ATTR(udev, uint8_t, sdev, bDeviceClass, "%02x\n"); READ_ATTR(udev, uint8_t, sdev, bDeviceSubClass, "%02x\n"); @@ -207,10 +199,13 @@ int read_usb_device(struct sysfs_device *sdev, struct usbip_usb_device *udev) READ_ATTR(udev, uint8_t, sdev, devnum, "%d\n"); udev->speed = read_attr_speed(sdev); - strncpy(udev->path, sdev->path, SYSFS_PATH_MAX); - strncpy(udev->busid, sdev->name, SYSFS_BUS_ID_SIZE); + path = udev_device_get_syspath(sdev); + name = udev_device_get_sysname(sdev); - sscanf(sdev->name, "%u-%u", &busnum, &devnum); + strncpy(udev->path, path, SYSFS_PATH_MAX); + strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE); + + sscanf(name, "%u-%u", &busnum, &devnum); udev->busnum = busnum; return 0; @@ -220,13 +215,13 @@ int read_usb_interface(struct usbip_usb_device *udev, int i, struct usbip_usb_interface *uinf) { char busid[SYSFS_BUS_ID_SIZE]; - struct sysfs_device *sif; + struct udev_device *sif; sprintf(busid, "%s:%d.%d", udev->busid, udev->bConfigurationValue, i); - sif = sysfs_open_device("usb", busid); + sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid); if (!sif) { - dbg("sysfs_open_device(\"usb\", \"%s\") failed", busid); + err("udev_device_new_from_subsystem_sysname %s failed", busid); return -1; } @@ -234,8 +229,6 @@ int read_usb_interface(struct usbip_usb_device *udev, int i, READ_ATTR(uinf, uint8_t, sif, bInterfaceSubClass, "%02x\n"); READ_ATTR(uinf, uint8_t, sif, bInterfaceProtocol, "%02x\n"); - sysfs_close_device(sif); - return 0; } diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.h b/drivers/staging/usbip/userspace/libsrc/usbip_common.h index 938ad1c..23be848 100644 --- a/drivers/staging/usbip/userspace/libsrc/usbip_common.h +++ b/drivers/staging/usbip/userspace/libsrc/usbip_common.h @@ -5,7 +5,7 @@ #ifndef __USBIP_COMMON_H #define __USBIP_COMMON_H -#include <sysfs/libsysfs.h> +#include <libudev.h> #include <stdint.h> #include <stdio.h> @@ -14,6 +14,8 @@ #include <syslog.h> #include <unistd.h> +#include <linux/usb/ch9.h> +#include "../../uapi/usbip.h" #ifndef USBIDS_FILE #define USBIDS_FILE "/usr/share/hwdata/usb.ids" @@ -28,6 +30,15 @@ #define USBIP_HOST_DRV_NAME "usbip-host" #define USBIP_VHCI_DRV_NAME "vhci_hcd" +/* sysfs constants */ +#define SYSFS_MNT_PATH "/sys" +#define SYSFS_BUS_NAME "bus" +#define SYSFS_BUS_TYPE "usb" +#define SYSFS_DRIVERS_NAME "drivers" + +#define SYSFS_PATH_MAX 256 +#define SYSFS_BUS_ID_SIZE 32 + extern int usbip_use_syslog; extern int usbip_use_stderr; extern int usbip_use_debug ; @@ -76,30 +87,6 @@ extern int usbip_use_debug ; abort(); \ } while (0) -enum usb_device_speed { - USB_SPEED_UNKNOWN = 0, /* enumerating */ - USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ - USB_SPEED_HIGH, /* usb 2.0 */ - USB_SPEED_VARIABLE /* wireless (usb 2.5) */ -}; - -/* FIXME: how to sync with drivers/usbip_common.h ? */ -enum usbip_device_status { - /* sdev is available. */ - SDEV_ST_AVAILABLE = 0x01, - /* sdev is now used. */ - SDEV_ST_USED, - /* sdev is unusable because of a fatal error. */ - SDEV_ST_ERROR, - - /* vdev does not connect a remote device. */ - VDEV_ST_NULL, - /* vdev is used, but the USB address is not assigned yet */ - VDEV_ST_NOTASSIGNED, - VDEV_ST_USED, - VDEV_ST_ERROR -}; - struct usbip_usb_interface { uint8_t bInterfaceClass; uint8_t bInterfaceSubClass; @@ -131,8 +118,8 @@ struct usbip_usb_device { void dump_usb_interface(struct usbip_usb_interface *); void dump_usb_device(struct usbip_usb_device *); -int read_usb_device(struct sysfs_device *sdev, struct usbip_usb_device *udev); -int read_attr_value(struct sysfs_device *dev, const char *name, +int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev); +int read_attr_value(struct udev_device *dev, const char *name, const char *format); int read_usb_interface(struct usbip_usb_device *udev, int i, struct usbip_usb_interface *uinf); diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c index 71a449c..c5bf60b 100644 --- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c +++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c @@ -18,102 +18,65 @@ #include <sys/types.h> #include <sys/stat.h> +#include <fcntl.h> #include <errno.h> #include <unistd.h> +#include <libudev.h> + #include "usbip_common.h" #include "usbip_host_driver.h" +#include "list.h" +#include "sysfs_utils.h" #undef PROGNAME #define PROGNAME "libusbip" struct usbip_host_driver *host_driver; +struct udev *udev_context; -#define SYSFS_OPEN_RETRIES 100 - -/* only the first interface value is true! */ static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) { - char attrpath[SYSFS_PATH_MAX]; - struct sysfs_attribute *attr; + char status_attr_path[SYSFS_PATH_MAX]; + int fd; + int length; + char status; int value = 0; - int rc; - struct stat s; - int retries = SYSFS_OPEN_RETRIES; - - /* This access is racy! - * - * Just after detach, our driver removes the sysfs - * files and recreates them. - * - * We may try and fail to open the usbip_status of - * an exported device in the (short) window where - * it has been removed and not yet recreated. - * - * This is a bug in the interface. Nothing we can do - * except work around it here by polling for the sysfs - * usbip_status to reappear. - */ - - snprintf(attrpath, SYSFS_PATH_MAX, "%s/%s:%d.%d/usbip_status", - udev->path, udev->busid, udev->bConfigurationValue, 0); - - while (retries > 0) { - if (stat(attrpath, &s) == 0) - break; - - if (errno != ENOENT) { - dbg("stat failed: %s", attrpath); - return -1; - } - - usleep(10000); /* 10ms */ - retries--; - } - if (retries == 0) - dbg("usbip_status not ready after %d retries", - SYSFS_OPEN_RETRIES); - else if (retries < SYSFS_OPEN_RETRIES) - dbg("warning: usbip_status ready after %d retries", - SYSFS_OPEN_RETRIES - retries); + snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status", + udev->path); - attr = sysfs_open_attribute(attrpath); - if (!attr) { - dbg("sysfs_open_attribute failed: %s", attrpath); + if ((fd = open(status_attr_path, O_RDONLY)) < 0) { + err("error opening attribute %s", status_attr_path); return -1; } - rc = sysfs_read_attribute(attr); - if (rc) { - dbg("sysfs_read_attribute failed: %s", attrpath); - sysfs_close_attribute(attr); + length = read(fd, &status, 1); + if (length < 0) { + err("error reading attribute %s", status_attr_path); + close(fd); return -1; } - value = atoi(attr->value); - - sysfs_close_attribute(attr); + value = atoi(&status); return value; } -static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath) +static +struct usbip_exported_device *usbip_exported_device_new(const char *sdevpath) { struct usbip_exported_device *edev = NULL; + struct usbip_exported_device *edev_old; size_t size; int i; - edev = calloc(1, sizeof(*edev)); - if (!edev) { - dbg("calloc failed"); - return NULL; - } + edev = calloc(1, sizeof(struct usbip_exported_device)); - edev->sudev = sysfs_open_device_path(sdevpath); + edev->sudev = udev_device_new_from_syspath(udev_context, sdevpath); if (!edev->sudev) { - dbg("sysfs_open_device_path failed: %s", sdevpath); + err("udev_device_new_from_syspath: %s", sdevpath); goto err; } @@ -124,11 +87,13 @@ static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath) goto err; /* reallocate buffer to include usb interface data */ - size = sizeof(*edev) + edev->udev.bNumInterfaces * + size = sizeof(struct usbip_exported_device) + edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface); + edev_old = edev; edev = realloc(edev, size); if (!edev) { + edev = edev_old; dbg("realloc failed"); goto err; } @@ -138,160 +103,88 @@ static struct usbip_exported_device *usbip_exported_device_new(char *sdevpath) return edev; err: - if (edev && edev->sudev) - sysfs_close_device(edev->sudev); + if (edev->sudev) + udev_device_unref(edev->sudev); if (edev) free(edev); return NULL; } -static int check_new(struct dlist *dlist, struct sysfs_device *target) -{ - struct sysfs_device *dev; - - dlist_for_each_data(dlist, dev, struct sysfs_device) { - if (!strncmp(dev->bus_id, target->bus_id, SYSFS_BUS_ID_SIZE)) - /* device found and is not new */ - return 0; - } - return 1; -} - -static void delete_nothing(void *unused_data) -{ - /* - * NOTE: Do not delete anything, but the container will be deleted. - */ - (void) unused_data; -} - 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); - } - } - - 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; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *dev; + const char *path; + + enumerate = udev_enumerate_new(udev_context); + udev_enumerate_add_match_subsystem(enumerate, "usb"); + udev_enumerate_scan_devices(enumerate); + + devices = udev_enumerate_get_list_entry(enumerate); + + udev_list_entry_foreach(dev_list_entry, devices) { + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(udev_context, path); + + /* Check whether device uses usbip-host driver. */ + if (!strcmp(udev_device_get_driver(dev), + USBIP_HOST_DRV_NAME)) { + edev = usbip_exported_device_new(path); + if (!edev) { + dbg("usbip_exported_device_new failed"); + continue; + } + + list_add(&edev->node, &host_driver->edev_list); + host_driver->ndevs++; } - - dlist_unshift(host_driver->edev_list, edev); - host_driver->ndevs++; } - dlist_destroy(sudev_list); - return 0; } -static struct sysfs_driver *open_sysfs_host_driver(void) +static void usbip_exported_device_destroy(void) { - char bus_type[] = "usb"; - char sysfs_mntpath[SYSFS_PATH_MAX]; - char host_drv_path[SYSFS_PATH_MAX]; - struct sysfs_driver *host_drv; - int rc; - - rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); - if (rc < 0) { - dbg("sysfs_get_mnt_path failed"); - return NULL; - } - - snprintf(host_drv_path, SYSFS_PATH_MAX, "%s/%s/%s/%s/%s", - sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME, - USBIP_HOST_DRV_NAME); + struct list_head *i, *tmp; + struct usbip_exported_device *edev; - host_drv = sysfs_open_driver_path(host_drv_path); - if (!host_drv) { - dbg("sysfs_open_driver_path failed"); - return NULL; + list_for_each_safe(i, tmp, &host_driver->edev_list) { + edev = list_entry(i, struct usbip_exported_device, node); + list_del(i); + free(edev); } - - return host_drv; -} - -static void usbip_exported_device_delete(void *dev) -{ - struct usbip_exported_device *edev = dev; - sysfs_close_device(edev->sudev); - free(dev); } int usbip_host_driver_open(void) { int rc; - host_driver = calloc(1, sizeof(*host_driver)); - if (!host_driver) { - dbg("calloc failed"); + udev_context = udev_new(); + if (!udev_context) { + err("udev_new failed"); return -1; } - host_driver->ndevs = 0; - host_driver->edev_list = - dlist_new_with_delete(sizeof(struct usbip_exported_device), - usbip_exported_device_delete); - if (!host_driver->edev_list) { - dbg("dlist_new_with_delete failed"); - goto err_free_host_driver; - } + host_driver = calloc(1, sizeof(*host_driver)); - host_driver->sysfs_driver = open_sysfs_host_driver(); - if (!host_driver->sysfs_driver) - goto err_destroy_edev_list; + host_driver->ndevs = 0; + INIT_LIST_HEAD(&host_driver->edev_list); rc = refresh_exported_devices(); if (rc < 0) - goto err_close_sysfs_driver; + goto err_free_host_driver; return 0; -err_close_sysfs_driver: - sysfs_close_driver(host_driver->sysfs_driver); -err_destroy_edev_list: - dlist_destroy(host_driver->edev_list); err_free_host_driver: free(host_driver); host_driver = NULL; + udev_unref(udev_context); + return -1; } @@ -300,30 +193,22 @@ void usbip_host_driver_close(void) if (!host_driver) return; - if (host_driver->edev_list) - dlist_destroy(host_driver->edev_list); - if (host_driver->sysfs_driver) - sysfs_close_driver(host_driver->sysfs_driver); + usbip_exported_device_destroy(); free(host_driver); host_driver = NULL; + + udev_unref(udev_context); } int usbip_host_refresh_device_list(void) { int rc; - if (host_driver->edev_list) - dlist_destroy(host_driver->edev_list); + usbip_exported_device_destroy(); host_driver->ndevs = 0; - host_driver->edev_list = - dlist_new_with_delete(sizeof(struct usbip_exported_device), - usbip_exported_device_delete); - if (!host_driver->edev_list) { - dbg("dlist_new_with_delete failed"); - return -1; - } + INIT_LIST_HEAD(&host_driver->edev_list); rc = refresh_exported_devices(); if (rc < 0) @@ -335,8 +220,7 @@ int usbip_host_refresh_device_list(void) int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd) { char attr_name[] = "usbip_sockfd"; - char attr_path[SYSFS_PATH_MAX]; - struct sysfs_attribute *attr; + char sockfd_attr_path[SYSFS_PATH_MAX]; char sockfd_buff[30]; int ret; @@ -356,41 +240,32 @@ int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd) } /* only the first interface is true */ - snprintf(attr_path, sizeof(attr_path), "%s/%s:%d.%d/%s", - edev->udev.path, edev->udev.busid, - edev->udev.bConfigurationValue, 0, attr_name); - - attr = sysfs_open_attribute(attr_path); - if (!attr) { - dbg("sysfs_open_attribute failed: %s", attr_path); - return -1; - } + snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s", + edev->udev.path, attr_name); snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd); - dbg("write: %s", sockfd_buff); - ret = sysfs_write_attribute(attr, sockfd_buff, strlen(sockfd_buff)); + ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff, + strlen(sockfd_buff)); if (ret < 0) { - dbg("sysfs_write_attribute failed: sockfd %s to %s", - sockfd_buff, attr_path); - goto err_write_sockfd; + err("write_sysfs_attribute failed: sockfd %s to %s", + sockfd_buff, sockfd_attr_path); + return ret; } - dbg("connect: %s", edev->udev.busid); - -err_write_sockfd: - sysfs_close_attribute(attr); + info("connect: %s", edev->udev.busid); return ret; } struct usbip_exported_device *usbip_host_get_device(int num) { + struct list_head *i; struct usbip_exported_device *edev; - struct dlist *dlist = host_driver->edev_list; int cnt = 0; - dlist_for_each_data(dlist, edev, struct usbip_exported_device) { + list_for_each(i, &host_driver->edev_list) { + edev = list_entry(i, struct usbip_exported_device, node); if (num == cnt) return edev; else diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h index 34fd14c..2a31f85 100644 --- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h +++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h @@ -21,18 +21,19 @@ #include <stdint.h> #include "usbip_common.h" +#include "list.h" struct usbip_host_driver { int ndevs; - struct sysfs_driver *sysfs_driver; /* list of exported device */ - struct dlist *edev_list; + struct list_head edev_list; }; struct usbip_exported_device { - struct sysfs_device *sudev; + struct udev_device *sudev; int32_t status; struct usbip_usb_device udev; + struct list_head node; struct usbip_usb_interface uinf[]; }; diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c index 209df9b..8901fcb 100644 --- a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c +++ b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c @@ -6,44 +6,28 @@ #include "vhci_driver.h" #include <limits.h> #include <netdb.h> +#include <libudev.h> +#include "sysfs_utils.h" #undef PROGNAME #define PROGNAME "libusbip" struct usbip_vhci_driver *vhci_driver; +struct udev *udev_context; static struct usbip_imported_device * imported_device_init(struct usbip_imported_device *idev, char *busid) { - struct sysfs_device *sudev; + struct udev_device *sudev; - sudev = sysfs_open_device("usb", busid); + sudev = udev_device_new_from_subsystem_sysname(udev_context, + "usb", busid); if (!sudev) { - dbg("sysfs_open_device failed: %s", busid); + dbg("udev_device_new_from_subsystem_sysname failed: %s", busid); goto err; } read_usb_device(sudev, &idev->udev); - sysfs_close_device(sudev); - - /* add class devices of this imported device */ - struct usbip_class_device *cdev; - dlist_for_each_data(vhci_driver->cdev_list, cdev, - struct usbip_class_device) { - if (!strncmp(cdev->dev_path, idev->udev.path, - strlen(idev->udev.path))) { - struct usbip_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); - } - } + udev_device_unref(sudev); return idev; @@ -53,7 +37,7 @@ err: -static int parse_status(char *value) +static int parse_status(const char *value) { int ret = 0; char *c; @@ -100,12 +84,6 @@ static int parse_status(char *value) idev->busnum = (devid >> 16); idev->devnum = (devid & 0x0000ffff); - idev->cdev_list = dlist_new(sizeof(struct usbip_class_device)); - if (!idev->cdev_list) { - dbg("dlist_new failed"); - return -1; - } - if (idev->status != VDEV_ST_NULL && idev->status != VDEV_ST_NOTASSIGNED) { idev = imported_device_init(idev, lbusid); @@ -129,156 +107,35 @@ static int parse_status(char *value) return 0; } - -static int check_usbip_device(struct sysfs_class_device *cdev) -{ - /* /sys/class/video4linux/video0/device */ - char class_path[SYSFS_PATH_MAX]; - /* /sys/devices/platform/vhci_hcd/usb6/6-1:1.1 */ - char dev_path[SYSFS_PATH_MAX]; - int ret; - struct usbip_class_device *usbip_cdev; - - snprintf(class_path, sizeof(class_path), "%s/device", cdev->path); - - ret = sysfs_get_link(class_path, dev_path, sizeof(dev_path)); - if (ret == 0) { - if (!strncmp(dev_path, vhci_driver->hc_device->path, - strlen(vhci_driver->hc_device->path))) { - /* found usbip device */ - usbip_cdev = calloc(1, sizeof(*usbip_cdev)); - if (!usbip_cdev) { - dbg("calloc failed"); - return -1; - } - dlist_unshift(vhci_driver->cdev_list, usbip_cdev); - strncpy(usbip_cdev->class_path, class_path, - sizeof(usbip_cdev->class_path)); - strncpy(usbip_cdev->dev_path, dev_path, - sizeof(usbip_cdev->dev_path)); - dbg("found: %s %s", class_path, dev_path); - } - } - - return 0; -} - - -static int search_class_for_usbip_device(char *cname) -{ - struct sysfs_class *class; - struct dlist *cdev_list; - struct sysfs_class_device *cdev; - int ret = 0; - - class = sysfs_open_class(cname); - if (!class) { - dbg("sysfs_open_class failed"); - return -1; - } - - dbg("class: %s", class->name); - - cdev_list = sysfs_get_class_devices(class); - if (!cdev_list) - /* nothing */ - goto out; - - dlist_for_each_data(cdev_list, cdev, struct sysfs_class_device) { - dbg("cdev: %s", cdev->name); - ret = check_usbip_device(cdev); - if (ret < 0) - goto out; - } - -out: - sysfs_close_class(class); - - return ret; -} - - -static int refresh_class_device_list(void) -{ - int ret; - struct dlist *cname_list; - char *cname; - char sysfs_mntpath[SYSFS_PATH_MAX]; - char class_path[SYSFS_PATH_MAX]; - - ret = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); - if (ret < 0) { - dbg("sysfs_get_mnt_path failed"); - return -1; - } - - snprintf(class_path, sizeof(class_path), "%s/%s", sysfs_mntpath, - SYSFS_CLASS_NAME); - - /* search under /sys/class */ - cname_list = sysfs_open_directory_list(class_path); - if (!cname_list) { - dbg("sysfs_open_directory failed"); - return -1; - } - - dlist_for_each_data(cname_list, cname, char) { - ret = search_class_for_usbip_device(cname); - if (ret < 0) { - sysfs_close_list(cname_list); - return -1; - } - } - - sysfs_close_list(cname_list); - - /* search under /sys/block */ - ret = search_class_for_usbip_device(SYSFS_BLOCK_NAME); - if (ret < 0) - return -1; - - return 0; -} - - static int refresh_imported_device_list(void) { - struct sysfs_attribute *attr_status; - + const char *attr_status; - attr_status = sysfs_get_device_attr(vhci_driver->hc_device, "status"); + attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device, + "status"); if (!attr_status) { - dbg("sysfs_get_device_attr(\"status\") failed: %s", - vhci_driver->hc_device->name); + err("udev_device_get_sysattr_value failed"); return -1; } - dbg("name: %s path: %s len: %d method: %d value: %s", - attr_status->name, attr_status->path, attr_status->len, - attr_status->method, attr_status->value); - - return parse_status(attr_status->value); + return parse_status(attr_status); } static int get_nports(void) { char *c; int nports = 0; - struct sysfs_attribute *attr_status; + const char *attr_status; - attr_status = sysfs_get_device_attr(vhci_driver->hc_device, "status"); + attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device, + "status"); if (!attr_status) { - dbg("sysfs_get_device_attr(\"status\") failed: %s", - vhci_driver->hc_device->name); + err("udev_device_get_sysattr_value failed"); return -1; } - dbg("name: %s path: %s len: %d method: %d value: %s", - attr_status->name, attr_status->path, attr_status->len, - attr_status->method, attr_status->value); - /* skip a header line */ - c = strchr(attr_status->value, '\n'); + c = strchr(attr_status, '\n'); if (!c) return 0; c++; @@ -295,71 +152,66 @@ static int get_nports(void) return nports; } -static int get_hc_busid(char *sysfs_mntpath, char *hc_busid) -{ - struct sysfs_driver *sdriver; - char sdriver_path[SYSFS_PATH_MAX]; - - struct sysfs_device *hc_dev; - struct dlist *hc_devs; - - int found = 0; - - snprintf(sdriver_path, SYSFS_PATH_MAX, "%s/%s/%s/%s/%s", sysfs_mntpath, - SYSFS_BUS_NAME, USBIP_VHCI_BUS_TYPE, SYSFS_DRIVERS_NAME, - USBIP_VHCI_DRV_NAME); - - sdriver = sysfs_open_driver_path(sdriver_path); - if (!sdriver) { - dbg("sysfs_open_driver_path failed: %s", sdriver_path); - dbg("make sure " USBIP_CORE_MOD_NAME ".ko and " - USBIP_VHCI_DRV_NAME ".ko are loaded!"); - return -1; - } - - hc_devs = sysfs_get_driver_devices(sdriver); - if (!hc_devs) { - dbg("sysfs_get_driver failed"); - goto err; - } - - /* assume only one vhci_hcd */ - dlist_for_each_data(hc_devs, hc_dev, struct sysfs_device) { - strncpy(hc_busid, hc_dev->bus_id, SYSFS_BUS_ID_SIZE); - found = 1; - } - -err: - sysfs_close_driver(sdriver); - - if (found) - return 0; - - dbg("%s not found", hc_busid); - return -1; -} - -static int read_record(int rhport, char *host, char *port, char *busid) +/* + * Read the given port's record. + * + * To avoid buffer overflow we will read the entire line and + * validate each part's size. The initial buffer is padded by 4 to + * accommodate the 2 spaces, 1 newline and an additional character + * which is needed to properly validate the 3rd part without it being + * truncated to an acceptable length. + */ +static int read_record(int rhport, char *host, unsigned long host_len, + char *port, unsigned long port_len, char *busid) { + int part; FILE *file; char path[PATH_MAX+1]; + char *buffer, *start, *end; + char delim[] = {' ', ' ', '\n'}; + int max_len[] = {(int)host_len, (int)port_len, SYSFS_BUS_ID_SIZE}; + size_t buffer_len = host_len + port_len + SYSFS_BUS_ID_SIZE + 4; + + buffer = malloc(buffer_len); + if (!buffer) + return -1; snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport); file = fopen(path, "r"); if (!file) { err("fopen"); + free(buffer); return -1; } - if (fscanf(file, "%s %s %s\n", host, port, busid) != 3) { - err("fscanf"); + if (fgets(buffer, buffer_len, file) == NULL) { + err("fgets"); + free(buffer); fclose(file); return -1; } - fclose(file); + /* validate the length of each of the 3 parts */ + start = buffer; + for (part = 0; part < 3; part++) { + end = strchr(start, delim[part]); + if (end == NULL || (end - start) > max_len[part]) { + free(buffer); + return -1; + } + start = end + 1; + } + + if (sscanf(buffer, "%s %s %s\n", host, port, busid) != 3) { + err("sscanf"); + free(buffer); + return -1; + } + + free(buffer); + return 0; } @@ -367,30 +219,21 @@ static int read_record(int rhport, char *host, char *port, char *busid) int usbip_vhci_driver_open(void) { - int ret; - char hc_busid[SYSFS_BUS_ID_SIZE]; - - vhci_driver = (struct usbip_vhci_driver *) calloc(1, sizeof(*vhci_driver)); - if (!vhci_driver) { - dbg("calloc failed"); + udev_context = udev_new(); + if (!udev_context) { + err("udev_new failed"); return -1; } - ret = sysfs_get_mnt_path(vhci_driver->sysfs_mntpath, SYSFS_PATH_MAX); - if (ret < 0) { - dbg("sysfs_get_mnt_path failed"); - goto err; - } - - ret = get_hc_busid(vhci_driver->sysfs_mntpath, hc_busid); - if (ret < 0) - goto err; + vhci_driver = calloc(1, sizeof(struct usbip_vhci_driver)); /* will be freed in usbip_driver_close() */ - vhci_driver->hc_device = sysfs_open_device(USBIP_VHCI_BUS_TYPE, - hc_busid); + vhci_driver->hc_device = + udev_device_new_from_subsystem_sysname(udev_context, + USBIP_VHCI_BUS_TYPE, + USBIP_VHCI_DRV_NAME); if (!vhci_driver->hc_device) { - dbg("sysfs_open_device failed"); + err("udev_device_new_from_subsystem_sysname failed"); goto err; } @@ -398,29 +241,21 @@ int usbip_vhci_driver_open(void) dbg("available ports: %d", vhci_driver->nports); - vhci_driver->cdev_list = dlist_new(sizeof(struct usbip_class_device)); - if (!vhci_driver->cdev_list) - goto err; - - if (refresh_class_device_list()) - goto err; - if (refresh_imported_device_list()) goto err; - return 0; - err: - if (vhci_driver->cdev_list) - dlist_destroy(vhci_driver->cdev_list); - if (vhci_driver->hc_device) - sysfs_close_device(vhci_driver->hc_device); + udev_device_unref(vhci_driver->hc_device); + if (vhci_driver) free(vhci_driver); vhci_driver = NULL; + + udev_unref(udev_context); + return -1; } @@ -430,53 +265,24 @@ void usbip_vhci_driver_close() if (!vhci_driver) return; - if (vhci_driver->cdev_list) - dlist_destroy(vhci_driver->cdev_list); - - for (int i = 0; i < vhci_driver->nports; i++) { - if (vhci_driver->idev[i].cdev_list) - dlist_destroy(vhci_driver->idev[i].cdev_list); - } + udev_device_unref(vhci_driver->hc_device); - if (vhci_driver->hc_device) - sysfs_close_device(vhci_driver->hc_device); free(vhci_driver); vhci_driver = NULL; + + udev_unref(udev_context); } int usbip_vhci_refresh_device_list(void) { - if (vhci_driver->cdev_list) - dlist_destroy(vhci_driver->cdev_list); - - - for (int i = 0; i < vhci_driver->nports; i++) { - if (vhci_driver->idev[i].cdev_list) - dlist_destroy(vhci_driver->idev[i].cdev_list); - } - - vhci_driver->cdev_list = dlist_new(sizeof(struct usbip_class_device)); - if (!vhci_driver->cdev_list) - goto err; - - if (refresh_class_device_list()) - goto err; if (refresh_imported_device_list()) goto err; return 0; err: - if (vhci_driver->cdev_list) - dlist_destroy(vhci_driver->cdev_list); - - for (int i = 0; i < vhci_driver->nports; i++) { - if (vhci_driver->idev[i].cdev_list) - dlist_destroy(vhci_driver->idev[i].cdev_list); - } - dbg("failed to refresh device list"); return -1; } @@ -494,24 +300,24 @@ int usbip_vhci_get_free_port(void) int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid, uint32_t speed) { - struct sysfs_attribute *attr_attach; char buff[200]; /* what size should be ? */ + char attach_attr_path[SYSFS_PATH_MAX]; + char attr_attach[] = "attach"; + const char *path; int ret; - attr_attach = sysfs_get_device_attr(vhci_driver->hc_device, "attach"); - if (!attr_attach) { - dbg("sysfs_get_device_attr(\"attach\") failed: %s", - vhci_driver->hc_device->name); - return -1; - } - - snprintf(buff, sizeof(buff), "%u %u %u %u", + snprintf(buff, sizeof(buff), "%u %d %u %u", port, sockfd, devid, speed); dbg("writing: %s", buff); - ret = sysfs_write_attribute(attr_attach, buff, strlen(buff)); + path = udev_device_get_syspath(vhci_driver->hc_device); + snprintf(attach_attr_path, sizeof(attach_attr_path), "%s/%s", + path, attr_attach); + dbg("attach attribute path: %s", attach_attr_path); + + ret = write_sysfs_attribute(attach_attr_path, buff, strlen(buff)); if (ret < 0) { - dbg("sysfs_write_attribute failed"); + dbg("write_sysfs_attribute failed"); return -1; } @@ -536,23 +342,23 @@ int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum, int usbip_vhci_detach_device(uint8_t port) { - struct sysfs_attribute *attr_detach; + char detach_attr_path[SYSFS_PATH_MAX]; + char attr_detach[] = "detach"; char buff[200]; /* what size should be ? */ + const char *path; int ret; - attr_detach = sysfs_get_device_attr(vhci_driver->hc_device, "detach"); - if (!attr_detach) { - dbg("sysfs_get_device_attr(\"detach\") failed: %s", - vhci_driver->hc_device->name); - return -1; - } - snprintf(buff, sizeof(buff), "%u", port); dbg("writing: %s", buff); - ret = sysfs_write_attribute(attr_detach, buff, strlen(buff)); + path = udev_device_get_syspath(vhci_driver->hc_device); + snprintf(detach_attr_path, sizeof(detach_attr_path), "%s/%s", + path, attr_detach); + dbg("detach attribute path: %s", detach_attr_path); + + ret = write_sysfs_attribute(detach_attr_path, buff, strlen(buff)); if (ret < 0) { - dbg("sysfs_write_attribute failed"); + dbg("write_sysfs_attribute failed"); return -1; } @@ -573,7 +379,8 @@ int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev) if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED) return 0; - ret = read_record(idev->port, host, serv, remote_busid); + ret = read_record(idev->port, host, sizeof(host), serv, sizeof(serv), + remote_busid); if (ret) { err("read_record"); read_record_error = 1; diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.h b/drivers/staging/usbip/userspace/libsrc/vhci_driver.h index e071f80..fa2316c 100644 --- a/drivers/staging/usbip/userspace/libsrc/vhci_driver.h +++ b/drivers/staging/usbip/userspace/libsrc/vhci_driver.h @@ -5,7 +5,7 @@ #ifndef __VHCI_DRIVER_H #define __VHCI_DRIVER_H -#include <sysfs/libsysfs.h> +#include <libudev.h> #include <stdint.h> #include "usbip_common.h" @@ -13,11 +13,6 @@ #define USBIP_VHCI_BUS_TYPE "platform" #define MAXNPORT 128 -struct usbip_class_device { - char class_path[SYSFS_PATH_MAX]; - char dev_path[SYSFS_PATH_MAX]; -}; - struct usbip_imported_device { uint8_t port; uint32_t status; @@ -28,18 +23,13 @@ struct usbip_imported_device { uint8_t devnum; /* usbip_class_device list */ - struct dlist *cdev_list; struct usbip_usb_device udev; }; struct usbip_vhci_driver { - char sysfs_mntpath[SYSFS_PATH_MAX]; /* /sys/devices/platform/vhci_hcd */ - struct sysfs_device *hc_device; - - /* usbip_class_device list */ - struct dlist *cdev_list; + struct udev_device *hc_device; int nports; struct usbip_imported_device idev[MAXNPORT]; diff --git a/drivers/staging/usbip/userspace/src/Makefile.am b/drivers/staging/usbip/userspace/src/Makefile.am index b4f8c4b0..e81a4eb 100644 --- a/drivers/staging/usbip/userspace/src/Makefile.am +++ b/drivers/staging/usbip/userspace/src/Makefile.am @@ -8,5 +8,4 @@ usbip_SOURCES := usbip.h utils.h usbip.c utils.c usbip_network.c \ usbip_attach.c usbip_detach.c usbip_list.c \ usbip_bind.c usbip_unbind.c usbip_port.c - usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c diff --git a/drivers/staging/usbip/userspace/src/usbip_attach.c b/drivers/staging/usbip/userspace/src/usbip_attach.c index 0858411..716a79e 100644 --- a/drivers/staging/usbip/userspace/src/usbip_attach.c +++ b/drivers/staging/usbip/userspace/src/usbip_attach.c @@ -17,7 +17,6 @@ */ #include <sys/stat.h> -#include <sysfs/libsysfs.h> #include <limits.h> #include <stdint.h> diff --git a/drivers/staging/usbip/userspace/src/usbip_bind.c b/drivers/staging/usbip/userspace/src/usbip_bind.c index 9ecaf6e..fa46141 100644 --- a/drivers/staging/usbip/userspace/src/usbip_bind.c +++ b/drivers/staging/usbip/userspace/src/usbip_bind.c @@ -16,7 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <sysfs/libsysfs.h> +#include <libudev.h> #include <errno.h> #include <stdio.h> @@ -28,6 +28,7 @@ #include "usbip_common.h" #include "utils.h" #include "usbip.h" +#include "sysfs_utils.h" enum unbind_status { UNBIND_ST_OK, @@ -48,167 +49,92 @@ void usbip_bind_usage(void) /* call at unbound state */ static int bind_usbip(char *busid) { - char bus_type[] = "usb"; char attr_name[] = "bind"; - char sysfs_mntpath[SYSFS_PATH_MAX]; char bind_attr_path[SYSFS_PATH_MAX]; - char intf_busid[SYSFS_BUS_ID_SIZE]; - struct sysfs_device *busid_dev; - struct sysfs_attribute *bind_attr; - struct sysfs_attribute *bConfValue; - struct sysfs_attribute *bNumIntfs; - int i, failed = 0; - int rc, ret = -1; - - rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); - if (rc < 0) { - err("sysfs must be mounted: %s", strerror(errno)); - return -1; - } + int rc = -1; snprintf(bind_attr_path, sizeof(bind_attr_path), "%s/%s/%s/%s/%s/%s", - sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME, - USBIP_HOST_DRV_NAME, attr_name); - - bind_attr = sysfs_open_attribute(bind_attr_path); - if (!bind_attr) { - dbg("problem getting bind attribute: %s", strerror(errno)); - return -1; - } + SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE, + SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, attr_name); - busid_dev = sysfs_open_device(bus_type, busid); - if (!busid_dev) { - dbg("sysfs_open_device %s failed: %s", busid, strerror(errno)); - goto err_close_bind_attr; - } - - bConfValue = sysfs_get_device_attr(busid_dev, "bConfigurationValue"); - bNumIntfs = sysfs_get_device_attr(busid_dev, "bNumInterfaces"); - - if (!bConfValue || !bNumIntfs) { - dbg("problem getting device attributes: %s", + rc = write_sysfs_attribute(bind_attr_path, busid, strlen(busid)); + if (rc < 0) { + err("error binding device %s to driver: %s", busid, strerror(errno)); - 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); - - rc = sysfs_write_attribute(bind_attr, intf_busid, - SYSFS_BUS_ID_SIZE); - if (rc < 0) { - dbg("bind driver at %s failed", intf_busid); - failed = 1; - } + return -1; } - if (!failed) - ret = 0; - -err_close_busid_dev: - sysfs_close_device(busid_dev); -err_close_bind_attr: - sysfs_close_attribute(bind_attr); - - return ret; + return 0; } /* 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; + char attr_name[] = "unbind"; + char unbind_attr_path[SYSFS_PATH_MAX]; + int rc = -1; + + struct udev *udev; + struct udev_device *dev; + const char *driver; + const char *bDevClass; + + /* Create libudev context. */ + udev = udev_new(); + + /* Get the device. */ + dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid); + if (!dev) { + dbg("unable to find device with bus ID %s", busid); + goto err_close_busid_dev; } - 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)); + /* Check what kind of device it is. */ + bDevClass = udev_device_get_sysattr_value(dev, "bDeviceClass"); + if (!bDevClass) { + dbg("unable to get bDevClass device attribute"); goto err_close_busid_dev; } - if (!strncmp(bDevClass->value, "09", bDevClass->len)) { + if (!strncmp(bDevClass, "09", strlen(bDevClass))) { 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; - } + /* Get the device driver. */ + driver = udev_device_get_driver(dev); + if (!driver) { + /* No driver bound to this device. */ + goto out; + } - 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; - } + if (!strncmp(USBIP_HOST_DRV_NAME, driver, + strlen(USBIP_HOST_DRV_NAME))) { + /* Already bound to usbip-host. */ + status = UNBIND_ST_USBIP_HOST; + goto out; + } - 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; - } + /* Unbind device from driver. */ + snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s", + SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE, + SYSFS_DRIVERS_NAME, driver, attr_name); - sysfs_close_driver(intf_drv); - sysfs_close_device(intf_dev); + rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid)); + if (rc < 0) { + err("error unbinding device %s from driver", busid); + goto err_close_busid_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); + udev_device_unref(dev); + udev_unref(udev); return status; } @@ -216,6 +142,17 @@ out: static int bind_device(char *busid) { int rc; + struct udev *udev; + struct udev_device *dev; + + /* Check whether the device with this bus ID exists. */ + udev = udev_new(); + dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid); + if (!dev) { + err("device with the specified bus ID does not exist"); + return -1; + } + udev_unref(udev); rc = unbind_other(busid); if (rc == UNBIND_ST_FAILED) { @@ -240,7 +177,7 @@ static int bind_device(char *busid) return -1; } - printf("bind device on busid %s: complete\n", busid); + info("bind device on busid %s: complete", busid); return 0; } diff --git a/drivers/staging/usbip/userspace/src/usbip_detach.c b/drivers/staging/usbip/userspace/src/usbip_detach.c index 13308df..05c6d15 100644 --- a/drivers/staging/usbip/userspace/src/usbip_detach.c +++ b/drivers/staging/usbip/userspace/src/usbip_detach.c @@ -16,8 +16,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <sysfs/libsysfs.h> - #include <ctype.h> #include <limits.h> #include <stdint.h> diff --git a/drivers/staging/usbip/userspace/src/usbip_list.c b/drivers/staging/usbip/userspace/src/usbip_list.c index 237e099..d5ce34a 100644 --- a/drivers/staging/usbip/userspace/src/usbip_list.c +++ b/drivers/staging/usbip/userspace/src/usbip_list.c @@ -17,7 +17,7 @@ */ #include <sys/types.h> -#include <sysfs/libsysfs.h> +#include <libudev.h> #include <errno.h> #include <stdbool.h> @@ -54,7 +54,7 @@ static int get_exported_devices(char *host, int sockfd) struct usbip_usb_device udev; struct usbip_usb_interface uintf; unsigned int i; - int j, rc; + int rc, j; rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0); if (rc < 0) { @@ -107,19 +107,20 @@ static int get_exported_devices(char *host, int sockfd) for (j = 0; j < udev.bNumInterfaces; j++) { rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf)); if (rc < 0) { - dbg("usbip_net_recv failed: usbip_usb_intf[%d]", - j); + err("usbip_net_recv failed: usbip_usb_intf[%d]", + j); return -1; } usbip_net_pack_usb_interface(0, &uintf); usbip_names_get_class(class_name, sizeof(class_name), - uintf.bInterfaceClass, - uintf.bInterfaceSubClass, - uintf.bInterfaceProtocol); + uintf.bInterfaceClass, + uintf.bInterfaceSubClass, + uintf.bInterfaceProtocol); printf("%11s: %2d - %s\n", "", j, class_name); } + printf("\n"); } @@ -150,8 +151,8 @@ static int list_exported_devices(char *host) return 0; } -static void print_device(char *busid, char *vendor, char *product, - bool parsable) +static void print_device(const char *busid, const char *vendor, + const char *product, bool parsable) { if (parsable) printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product); @@ -165,106 +166,73 @@ static void print_product_name(char *product_name, bool parsable) printf(" %s\n", product_name); } -static void print_interface(char *busid, char *driver, bool parsable) -{ - if (parsable) - printf("%s=%s#", busid, driver); - else - printf("%9s%s -> %s\n", "", busid, driver); -} - -static int is_device(void *x) -{ - struct sysfs_attribute *devpath; - struct sysfs_device *dev = x; - int ret = 0; - - devpath = sysfs_get_device_attr(dev, "devpath"); - if (devpath && *devpath->value != '0') - ret = 1; - - return ret; -} - -static int devcmp(void *a, void *b) -{ - return strcmp(a, b); -} - static int list_devices(bool parsable) { - char bus_type[] = "usb"; - char busid[SYSFS_BUS_ID_SIZE]; + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *dev; + const char *path; + const char *idVendor; + const char *idProduct; + const char *bConfValue; + const char *bNumIntfs; + const char *busid; char product_name[128]; - struct sysfs_bus *ubus; - struct sysfs_device *dev; - struct sysfs_device *intf; - struct sysfs_attribute *idVendor; - struct sysfs_attribute *idProduct; - struct sysfs_attribute *bConfValue; - struct sysfs_attribute *bNumIntfs; - struct dlist *devlist; - int i; int ret = -1; - ubus = sysfs_open_bus(bus_type); - if (!ubus) { - err("could not open %s bus: %s", bus_type, strerror(errno)); - return -1; - } - - devlist = sysfs_get_bus_devices(ubus); - if (!devlist) { - err("could not get %s bus devices: %s", bus_type, - strerror(errno)); - goto err_out; - } - - /* remove interfaces and root hubs from device list */ - dlist_filter_sort(devlist, is_device, devcmp); - - if (!parsable) { - printf("Local USB devices\n"); - printf("=================\n"); - } - dlist_for_each_data(devlist, dev, struct sysfs_device) { - idVendor = sysfs_get_device_attr(dev, "idVendor"); - idProduct = sysfs_get_device_attr(dev, "idProduct"); - bConfValue = sysfs_get_device_attr(dev, "bConfigurationValue"); - bNumIntfs = sysfs_get_device_attr(dev, "bNumInterfaces"); + /* Create libudev context. */ + udev = udev_new(); + + /* Create libudev device enumeration. */ + enumerate = udev_enumerate_new(udev); + + /* Take only USB devices that are not hubs and do not have + * the bInterfaceNumber attribute, i.e. are not interfaces. + */ + udev_enumerate_add_match_subsystem(enumerate, "usb"); + udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09"); + udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL); + udev_enumerate_scan_devices(enumerate); + + devices = udev_enumerate_get_list_entry(enumerate); + + /* Show information about each device. */ + udev_list_entry_foreach(dev_list_entry, devices) { + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(udev, path); + + /* Get device information. */ + idVendor = udev_device_get_sysattr_value(dev, "idVendor"); + idProduct = udev_device_get_sysattr_value(dev, "idProduct"); + bConfValue = udev_device_get_sysattr_value(dev, "bConfigurationValue"); + bNumIntfs = udev_device_get_sysattr_value(dev, "bNumInterfaces"); + busid = udev_device_get_sysname(dev); if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) { err("problem getting device attributes: %s", strerror(errno)); goto err_out; } - /* get product name */ + /* Get product name. */ usbip_names_get_product(product_name, sizeof(product_name), - strtol(idVendor->value, NULL, 16), - strtol(idProduct->value, NULL, 16)); - print_device(dev->bus_id, idVendor->value, idProduct->value, - parsable); + strtol(idVendor, NULL, 16), + strtol(idProduct, NULL, 16)); + + /* Print information. */ + print_device(busid, idVendor, idProduct, parsable); print_product_name(product_name, parsable); - for (i = 0; i < atoi(bNumIntfs->value); i++) { - snprintf(busid, sizeof(busid), "%s:%.1s.%d", - dev->bus_id, bConfValue->value, i); - intf = sysfs_open_device(bus_type, busid); - if (!intf) { - err("could not open device interface: %s", - strerror(errno)); - goto err_out; - } - print_interface(busid, intf->driver_name, parsable); - sysfs_close_device(intf); - } printf("\n"); + + udev_device_unref(dev); } ret = 0; err_out: - sysfs_close_bus(ubus); + udev_enumerate_unref(enumerate); + udev_unref(udev); return ret; } diff --git a/drivers/staging/usbip/userspace/src/usbip_network.h b/drivers/staging/usbip/userspace/src/usbip_network.h index f19ae19..c1e875c 100644 --- a/drivers/staging/usbip/userspace/src/usbip_network.h +++ b/drivers/staging/usbip/userspace/src/usbip_network.h @@ -10,7 +10,6 @@ #endif #include <sys/types.h> -#include <sysfs/libsysfs.h> #include <stdint.h> diff --git a/drivers/staging/usbip/userspace/src/usbip_unbind.c b/drivers/staging/usbip/userspace/src/usbip_unbind.c index d5a9ab6..a4a496c 100644 --- a/drivers/staging/usbip/userspace/src/usbip_unbind.c +++ b/drivers/staging/usbip/userspace/src/usbip_unbind.c @@ -16,7 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <sysfs/libsysfs.h> +#include <libudev.h> #include <errno.h> #include <stdio.h> @@ -27,6 +27,7 @@ #include "usbip_common.h" #include "utils.h" #include "usbip.h" +#include "sysfs_utils.h" static const char usbip_unbind_usage_string[] = "usbip unbind <args>\n" @@ -41,115 +42,69 @@ void usbip_unbind_usage(void) static int unbind_device(char *busid) { char bus_type[] = "usb"; - struct sysfs_driver *usbip_host_drv; - struct sysfs_device *dev; - struct dlist *devlist; - int verified = 0; int rc, ret = -1; - char attr_name[] = "bConfigurationValue"; - char sysfs_mntpath[SYSFS_PATH_MAX]; - char busid_attr_path[SYSFS_PATH_MAX]; - struct sysfs_attribute *busid_attr; - char *val = NULL; - int len; - - /* verify the busid device is using usbip-host */ - usbip_host_drv = sysfs_open_driver(bus_type, USBIP_HOST_DRV_NAME); - if (!usbip_host_drv) { - err("could not open %s driver: %s", USBIP_HOST_DRV_NAME, - strerror(errno)); - return -1; - } + char unbind_attr_name[] = "unbind"; + char unbind_attr_path[SYSFS_PATH_MAX]; + char rebind_attr_name[] = "rebind"; + char rebind_attr_path[SYSFS_PATH_MAX]; - devlist = sysfs_get_driver_devices(usbip_host_drv); - if (!devlist) { - err("%s is not in use by any devices", USBIP_HOST_DRV_NAME); - goto err_close_usbip_host_drv; - } + struct udev *udev; + struct udev_device *dev; + const char *driver; - dlist_for_each_data(devlist, dev, struct sysfs_device) { - if (!strncmp(busid, dev->name, strlen(busid)) && - !strncmp(dev->driver_name, USBIP_HOST_DRV_NAME, - strlen(USBIP_HOST_DRV_NAME))) { - verified = 1; - break; - } - } + /* Create libudev context. */ + udev = udev_new(); - if (!verified) { - err("device on busid %s is not using %s", busid, - USBIP_HOST_DRV_NAME); - goto err_close_usbip_host_drv; + /* Check whether the device with this bus ID exists. */ + dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid); + if (!dev) { + err("device with the specified bus ID does not exist"); + goto err_close_udev; } - /* - * NOTE: A read and write of an attribute value of the device busid - * refers to must be done to start probing. That way a rebind of the - * default driver for the device occurs. - * - * This seems very hackish and adds a lot of pointless code. I think it - * should be done in the kernel by the driver after del_match_busid is - * finished! - */ - - rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); - if (rc < 0) { - err("sysfs must be mounted: %s", strerror(errno)); - return -1; + /* Check whether the device is using usbip-host driver. */ + driver = udev_device_get_driver(dev); + if (!driver || strcmp(driver, "usbip-host")) { + err("device is not bound to usbip-host driver"); + goto err_close_udev; } - snprintf(busid_attr_path, sizeof(busid_attr_path), "%s/%s/%s/%s/%s/%s", - sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DEVICES_NAME, - busid, attr_name); + /* Unbind device from driver. */ + snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s", + SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME, + USBIP_HOST_DRV_NAME, unbind_attr_name); - /* read a device attribute */ - busid_attr = sysfs_open_attribute(busid_attr_path); - if (!busid_attr) { - err("could not open %s/%s: %s", busid, attr_name, - strerror(errno)); - return -1; - } - - if (sysfs_read_attribute(busid_attr) < 0) { - err("problem reading attribute: %s", strerror(errno)); - goto err_out; + rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid)); + if (rc < 0) { + err("error unbinding device %s from driver", busid); + goto err_close_udev; } - len = busid_attr->len; - val = malloc(len); - *val = *busid_attr->value; - sysfs_close_attribute(busid_attr); - - /* notify driver of unbind */ + /* Notify driver of unbind. */ rc = modify_match_busid(busid, 0); if (rc < 0) { err("unable to unbind device on %s", busid); - goto err_out; + goto err_close_udev; } - /* write the device attribute */ - busid_attr = sysfs_open_attribute(busid_attr_path); - if (!busid_attr) { - err("could not open %s/%s: %s", busid, attr_name, - strerror(errno)); - return -1; - } + /* Trigger new probing. */ + snprintf(rebind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s", + SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME, + USBIP_HOST_DRV_NAME, rebind_attr_name); - rc = sysfs_write_attribute(busid_attr, val, len); + rc = write_sysfs_attribute(rebind_attr_path, busid, strlen(busid)); if (rc < 0) { - err("problem writing attribute: %s", strerror(errno)); - goto err_out; + err("error rebinding"); + goto err_close_udev; } - sysfs_close_attribute(busid_attr); ret = 0; - printf("unbind device on busid %s: complete\n", busid); + info("unbind device on busid %s: complete", busid); -err_out: - free(val); -err_close_usbip_host_drv: - sysfs_close_driver(usbip_host_drv); +err_close_udev: + udev_device_unref(dev); + udev_unref(udev); return ret; } diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c index 7980f8b..2cae4ce 100644 --- a/drivers/staging/usbip/userspace/src/usbipd.c +++ b/drivers/staging/usbip/userspace/src/usbipd.c @@ -43,6 +43,7 @@ #include "usbip_host_driver.h" #include "usbip_common.h" #include "usbip_network.h" +#include "list.h" #undef PROGNAME #define PROGNAME "usbipd" @@ -93,6 +94,7 @@ static int recv_request_import(int sockfd) struct op_common reply; struct usbip_exported_device *edev; struct usbip_usb_device pdu_udev; + struct list_head *i; int found = 0; int error = 0; int rc; @@ -107,8 +109,8 @@ static int recv_request_import(int sockfd) } PACK_OP_IMPORT_REQUEST(0, &req); - dlist_for_each_data(host_driver->edev_list, edev, - struct usbip_exported_device) { + list_for_each(i, &host_driver->edev_list) { + edev = list_entry(i, struct usbip_exported_device, node); if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { info("found requested device: %s", req.busid); found = 1; @@ -161,13 +163,12 @@ static int send_reply_devlist(int connfd) struct usbip_usb_device pdu_udev; struct usbip_usb_interface pdu_uinf; struct op_devlist_reply reply; - int i; - int rc; + struct list_head *j; + int rc, i; reply.ndev = 0; /* number of exported devices */ - dlist_for_each_data(host_driver->edev_list, edev, - struct usbip_exported_device) { + list_for_each(j, &host_driver->edev_list) { reply.ndev += 1; } info("exportable devices: %d", reply.ndev); @@ -185,8 +186,8 @@ static int send_reply_devlist(int connfd) return -1; } - dlist_for_each_data(host_driver->edev_list, edev, - struct usbip_exported_device) { + list_for_each(j, &host_driver->edev_list) { + edev = list_entry(j, struct usbip_exported_device, node); dump_usb_device(&edev->udev); memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); usbip_net_pack_usb_device(1, &pdu_udev); @@ -203,9 +204,9 @@ static int send_reply_devlist(int connfd) usbip_net_pack_usb_interface(1, &pdu_uinf); rc = usbip_net_send(connfd, &pdu_uinf, - sizeof(pdu_uinf)); + sizeof(pdu_uinf)); if (rc < 0) { - dbg("usbip_net_send failed: pdu_uinf"); + err("usbip_net_send failed: pdu_uinf"); return -1; } } diff --git a/drivers/staging/usbip/userspace/src/utils.c b/drivers/staging/usbip/userspace/src/utils.c index 2d4966e..2b3d6d2 100644 --- a/drivers/staging/usbip/userspace/src/utils.c +++ b/drivers/staging/usbip/userspace/src/utils.c @@ -16,61 +16,37 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <sysfs/libsysfs.h> - #include <errno.h> #include <stdio.h> #include <string.h> #include "usbip_common.h" #include "utils.h" +#include "sysfs_utils.h" int modify_match_busid(char *busid, int add) { - char bus_type[] = "usb"; char attr_name[] = "match_busid"; - char buff[SYSFS_BUS_ID_SIZE + 4]; - char sysfs_mntpath[SYSFS_PATH_MAX]; + char command[SYSFS_BUS_ID_SIZE + 4]; char match_busid_attr_path[SYSFS_PATH_MAX]; - struct sysfs_attribute *match_busid_attr; - int rc, ret = 0; - - if (strnlen(busid, SYSFS_BUS_ID_SIZE) > SYSFS_BUS_ID_SIZE - 1) { - dbg("busid is too long"); - return -1; - } - - rc = sysfs_get_mnt_path(sysfs_mntpath, SYSFS_PATH_MAX); - if (rc < 0) { - err("sysfs must be mounted: %s", strerror(errno)); - return -1; - } + int rc; snprintf(match_busid_attr_path, sizeof(match_busid_attr_path), - "%s/%s/%s/%s/%s/%s", sysfs_mntpath, SYSFS_BUS_NAME, bus_type, - SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, attr_name); - - match_busid_attr = sysfs_open_attribute(match_busid_attr_path); - if (!match_busid_attr) { - dbg("problem getting match_busid attribute: %s", - strerror(errno)); - return -1; - } + "%s/%s/%s/%s/%s/%s", SYSFS_MNT_PATH, SYSFS_BUS_NAME, + SYSFS_BUS_TYPE, SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, + attr_name); if (add) - snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "add %s", busid); + snprintf(command, SYSFS_BUS_ID_SIZE + 4, "add %s", busid); else - snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "del %s", busid); + snprintf(command, SYSFS_BUS_ID_SIZE + 4, "del %s", busid); - dbg("write \"%s\" to %s", buff, match_busid_attr->path); - - rc = sysfs_write_attribute(match_busid_attr, buff, sizeof(buff)); + rc = write_sysfs_attribute(match_busid_attr_path, command, + sizeof(command)); if (rc < 0) { dbg("failed to write match_busid: %s", strerror(errno)); - ret = -1; + return -1; } - sysfs_close_attribute(match_busid_attr); - - return ret; + return 0; } |