/drivers/staging/usbip/userspace/src/bind-driver.c
C | 643 lines | 484 code | 145 blank | 14 comment | 72 complexity | f675406a7299b399a62948cd69d83913 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- *
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
- */
- #include "utils.h"
- #define _GNU_SOURCE
- #include <getopt.h>
- #include <glib.h>
- static const struct option longopts[] = {
- {"usbip", required_argument, NULL, 'u'},
- {"other", required_argument, NULL, 'o'},
- {"list", no_argument, NULL, 'l'},
- {"list2", no_argument, NULL, 'L'},
- {"help", no_argument, NULL, 'h'},
- #if 0
- {"allusbip", no_argument, NULL, 'a'},
- {"export-to", required_argument, NULL, 'e'},
- {"unexport", required_argument, NULL, 'x'},
- {"busid", required_argument, NULL, 'b'},
- #endif
- {NULL, 0, NULL, 0}
- };
- static const char match_busid_path[] = "/sys/bus/usb/drivers/usbip/match_busid";
- static void show_help(void)
- {
- printf("Usage: usbip_bind_driver [OPTION]\n");
- printf("Change driver binding for USB/IP.\n");
- printf(" --usbip busid make a device exportable\n");
- printf(" --other busid use a device by a local driver\n");
- printf(" --list print usb devices and their drivers\n");
- printf(" --list2 print usb devices and their drivers in parseable mode\n");
- #if 0
- printf(" --allusbip make all devices exportable\n");
- printf(" --export-to host export the device to 'host'\n");
- printf(" --unexport host unexport a device previously exported to 'host'\n");
- printf(" --busid busid the busid used for --export-to\n");
- #endif
- }
- static int modify_match_busid(char *busid, int add)
- {
- int fd;
- int ret;
- char buff[BUS_ID_SIZE + 4];
- /* BUS_IS_SIZE includes NULL termination? */
- if (strnlen(busid, BUS_ID_SIZE) > BUS_ID_SIZE - 1) {
- g_warning("too long busid");
- return -1;
- }
- fd = open(match_busid_path, O_WRONLY);
- if (fd < 0)
- return -1;
- if (add)
- snprintf(buff, BUS_ID_SIZE + 4, "add %s", busid);
- else
- snprintf(buff, BUS_ID_SIZE + 4, "del %s", busid);
- g_debug("write \"%s\" to %s", buff, match_busid_path);
- ret = write(fd, buff, sizeof(buff));
- if (ret < 0) {
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
- }
- static const char unbind_path_format[] = "/sys/bus/usb/devices/%s/driver/unbind";
- /* buggy driver may cause dead lock */
- static int unbind_interface_busid(char *busid)
- {
- char unbind_path[PATH_MAX];
- int fd;
- int ret;
- snprintf(unbind_path, sizeof(unbind_path), unbind_path_format, busid);
- fd = open(unbind_path, O_WRONLY);
- if (fd < 0) {
- g_warning("opening unbind_path failed: %d", fd);
- return -1;
- }
- ret = write(fd, busid, strnlen(busid, BUS_ID_SIZE));
- if (ret < 0) {
- g_warning("write to unbind_path failed: %d", ret);
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
- }
- static int unbind_interface(char *busid, int configvalue, int interface)
- {
- char inf_busid[BUS_ID_SIZE];
- g_debug("unbinding interface");
- snprintf(inf_busid, BUS_ID_SIZE, "%s:%d.%d", busid, configvalue, interface);
- return unbind_interface_busid(inf_busid);
- }
- static const char bind_path_format[] = "/sys/bus/usb/drivers/%s/bind";
- static int bind_interface_busid(char *busid, char *driver)
- {
- char bind_path[PATH_MAX];
- int fd;
- int ret;
- snprintf(bind_path, sizeof(bind_path), bind_path_format, driver);
- fd = open(bind_path, O_WRONLY);
- if (fd < 0)
- return -1;
- ret = write(fd, busid, strnlen(busid, BUS_ID_SIZE));
- if (ret < 0) {
- close(fd);
- return -1;
- }
- close(fd);
- return 0;
- }
- static int bind_interface(char *busid, int configvalue, int interface, char *driver)
- {
- char inf_busid[BUS_ID_SIZE];
- snprintf(inf_busid, BUS_ID_SIZE, "%s:%d.%d", busid, configvalue, interface);
- return bind_interface_busid(inf_busid, driver);
- }
- static int unbind(char *busid)
- {
- int configvalue = 0;
- int ninterface = 0;
- int devclass = 0;
- int i;
- int failed = 0;
- configvalue = read_bConfigurationValue(busid);
- ninterface = read_bNumInterfaces(busid);
- devclass = read_bDeviceClass(busid);
- if (configvalue < 0 || ninterface < 0 || devclass < 0) {
- g_warning("read config and ninf value, removed?");
- return -1;
- }
- if (devclass == 0x09) {
- g_message("skip unbinding of hub");
- return -1;
- }
- for (i = 0; i < ninterface; i++) {
- char driver[PATH_MAX];
- int ret;
- bzero(&driver, sizeof(driver));
- getdriver(busid, configvalue, i, driver, PATH_MAX-1);
- g_debug(" %s:%d.%d -> %s ", busid, configvalue, i, driver);
- if (!strncmp("none", driver, PATH_MAX))
- continue; /* unbound interface */
- #if 0
- if (!strncmp("usbip", driver, PATH_MAX))
- continue; /* already bound to usbip */
- #endif
- /* unbinding */
- ret = unbind_interface(busid, configvalue, i);
- if (ret < 0) {
- g_warning("unbind driver at %s:%d.%d failed",
- busid, configvalue, i);
- failed = 1;
- }
- }
- if (failed)
- return -1;
- else
- return 0;
- }
- /* call at unbound state */
- static int bind_to_usbip(char *busid)
- {
- int configvalue = 0;
- int ninterface = 0;
- int i;
- int failed = 0;
- configvalue = read_bConfigurationValue(busid);
- ninterface = read_bNumInterfaces(busid);
- if (configvalue < 0 || ninterface < 0) {
- g_warning("read config and ninf value, removed?");
- return -1;
- }
- for (i = 0; i < ninterface; i++) {
- int ret;
- ret = bind_interface(busid, configvalue, i, "usbip");
- if (ret < 0) {
- g_warning("bind usbip at %s:%d.%d, failed",
- busid, configvalue, i);
- failed = 1;
- /* need to contine binding at other interfaces */
- }
- }
- if (failed)
- return -1;
- else
- return 0;
- }
- static int use_device_by_usbip(char *busid)