Commit 1e940319 authored by Valentina Manea's avatar Valentina Manea Committed by Greg Kroah-Hartman

staging: usbip: userspace: migrate usbip_bind to libudev

This patch adds autoconf check for libudev and migrates
usbip_bind to the new library.

libsysfs will still be used until all userspace is modified.
Signed-off-by: default avatarValentina Manea <valentina.manea.m@gmail.com>
Reviewed-by: default avatarShuah Khan <shuah.kh@samsung.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0669e5fa
...@@ -50,6 +50,12 @@ AC_CHECK_HEADER([sysfs/libsysfs.h], ...@@ -50,6 +50,12 @@ AC_CHECK_HEADER([sysfs/libsysfs.h],
[AC_MSG_ERROR([Missing sysfs2 library!])])], [AC_MSG_ERROR([Missing sysfs2 library!])])],
[AC_MSG_ERROR([Missing /usr/include/sysfs/libsysfs.h])]) [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. # Checks for libwrap library.
AC_MSG_CHECKING([whether to use the libwrap (TCP wrappers) library]) AC_MSG_CHECKING([whether to use the libwrap (TCP wrappers) library])
AC_ARG_WITH([tcp-wrappers], AC_ARG_WITH([tcp-wrappers],
......
...@@ -30,6 +30,15 @@ ...@@ -30,6 +30,15 @@
#define USBIP_HOST_DRV_NAME "usbip-host" #define USBIP_HOST_DRV_NAME "usbip-host"
#define USBIP_VHCI_DRV_NAME "vhci_hcd" #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_syslog;
extern int usbip_use_stderr; extern int usbip_use_stderr;
extern int usbip_use_debug ; extern int usbip_use_debug ;
......
...@@ -6,7 +6,8 @@ sbin_PROGRAMS := usbip usbipd ...@@ -6,7 +6,8 @@ sbin_PROGRAMS := usbip usbipd
usbip_SOURCES := usbip.h utils.h usbip.c utils.c usbip_network.c \ usbip_SOURCES := usbip.h utils.h usbip.c utils.c usbip_network.c \
usbip_attach.c usbip_detach.c usbip_list.c \ usbip_attach.c usbip_detach.c usbip_list.c \
usbip_bind.c usbip_unbind.c usbip_port.c usbip_bind.c usbip_unbind.c usbip_port.c \
sysfs_utils.c
usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c
#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;
}
#ifndef __SYSFS_UTILS_H
#define __SYSFS_UTILS_H
int write_sysfs_attribute(const char *attr_path, const char *new_value,
size_t len);
#endif
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <sysfs/libsysfs.h> #include <libudev.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "usbip_common.h" #include "usbip_common.h"
#include "utils.h" #include "utils.h"
#include "usbip.h" #include "usbip.h"
#include "sysfs_utils.h"
enum unbind_status { enum unbind_status {
UNBIND_ST_OK, UNBIND_ST_OK,
...@@ -48,135 +49,92 @@ void usbip_bind_usage(void) ...@@ -48,135 +49,92 @@ void usbip_bind_usage(void)
/* call at unbound state */ /* call at unbound state */
static int bind_usbip(char *busid) static int bind_usbip(char *busid)
{ {
char bus_type[] = "usb";
char attr_name[] = "bind"; char attr_name[] = "bind";
char sysfs_mntpath[SYSFS_PATH_MAX];
char bind_attr_path[SYSFS_PATH_MAX]; char bind_attr_path[SYSFS_PATH_MAX];
struct sysfs_attribute *bind_attr; int rc = -1;
int 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;
}
snprintf(bind_attr_path, sizeof(bind_attr_path), "%s/%s/%s/%s/%s/%s", snprintf(bind_attr_path, sizeof(bind_attr_path), "%s/%s/%s/%s/%s/%s",
sysfs_mntpath, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME, SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE,
USBIP_HOST_DRV_NAME, attr_name); SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, attr_name);
bind_attr = sysfs_open_attribute(bind_attr_path); rc = write_sysfs_attribute(bind_attr_path, busid, strlen(busid));
if (!bind_attr) {
dbg("problem getting bind attribute: %s", strerror(errno));
return -1;
}
rc = sysfs_write_attribute(bind_attr, busid, SYSFS_BUS_ID_SIZE);
if (rc < 0) { if (rc < 0) {
dbg("bind driver at %s failed", busid); err("error binding device %s to driver: %s", busid,
failed = 1; strerror(errno));
return -1;
} }
if (!failed) return 0;
ret = 0;
sysfs_close_attribute(bind_attr);
return ret;
} }
/* buggy driver may cause dead lock */ /* buggy driver may cause dead lock */
static int unbind_other(char *busid) static int unbind_other(char *busid)
{ {
char bus_type[] = "usb";
struct sysfs_device *busid_dev;
struct sysfs_device *dev;
struct sysfs_driver *drv;
struct sysfs_attribute *unbind_attr;
struct sysfs_attribute *bDevClass;
int rc;
enum unbind_status status = UNBIND_ST_OK; enum unbind_status status = UNBIND_ST_OK;
busid_dev = sysfs_open_device(bus_type, busid); char attr_name[] = "unbind";
if (!busid_dev) { char unbind_attr_path[SYSFS_PATH_MAX];
dbg("sysfs_open_device %s failed: %s", busid, strerror(errno)); int rc = -1;
return -1;
}
dbg("busid path: %s", busid_dev->path);
bDevClass = sysfs_get_device_attr(busid_dev, "bDeviceClass"); struct udev *udev;
if (!bDevClass) { struct udev_device *dev;
dbg("problem getting device attribute: %s", const char *driver;
strerror(errno)); 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; goto err_close_busid_dev;
} }
if (!strncmp(bDevClass->value, "09", bDevClass->len)) { /* Check what kind of device it is. */
dbg("skip unbinding of hub"); bDevClass = udev_device_get_sysattr_value(dev, "bDeviceClass");
if (!bDevClass) {
dbg("unable to get bDevClass device attribute");
goto err_close_busid_dev; goto err_close_busid_dev;
} }
dev = sysfs_open_device(bus_type, busid); if (!strncmp(bDevClass, "09", strlen(bDevClass))) {
if (!dev) { dbg("skip unbinding of hub");
dbg("could not open device: %s",
strerror(errno));
goto err_close_busid_dev; goto err_close_busid_dev;
} }
dbg("%s -> %s", dev->name, dev->driver_name); /* Get the device driver. */
driver = udev_device_get_driver(dev);
if (!strncmp("unknown", dev->driver_name, SYSFS_NAME_LEN)) { if (!driver) {
/* unbound interface */ /* No driver bound to this device. */
sysfs_close_device(dev);
goto out; goto out;
} }
if (!strncmp(USBIP_HOST_DRV_NAME, dev->driver_name, if (!strncmp(USBIP_HOST_DRV_NAME, driver,
SYSFS_NAME_LEN)) { strlen(USBIP_HOST_DRV_NAME))) {
/* already bound to usbip-host */ /* Already bound to usbip-host. */
status = UNBIND_ST_USBIP_HOST; status = UNBIND_ST_USBIP_HOST;
sysfs_close_device(dev);
goto out; goto out;
} }
/* unbinding */ /* Unbind device from driver. */
drv = sysfs_open_driver(bus_type, dev->driver_name); snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
if (!drv) { SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE,
dbg("could not open device driver on %s: %s", SYSFS_DRIVERS_NAME, driver, attr_name);
dev->name, strerror(errno));
goto err_close_intf_dev;
}
dbg("device driver: %s", drv->path);
unbind_attr = sysfs_get_driver_attr(drv, "unbind"); rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
if (!unbind_attr) {
dbg("problem getting device driver attribute: %s",
strerror(errno));
goto err_close_intf_drv;
}
rc = sysfs_write_attribute(unbind_attr, dev->bus_id,
SYSFS_BUS_ID_SIZE);
if (rc < 0) { if (rc < 0) {
/* NOTE: why keep unbinding other interfaces? */ err("error unbinding device %s from driver", busid);
dbg("unbind driver at %s failed", dev->bus_id); goto err_close_busid_dev;
status = UNBIND_ST_FAILED;
} }
sysfs_close_driver(drv);
sysfs_close_device(dev);
goto out; goto out;
err_close_intf_drv:
sysfs_close_driver(drv);
err_close_intf_dev:
sysfs_close_device(dev);
err_close_busid_dev: err_close_busid_dev:
status = UNBIND_ST_FAILED; status = UNBIND_ST_FAILED;
out: out:
sysfs_close_device(busid_dev); udev_device_unref(dev);
udev_unref(udev);
return status; return status;
} }
...@@ -184,6 +142,17 @@ static int unbind_other(char *busid) ...@@ -184,6 +142,17 @@ static int unbind_other(char *busid)
static int bind_device(char *busid) static int bind_device(char *busid)
{ {
int rc; 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); rc = unbind_other(busid);
if (rc == UNBIND_ST_FAILED) { if (rc == UNBIND_ST_FAILED) {
...@@ -208,7 +177,7 @@ static int bind_device(char *busid) ...@@ -208,7 +177,7 @@ static int bind_device(char *busid)
return -1; return -1;
} }
printf("bind device on busid %s: complete\n", busid); info("bind device on busid %s: complete", busid);
return 0; return 0;
} }
......
...@@ -16,61 +16,37 @@ ...@@ -16,61 +16,37 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <sysfs/libsysfs.h>
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "usbip_common.h" #include "usbip_common.h"
#include "utils.h" #include "utils.h"
#include "sysfs_utils.h"
int modify_match_busid(char *busid, int add) int modify_match_busid(char *busid, int add)
{ {
char bus_type[] = "usb";
char attr_name[] = "match_busid"; char attr_name[] = "match_busid";
char buff[SYSFS_BUS_ID_SIZE + 4]; char command[SYSFS_BUS_ID_SIZE + 4];
char sysfs_mntpath[SYSFS_PATH_MAX];
char match_busid_attr_path[SYSFS_PATH_MAX]; char match_busid_attr_path[SYSFS_PATH_MAX];
struct sysfs_attribute *match_busid_attr; int rc;
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;
}
snprintf(match_busid_attr_path, sizeof(match_busid_attr_path), snprintf(match_busid_attr_path, sizeof(match_busid_attr_path),
"%s/%s/%s/%s/%s/%s", sysfs_mntpath, SYSFS_BUS_NAME, bus_type, "%s/%s/%s/%s/%s/%s", SYSFS_MNT_PATH, SYSFS_BUS_NAME,
SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, attr_name); SYSFS_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;
}
if (add) if (add)
snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "add %s", busid); snprintf(command, SYSFS_BUS_ID_SIZE + 4, "add %s", busid);
else 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 = write_sysfs_attribute(match_busid_attr_path, command,
sizeof(command));
rc = sysfs_write_attribute(match_busid_attr, buff, sizeof(buff));
if (rc < 0) { if (rc < 0) {
dbg("failed to write match_busid: %s", strerror(errno)); dbg("failed to write match_busid: %s", strerror(errno));
ret = -1; return -1;
} }
sysfs_close_attribute(match_busid_attr); return 0;
return ret;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment