PageRenderTime 772ms CodeModel.GetById 91ms RepoModel.GetById 43ms app.codeStats 0ms

/drivers/staging/usbip/userspace/src/bind-driver.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2
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
  1. /*
  2. *
  3. * Copyright (C) 2005-2007 Takahiro Hirofuchi
  4. */
  5. #include "utils.h"
  6. #define _GNU_SOURCE
  7. #include <getopt.h>
  8. #include <glib.h>
  9. static const struct option longopts[] = {
  10. {"usbip", required_argument, NULL, 'u'},
  11. {"other", required_argument, NULL, 'o'},
  12. {"list", no_argument, NULL, 'l'},
  13. {"list2", no_argument, NULL, 'L'},
  14. {"help", no_argument, NULL, 'h'},
  15. #if 0
  16. {"allusbip", no_argument, NULL, 'a'},
  17. {"export-to", required_argument, NULL, 'e'},
  18. {"unexport", required_argument, NULL, 'x'},
  19. {"busid", required_argument, NULL, 'b'},
  20. #endif
  21. {NULL, 0, NULL, 0}
  22. };
  23. static const char match_busid_path[] = "/sys/bus/usb/drivers/usbip/match_busid";
  24. static void show_help(void)
  25. {
  26. printf("Usage: usbip_bind_driver [OPTION]\n");
  27. printf("Change driver binding for USB/IP.\n");
  28. printf(" --usbip busid make a device exportable\n");
  29. printf(" --other busid use a device by a local driver\n");
  30. printf(" --list print usb devices and their drivers\n");
  31. printf(" --list2 print usb devices and their drivers in parseable mode\n");
  32. #if 0
  33. printf(" --allusbip make all devices exportable\n");
  34. printf(" --export-to host export the device to 'host'\n");
  35. printf(" --unexport host unexport a device previously exported to 'host'\n");
  36. printf(" --busid busid the busid used for --export-to\n");
  37. #endif
  38. }
  39. static int modify_match_busid(char *busid, int add)
  40. {
  41. int fd;
  42. int ret;
  43. char buff[BUS_ID_SIZE + 4];
  44. /* BUS_IS_SIZE includes NULL termination? */
  45. if (strnlen(busid, BUS_ID_SIZE) > BUS_ID_SIZE - 1) {
  46. g_warning("too long busid");
  47. return -1;
  48. }
  49. fd = open(match_busid_path, O_WRONLY);
  50. if (fd < 0)
  51. return -1;
  52. if (add)
  53. snprintf(buff, BUS_ID_SIZE + 4, "add %s", busid);
  54. else
  55. snprintf(buff, BUS_ID_SIZE + 4, "del %s", busid);
  56. g_debug("write \"%s\" to %s", buff, match_busid_path);
  57. ret = write(fd, buff, sizeof(buff));
  58. if (ret < 0) {
  59. close(fd);
  60. return -1;
  61. }
  62. close(fd);
  63. return 0;
  64. }
  65. static const char unbind_path_format[] = "/sys/bus/usb/devices/%s/driver/unbind";
  66. /* buggy driver may cause dead lock */
  67. static int unbind_interface_busid(char *busid)
  68. {
  69. char unbind_path[PATH_MAX];
  70. int fd;
  71. int ret;
  72. snprintf(unbind_path, sizeof(unbind_path), unbind_path_format, busid);
  73. fd = open(unbind_path, O_WRONLY);
  74. if (fd < 0) {
  75. g_warning("opening unbind_path failed: %d", fd);
  76. return -1;
  77. }
  78. ret = write(fd, busid, strnlen(busid, BUS_ID_SIZE));
  79. if (ret < 0) {
  80. g_warning("write to unbind_path failed: %d", ret);
  81. close(fd);
  82. return -1;
  83. }
  84. close(fd);
  85. return 0;
  86. }
  87. static int unbind_interface(char *busid, int configvalue, int interface)
  88. {
  89. char inf_busid[BUS_ID_SIZE];
  90. g_debug("unbinding interface");
  91. snprintf(inf_busid, BUS_ID_SIZE, "%s:%d.%d", busid, configvalue, interface);
  92. return unbind_interface_busid(inf_busid);
  93. }
  94. static const char bind_path_format[] = "/sys/bus/usb/drivers/%s/bind";
  95. static int bind_interface_busid(char *busid, char *driver)
  96. {
  97. char bind_path[PATH_MAX];
  98. int fd;
  99. int ret;
  100. snprintf(bind_path, sizeof(bind_path), bind_path_format, driver);
  101. fd = open(bind_path, O_WRONLY);
  102. if (fd < 0)
  103. return -1;
  104. ret = write(fd, busid, strnlen(busid, BUS_ID_SIZE));
  105. if (ret < 0) {
  106. close(fd);
  107. return -1;
  108. }
  109. close(fd);
  110. return 0;
  111. }
  112. static int bind_interface(char *busid, int configvalue, int interface, char *driver)
  113. {
  114. char inf_busid[BUS_ID_SIZE];
  115. snprintf(inf_busid, BUS_ID_SIZE, "%s:%d.%d", busid, configvalue, interface);
  116. return bind_interface_busid(inf_busid, driver);
  117. }
  118. static int unbind(char *busid)
  119. {
  120. int configvalue = 0;
  121. int ninterface = 0;
  122. int devclass = 0;
  123. int i;
  124. int failed = 0;
  125. configvalue = read_bConfigurationValue(busid);
  126. ninterface = read_bNumInterfaces(busid);
  127. devclass = read_bDeviceClass(busid);
  128. if (configvalue < 0 || ninterface < 0 || devclass < 0) {
  129. g_warning("read config and ninf value, removed?");
  130. return -1;
  131. }
  132. if (devclass == 0x09) {
  133. g_message("skip unbinding of hub");
  134. return -1;
  135. }
  136. for (i = 0; i < ninterface; i++) {
  137. char driver[PATH_MAX];
  138. int ret;
  139. bzero(&driver, sizeof(driver));
  140. getdriver(busid, configvalue, i, driver, PATH_MAX-1);
  141. g_debug(" %s:%d.%d -> %s ", busid, configvalue, i, driver);
  142. if (!strncmp("none", driver, PATH_MAX))
  143. continue; /* unbound interface */
  144. #if 0
  145. if (!strncmp("usbip", driver, PATH_MAX))
  146. continue; /* already bound to usbip */
  147. #endif
  148. /* unbinding */
  149. ret = unbind_interface(busid, configvalue, i);
  150. if (ret < 0) {
  151. g_warning("unbind driver at %s:%d.%d failed",
  152. busid, configvalue, i);
  153. failed = 1;
  154. }
  155. }
  156. if (failed)
  157. return -1;
  158. else
  159. return 0;
  160. }
  161. /* call at unbound state */
  162. static int bind_to_usbip(char *busid)
  163. {
  164. int configvalue = 0;
  165. int ninterface = 0;
  166. int i;
  167. int failed = 0;
  168. configvalue = read_bConfigurationValue(busid);
  169. ninterface = read_bNumInterfaces(busid);
  170. if (configvalue < 0 || ninterface < 0) {
  171. g_warning("read config and ninf value, removed?");
  172. return -1;
  173. }
  174. for (i = 0; i < ninterface; i++) {
  175. int ret;
  176. ret = bind_interface(busid, configvalue, i, "usbip");
  177. if (ret < 0) {
  178. g_warning("bind usbip at %s:%d.%d, failed",
  179. busid, configvalue, i);
  180. failed = 1;
  181. /* need to contine binding at other interfaces */
  182. }
  183. }
  184. if (failed)
  185. return -1;
  186. else
  187. return 0;
  188. }
  189. static int use_device_by_usbip(char *busid)
  190. {
  191. int ret;
  192. ret = unbind(busid);
  193. if (ret < 0) {
  194. g_warning("unbind drivers of %s, failed", busid);
  195. return -1;
  196. }
  197. ret = modify_match_busid(busid, 1);
  198. if (ret < 0) {
  199. g_warning("add %s to match_busid, failed", busid);
  200. return -1;
  201. }
  202. ret = bind_to_usbip(busid);
  203. if (ret < 0) {
  204. g_warning("bind usbip to %s, failed", busid);
  205. modify_match_busid(busid, 0);
  206. return -1;
  207. }
  208. g_message("bind %s to usbip, complete!", busid);
  209. return 0;
  210. }
  211. static int use_device_by_other(char *busid)
  212. {
  213. int ret;
  214. int config;
  215. /* read and write the same config value to kick probing */
  216. config = read_bConfigurationValue(busid);
  217. if (config < 0) {
  218. g_warning("read bConfigurationValue of %s, failed", busid);
  219. return -1;
  220. }
  221. ret = modify_match_busid(busid, 0);
  222. if (ret < 0) {
  223. g_warning("del %s to match_busid, failed", busid);
  224. return -1;
  225. }
  226. ret = write_bConfigurationValue(busid, config);
  227. if (ret < 0) {
  228. g_warning("read bConfigurationValue of %s, failed", busid);
  229. return -1;
  230. }
  231. g_message("bind %s to other drivers than usbip, complete!", busid);
  232. return 0;
  233. }
  234. #include <sys/types.h>
  235. #include <regex.h>
  236. #include <errno.h>
  237. #include <string.h>
  238. #include <stdio.h>
  239. static int is_usb_device(char *busid)
  240. {
  241. int ret;
  242. regex_t regex;
  243. regmatch_t pmatch[1];
  244. ret = regcomp(&regex, "^[0-9]+-[0-9]+(\\.[0-9]+)*$", REG_NOSUB|REG_EXTENDED);
  245. if (ret < 0)
  246. g_error("regcomp: %s\n", strerror(errno));
  247. ret = regexec(&regex, busid, 0, pmatch, 0);
  248. if (ret)
  249. return 0; /* not matched */
  250. return 1;
  251. }
  252. #include <dirent.h>
  253. static int show_devices(void)
  254. {
  255. DIR *dir;
  256. dir = opendir("/sys/bus/usb/devices/");
  257. if (!dir)
  258. g_error("opendir: %s", strerror(errno));
  259. printf("List USB devices\n");
  260. for (;;) {
  261. struct dirent *dirent;
  262. char *busid;
  263. dirent = readdir(dir);
  264. if (!dirent)
  265. break;
  266. busid = dirent->d_name;
  267. if (is_usb_device(busid)) {
  268. char name[100] = {'\0'};
  269. char driver[100] = {'\0'};
  270. int conf, ninf = 0;
  271. int i;
  272. conf = read_bConfigurationValue(busid);
  273. ninf = read_bNumInterfaces(busid);
  274. getdevicename(busid, name, sizeof(name));
  275. printf(" - busid %s (%s)\n", busid, name);
  276. for (i = 0; i < ninf; i++) {
  277. getdriver(busid, conf, i, driver, sizeof(driver));
  278. printf(" %s:%d.%d -> %s\n", busid, conf, i, driver);
  279. }
  280. printf("\n");
  281. }
  282. }
  283. closedir(dir);
  284. return 0;
  285. }
  286. static int show_devices2(void)
  287. {
  288. DIR *dir;
  289. dir = opendir("/sys/bus/usb/devices/");
  290. if (!dir)
  291. g_error("opendir: %s", strerror(errno));
  292. for (;;) {
  293. struct dirent *dirent;
  294. char *busid;
  295. dirent = readdir(dir);
  296. if (!dirent)
  297. break;
  298. busid = dirent->d_name;
  299. if (is_usb_device(busid)) {
  300. char name[100] = {'\0'};
  301. char driver[100] = {'\0'};
  302. int conf, ninf = 0;
  303. int i;
  304. conf = read_bConfigurationValue(busid);
  305. ninf = read_bNumInterfaces(busid);
  306. getdevicename(busid, name, sizeof(name));
  307. printf("busid=%s#usbid=%s#", busid, name);
  308. for (i = 0; i < ninf; i++) {
  309. getdriver(busid, conf, i, driver, sizeof(driver));
  310. printf("%s:%d.%d=%s#", busid, conf, i, driver);
  311. }
  312. printf("\n");
  313. }
  314. }
  315. closedir(dir);
  316. return 0;
  317. }
  318. #if 0
  319. static int export_to(char *host, char *busid) {
  320. int ret;
  321. if( host == NULL ) {
  322. printf( "no host given\n\n");
  323. show_help();
  324. return -1;
  325. }
  326. if( busid == NULL ) {
  327. /* XXX print device list and ask for busnumber, if none is
  328. * given */
  329. printf( "no busid given, use --busid switch\n\n");
  330. show_help();
  331. return -1;
  332. }
  333. ret = use_device_by_usbip(busid);
  334. if( ret != 0 ) {
  335. printf( "could not bind driver to usbip\n");
  336. return -1;
  337. }
  338. printf( "DEBUG: exporting device '%s' to '%s'\n", busid, host );
  339. ret = export_busid_to_host(host, busid); /* usbip_export.[ch] */
  340. if( ret != 0 ) {
  341. printf( "could not export device to host\n" );
  342. printf( " host: %s, device: %s\n", host, busid );
  343. use_device_by_other(busid);
  344. return -1;
  345. }
  346. return 0;
  347. }
  348. static int unexport_from(char *host, char *busid) {
  349. int ret;
  350. if (!host || !busid)
  351. g_error("no host or no busid\n");
  352. g_message("unexport_from: host: '%s', busid: '%s'", host, busid);
  353. ret = unexport_busid_from_host(host, busid); /* usbip_export.[ch] */
  354. if( ret != 0 ) {
  355. err( "could not unexport device from host\n" );
  356. err( " host: %s, device: %s\n", host, busid );
  357. }
  358. ret = use_device_by_other(busid);
  359. if (ret < 0)
  360. g_error("could not unbind device from usbip\n");
  361. return 0;
  362. }
  363. static int allusbip(void)
  364. {
  365. DIR *dir;
  366. dir = opendir("/sys/bus/usb/devices/");
  367. if (!dir)
  368. g_error("opendir: %s", strerror(errno));
  369. for (;;) {
  370. struct dirent *dirent;
  371. char *busid;
  372. dirent = readdir(dir);
  373. if (!dirent)
  374. break;
  375. busid = dirent->d_name;
  376. if (!is_usb_device(busid))
  377. continue;
  378. {
  379. char name[PATH_MAX];
  380. int conf, ninf = 0;
  381. int i;
  382. int be_local = 0;
  383. conf = read_bConfigurationValue(busid);
  384. ninf = read_bNumInterfaces(busid);
  385. getdevicename(busid, name, sizeof(name));
  386. for (i = 0; i < ninf; i++) {
  387. char driver[PATH_MAX];
  388. getdriver(busid, conf, i, driver, sizeof(driver));
  389. #if 0
  390. if (strncmp(driver, "usbhid", 6) == 0 || strncmp(driver, "usb-storage", 11) == 0) {
  391. be_local = 1;
  392. break;
  393. }
  394. #endif
  395. }
  396. if (be_local == 0)
  397. use_device_by_usbip(busid);
  398. }
  399. }
  400. closedir(dir);
  401. return 0;
  402. }
  403. #endif
  404. int main(int argc, char **argv)
  405. {
  406. char *busid = NULL;
  407. char *remote_host __attribute__((unused)) = NULL;
  408. enum {
  409. cmd_unknown = 0,
  410. cmd_use_by_usbip,
  411. cmd_use_by_other,
  412. cmd_list,
  413. cmd_list2,
  414. cmd_allusbip,
  415. cmd_export_to,
  416. cmd_unexport,
  417. cmd_help,
  418. } cmd = cmd_unknown;
  419. if (geteuid() != 0)
  420. g_warning("running non-root?");
  421. for (;;) {
  422. int c;
  423. int index = 0;
  424. c = getopt_long(argc, argv, "u:o:hlLae:x:b:", longopts, &index);
  425. if (c == -1)
  426. break;
  427. switch (c) {
  428. case 'u':
  429. cmd = cmd_use_by_usbip;
  430. busid = optarg;
  431. break;
  432. case 'o' :
  433. cmd = cmd_use_by_other;
  434. busid = optarg;
  435. break;
  436. case 'l' :
  437. cmd = cmd_list;
  438. break;
  439. case 'L' :
  440. cmd = cmd_list2;
  441. break;
  442. case 'a' :
  443. cmd = cmd_allusbip;
  444. break;
  445. case 'b':
  446. busid = optarg;
  447. break;
  448. case 'e':
  449. cmd = cmd_export_to;
  450. remote_host = optarg;
  451. break;
  452. case 'x':
  453. cmd = cmd_unexport;
  454. remote_host = optarg;
  455. break;
  456. case 'h': /* fallthrough */
  457. case '?':
  458. cmd = cmd_help;
  459. break;
  460. default:
  461. g_error("getopt");
  462. }
  463. //if (cmd)
  464. // break;
  465. }
  466. switch (cmd) {
  467. case cmd_use_by_usbip:
  468. use_device_by_usbip(busid);
  469. break;
  470. case cmd_use_by_other:
  471. use_device_by_other(busid);
  472. break;
  473. case cmd_list:
  474. show_devices();
  475. break;
  476. case cmd_list2:
  477. show_devices2();
  478. break;
  479. #if 0
  480. case cmd_allusbip:
  481. allusbip();
  482. break;
  483. case cmd_export_to:
  484. export_to(remote_host, busid);
  485. break;
  486. case cmd_unexport:
  487. unexport_from(remote_host, busid);
  488. break;
  489. #endif
  490. case cmd_help: /* fallthrough */
  491. case cmd_unknown:
  492. show_help();
  493. break;
  494. default:
  495. g_error("NOT REACHED");
  496. }
  497. return 0;
  498. }