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: Valentina Manea <valentina.manea.m@gmail.com> Reviewed-by: Shuah Khan <shuah.kh@samsung.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
0669e5fa80
commit
1e94031973
|
@ -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 @@
|
||||||
#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
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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 @@
|
||||||
#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)
|
||||||
/* 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) {
|
if (rc < 0) {
|
||||||
dbg("problem getting bind attribute: %s", strerror(errno));
|
err("error binding device %s to driver: %s", busid,
|
||||||
|
strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sysfs_write_attribute(bind_attr, busid, SYSFS_BUS_ID_SIZE);
|
return 0;
|
||||||
if (rc < 0) {
|
|
||||||
dbg("bind driver at %s failed", busid);
|
|
||||||
failed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!failed)
|
|
||||||
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. */
|
||||||
|
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, "09", strlen(bDevClass))) {
|
||||||
dbg("skip unbinding of hub");
|
dbg("skip unbinding of hub");
|
||||||
goto err_close_busid_dev;
|
goto err_close_busid_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev = sysfs_open_device(bus_type, busid);
|
/* Get the device driver. */
|
||||||
if (!dev) {
|
driver = udev_device_get_driver(dev);
|
||||||
dbg("could not open device: %s",
|
if (!driver) {
|
||||||
strerror(errno));
|
/* No driver bound to this device. */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strncmp(USBIP_HOST_DRV_NAME, driver,
|
||||||
|
strlen(USBIP_HOST_DRV_NAME))) {
|
||||||
|
/* Already bound to usbip-host. */
|
||||||
|
status = UNBIND_ST_USBIP_HOST;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
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 err_close_busid_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg("%s -> %s", dev->name, dev->driver_name);
|
|
||||||
|
|
||||||
if (!strncmp("unknown", dev->driver_name, SYSFS_NAME_LEN)) {
|
|
||||||
/* unbound interface */
|
|
||||||
sysfs_close_device(dev);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strncmp(USBIP_HOST_DRV_NAME, dev->driver_name,
|
|
||||||
SYSFS_NAME_LEN)) {
|
|
||||||
/* already bound to usbip-host */
|
|
||||||
status = UNBIND_ST_USBIP_HOST;
|
|
||||||
sysfs_close_device(dev);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* unbinding */
|
|
||||||
drv = sysfs_open_driver(bus_type, dev->driver_name);
|
|
||||||
if (!drv) {
|
|
||||||
dbg("could not open device driver on %s: %s",
|
|
||||||
dev->name, strerror(errno));
|
|
||||||
goto err_close_intf_dev;
|
|
||||||
}
|
|
||||||
dbg("device driver: %s", drv->path);
|
|
||||||
|
|
||||||
unbind_attr = sysfs_get_driver_attr(drv, "unbind");
|
|
||||||
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) {
|
|
||||||
/* NOTE: why keep unbinding other interfaces? */
|
|
||||||
dbg("unbind driver at %s failed", dev->bus_id);
|
|
||||||
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 @@ out:
|
||||||
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)
|
||||||
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 @@
|
||||||
* 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 (add)
|
||||||
if (!match_busid_attr) {
|
snprintf(command, SYSFS_BUS_ID_SIZE + 4, "add %s", busid);
|
||||||
dbg("problem getting match_busid attribute: %s",
|
else
|
||||||
strerror(errno));
|
snprintf(command, SYSFS_BUS_ID_SIZE + 4, "del %s", busid);
|
||||||
|
|
||||||
|
rc = write_sysfs_attribute(match_busid_attr_path, command,
|
||||||
|
sizeof(command));
|
||||||
|
if (rc < 0) {
|
||||||
|
dbg("failed to write match_busid: %s", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add)
|
return 0;
|
||||||
snprintf(buff, SYSFS_BUS_ID_SIZE + 4, "add %s", busid);
|
|
||||||
else
|
|
||||||
snprintf(buff, 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));
|
|
||||||
if (rc < 0) {
|
|
||||||
dbg("failed to write match_busid: %s", strerror(errno));
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sysfs_close_attribute(match_busid_attr);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue