3 * Copyright (C) 2005-2007 Takahiro Hirofuchi
14 static const struct option longopts[] = {
15 {"usbip", required_argument, NULL, 'u'},
16 {"other", required_argument, NULL, 'o'},
17 {"list", no_argument, NULL, 'l'},
18 {"list2", no_argument, NULL, 'L'},
19 {"help", no_argument, NULL, 'h'},
21 {"allusbip", no_argument, NULL, 'a'},
22 {"export-to", required_argument, NULL, 'e'},
23 {"unexport", required_argument, NULL, 'x'},
24 {"busid", required_argument, NULL, 'b'},
30 static const char match_busid_path[] = "/sys/bus/usb/drivers/usbip/match_busid";
33 static void show_help(void)
35 printf("Usage: usbip_bind_driver [OPTION]\n");
36 printf("Change driver binding for USB/IP.\n");
37 printf(" --usbip busid make a device exportable\n");
38 printf(" --other busid use a device by a local driver\n");
39 printf(" --list print usb devices and their drivers\n");
40 printf(" --list2 print usb devices and their drivers in parseable mode\n");
42 printf(" --allusbip make all devices exportable\n");
43 printf(" --export-to host export the device to 'host'\n");
44 printf(" --unexport host unexport a device previously exported to 'host'\n");
45 printf(" --busid busid the busid used for --export-to\n");
49 static int modify_match_busid(char *busid, int add)
53 char buff[BUS_ID_SIZE + 4];
55 /* BUS_IS_SIZE includes NULL termination? */
56 if (strnlen(busid, BUS_ID_SIZE) > BUS_ID_SIZE - 1) {
57 g_warning("too long busid");
61 fd = open(match_busid_path, O_WRONLY);
66 snprintf(buff, BUS_ID_SIZE + 4, "add %s", busid);
68 snprintf(buff, BUS_ID_SIZE + 4, "del %s", busid);
70 g_debug("write \"%s\" to %s", buff, match_busid_path);
72 ret = write(fd, buff, sizeof(buff));
83 static const char unbind_path_format[] = "/sys/bus/usb/devices/%s/driver/unbind";
85 /* buggy driver may cause dead lock */
86 static int unbind_interface_busid(char *busid)
88 char unbind_path[PATH_MAX];
92 snprintf(unbind_path, sizeof(unbind_path), unbind_path_format, busid);
94 fd = open(unbind_path, O_WRONLY);
96 g_warning("opening unbind_path failed: %d", fd);
100 ret = write(fd, busid, strnlen(busid, BUS_ID_SIZE));
102 g_warning("write to unbind_path failed: %d", ret);
112 static int unbind_interface(char *busid, int configvalue, int interface)
114 char inf_busid[BUS_ID_SIZE];
115 g_debug("unbinding interface");
117 snprintf(inf_busid, BUS_ID_SIZE, "%s:%d.%d", busid, configvalue, interface);
119 return unbind_interface_busid(inf_busid);
123 static const char bind_path_format[] = "/sys/bus/usb/drivers/%s/bind";
125 static int bind_interface_busid(char *busid, char *driver)
127 char bind_path[PATH_MAX];
131 snprintf(bind_path, sizeof(bind_path), bind_path_format, driver);
133 fd = open(bind_path, O_WRONLY);
137 ret = write(fd, busid, strnlen(busid, BUS_ID_SIZE));
148 static int bind_interface(char *busid, int configvalue, int interface, char *driver)
150 char inf_busid[BUS_ID_SIZE];
152 snprintf(inf_busid, BUS_ID_SIZE, "%s:%d.%d", busid, configvalue, interface);
154 return bind_interface_busid(inf_busid, driver);
157 static int unbind(char *busid)
165 configvalue = read_bConfigurationValue(busid);
166 ninterface = read_bNumInterfaces(busid);
167 devclass = read_bDeviceClass(busid);
169 if (configvalue < 0 || ninterface < 0 || devclass < 0) {
170 g_warning("read config and ninf value, removed?");
174 if (devclass == 0x09) {
175 g_message("skip unbinding of hub");
179 for (i = 0; i < ninterface; i++) {
180 char driver[PATH_MAX];
183 bzero(&driver, sizeof(driver));
185 getdriver(busid, configvalue, i, driver, PATH_MAX-1);
187 g_debug(" %s:%d.%d -> %s ", busid, configvalue, i, driver);
189 if (!strncmp("none", driver, PATH_MAX))
190 continue; /* unbound interface */
193 if (!strncmp("usbip", driver, PATH_MAX))
194 continue; /* already bound to usbip */
198 ret = unbind_interface(busid, configvalue, i);
200 g_warning("unbind driver at %s:%d.%d failed",
201 busid, configvalue, i);
212 /* call at unbound state */
213 static int bind_to_usbip(char *busid)
220 configvalue = read_bConfigurationValue(busid);
221 ninterface = read_bNumInterfaces(busid);
223 if (configvalue < 0 || ninterface < 0) {
224 g_warning("read config and ninf value, removed?");
228 for (i = 0; i < ninterface; i++) {
231 ret = bind_interface(busid, configvalue, i, "usbip");
233 g_warning("bind usbip at %s:%d.%d, failed",
234 busid, configvalue, i);
236 /* need to contine binding at other interfaces */
247 static int use_device_by_usbip(char *busid)
253 g_warning("unbind drivers of %s, failed", busid);
257 ret = modify_match_busid(busid, 1);
259 g_warning("add %s to match_busid, failed", busid);
263 ret = bind_to_usbip(busid);
265 g_warning("bind usbip to %s, failed", busid);
266 modify_match_busid(busid, 0);
270 g_message("bind %s to usbip, complete!", busid);
277 static int use_device_by_other(char *busid)
282 /* read and write the same config value to kick probing */
283 config = read_bConfigurationValue(busid);
285 g_warning("read bConfigurationValue of %s, failed", busid);
289 ret = modify_match_busid(busid, 0);
291 g_warning("del %s to match_busid, failed", busid);
295 ret = write_bConfigurationValue(busid, config);
297 g_warning("read bConfigurationValue of %s, failed", busid);
301 g_message("bind %s to other drivers than usbip, complete!", busid);
307 #include <sys/types.h>
316 static int is_usb_device(char *busid)
321 regmatch_t pmatch[1];
323 ret = regcomp(®ex, "^[0-9]+-[0-9]+(\\.[0-9]+)*$", REG_NOSUB|REG_EXTENDED);
325 g_error("regcomp: %s\n", strerror(errno));
327 ret = regexec(®ex, busid, 0, pmatch, 0);
329 return 0; /* not matched */
336 static int show_devices(void)
340 dir = opendir("/sys/bus/usb/devices/");
342 g_error("opendir: %s", strerror(errno));
344 printf("List USB devices\n");
346 struct dirent *dirent;
349 dirent = readdir(dir);
353 busid = dirent->d_name;
355 if (is_usb_device(busid)) {
356 char name[100] = {'\0'};
357 char driver[100] = {'\0'};
361 conf = read_bConfigurationValue(busid);
362 ninf = read_bNumInterfaces(busid);
364 getdevicename(busid, name, sizeof(name));
366 printf(" - busid %s (%s)\n", busid, name);
368 for (i = 0; i < ninf; i++) {
369 getdriver(busid, conf, i, driver, sizeof(driver));
370 printf(" %s:%d.%d -> %s\n", busid, conf, i, driver);
381 static int show_devices2(void)
385 dir = opendir("/sys/bus/usb/devices/");
387 g_error("opendir: %s", strerror(errno));
390 struct dirent *dirent;
393 dirent = readdir(dir);
397 busid = dirent->d_name;
399 if (is_usb_device(busid)) {
400 char name[100] = {'\0'};
401 char driver[100] = {'\0'};
405 conf = read_bConfigurationValue(busid);
406 ninf = read_bNumInterfaces(busid);
408 getdevicename(busid, name, sizeof(name));
410 printf("busid=%s#usbid=%s#", busid, name);
412 for (i = 0; i < ninf; i++) {
413 getdriver(busid, conf, i, driver, sizeof(driver));
414 printf("%s:%d.%d=%s#", busid, conf, i, driver);
427 static int export_to(char *host, char *busid) {
432 printf( "no host given\n\n");
436 if( busid == NULL ) {
437 /* XXX print device list and ask for busnumber, if none is
439 printf( "no busid given, use --busid switch\n\n");
445 ret = use_device_by_usbip(busid);
447 printf( "could not bind driver to usbip\n");
451 printf( "DEBUG: exporting device '%s' to '%s'\n", busid, host );
452 ret = export_busid_to_host(host, busid); /* usbip_export.[ch] */
454 printf( "could not export device to host\n" );
455 printf( " host: %s, device: %s\n", host, busid );
456 use_device_by_other(busid);
463 static int unexport_from(char *host, char *busid) {
468 g_error("no host or no busid\n");
470 g_message("unexport_from: host: '%s', busid: '%s'", host, busid);
472 ret = unexport_busid_from_host(host, busid); /* usbip_export.[ch] */
474 err( "could not unexport device from host\n" );
475 err( " host: %s, device: %s\n", host, busid );
478 ret = use_device_by_other(busid);
480 g_error("could not unbind device from usbip\n");
486 static int allusbip(void)
490 dir = opendir("/sys/bus/usb/devices/");
492 g_error("opendir: %s", strerror(errno));
495 struct dirent *dirent;
498 dirent = readdir(dir);
502 busid = dirent->d_name;
504 if (!is_usb_device(busid))
513 conf = read_bConfigurationValue(busid);
514 ninf = read_bNumInterfaces(busid);
516 getdevicename(busid, name, sizeof(name));
518 for (i = 0; i < ninf; i++) {
519 char driver[PATH_MAX];
521 getdriver(busid, conf, i, driver, sizeof(driver));
523 if (strncmp(driver, "usbhid", 6) == 0 || strncmp(driver, "usb-storage", 11) == 0) {
531 use_device_by_usbip(busid);
541 int main(int argc, char **argv)
544 char *remote_host __attribute__((unused)) = NULL;
559 g_warning("running non-root?");
565 c = getopt_long(argc, argv, "u:o:hlLae:x:b:", longopts, &index);
571 cmd = cmd_use_by_usbip;
575 cmd = cmd_use_by_other;
592 remote_host = optarg;
596 remote_host = optarg;
598 case 'h': /* fallthrough */
611 case cmd_use_by_usbip:
612 use_device_by_usbip(busid);
614 case cmd_use_by_other:
615 use_device_by_other(busid);
628 export_to(remote_host, busid);
631 unexport_from(remote_host, busid);
634 case cmd_help: /* fallthrough */
639 g_error("NOT REACHED");