/tags/0.1.12/libusb/linux.c

# · C · 733 lines · 503 code · 155 blank · 75 comment · 123 complexity · 1efab0f4806386eb831c67a3651f0e72 MD5 · raw file

  1. /*
  2. * Linux USB support
  3. *
  4. * Copyright (c) 2000-2003 Johannes Erdfelt <johannes@erdfelt.com>
  5. *
  6. * This library is covered by the LGPL, read LICENSE for details.
  7. */
  8. #include <stdlib.h> /* getenv, etc */
  9. #include <unistd.h>
  10. #include <string.h>
  11. #include <stdio.h>
  12. #include <fcntl.h>
  13. #include <errno.h>
  14. #include <sys/time.h>
  15. #include <dirent.h>
  16. #include "linux.h"
  17. #include "usbi.h"
  18. static char usb_path[PATH_MAX + 1] = "";
  19. static int device_open(struct usb_device *dev)
  20. {
  21. char filename[PATH_MAX + 1];
  22. int fd;
  23. snprintf(filename, sizeof(filename) - 1, "%s/%s/%s",
  24. usb_path, dev->bus->dirname, dev->filename);
  25. fd = open(filename, O_RDWR);
  26. if (fd < 0) {
  27. fd = open(filename, O_RDONLY);
  28. if (fd < 0)
  29. USB_ERROR_STR(-errno, "failed to open %s: %s",
  30. filename, strerror(errno));
  31. }
  32. return fd;
  33. }
  34. int usb_os_open(usb_dev_handle *dev)
  35. {
  36. dev->fd = device_open(dev->device);
  37. return 0;
  38. }
  39. int usb_os_close(usb_dev_handle *dev)
  40. {
  41. if (dev->fd < 0)
  42. return 0;
  43. if (close(dev->fd) == -1)
  44. /* Failing trying to close a file really isn't an error, so return 0 */
  45. USB_ERROR_STR(0, "tried to close device fd %d: %s", dev->fd,
  46. strerror(errno));
  47. return 0;
  48. }
  49. int usb_set_configuration(usb_dev_handle *dev, int configuration)
  50. {
  51. int ret;
  52. ret = ioctl(dev->fd, IOCTL_USB_SETCONFIG, &configuration);
  53. if (ret < 0)
  54. USB_ERROR_STR(-errno, "could not set config %d: %s", configuration,
  55. strerror(errno));
  56. dev->config = configuration;
  57. return 0;
  58. }
  59. int usb_claim_interface(usb_dev_handle *dev, int interface)
  60. {
  61. int ret;
  62. ret = ioctl(dev->fd, IOCTL_USB_CLAIMINTF, &interface);
  63. if (ret < 0) {
  64. if (errno == EBUSY && usb_debug > 0)
  65. fprintf(stderr, "Check that you have permissions to write to %s/%s and, if you don't, that you set up hotplug (http://linux-hotplug.sourceforge.net/) correctly.\n", dev->bus->dirname, dev->device->filename);
  66. USB_ERROR_STR(-errno, "could not claim interface %d: %s", interface,
  67. strerror(errno));
  68. }
  69. dev->interface = interface;
  70. return 0;
  71. }
  72. int usb_release_interface(usb_dev_handle *dev, int interface)
  73. {
  74. int ret;
  75. ret = ioctl(dev->fd, IOCTL_USB_RELEASEINTF, &interface);
  76. if (ret < 0)
  77. USB_ERROR_STR(-errno, "could not release intf %d: %s", interface,
  78. strerror(errno));
  79. dev->interface = -1;
  80. return 0;
  81. }
  82. int usb_set_altinterface(usb_dev_handle *dev, int alternate)
  83. {
  84. int ret;
  85. struct usb_setinterface setintf;
  86. if (dev->interface < 0)
  87. USB_ERROR(-EINVAL);
  88. setintf.interface = dev->interface;
  89. setintf.altsetting = alternate;
  90. ret = ioctl(dev->fd, IOCTL_USB_SETINTF, &setintf);
  91. if (ret < 0)
  92. USB_ERROR_STR(-errno, "could not set alt intf %d/%d: %s",
  93. dev->interface, alternate, strerror(errno));
  94. dev->altsetting = alternate;
  95. return 0;
  96. }
  97. /*
  98. * Linux usbfs has a limit of one page size for synchronous bulk read/write.
  99. * 4096 is the most portable maximum we can do for now.
  100. * Linux usbfs has a limit of 16KB for the URB interface. We use this now
  101. * to get better performance for USB 2.0 devices.
  102. */
  103. #define MAX_READ_WRITE (16 * 1024)
  104. int usb_control_msg(usb_dev_handle *dev, int requesttype, int request,
  105. int value, int index, char *bytes, int size, int timeout)
  106. {
  107. struct usb_ctrltransfer ctrl;
  108. int ret;
  109. ctrl.bRequestType = requesttype;
  110. ctrl.bRequest = request;
  111. ctrl.wValue = value;
  112. ctrl.wIndex = index;
  113. ctrl.wLength = size;
  114. ctrl.data = bytes;
  115. ctrl.timeout = timeout;
  116. ret = ioctl(dev->fd, IOCTL_USB_CONTROL, &ctrl);
  117. if (ret < 0)
  118. USB_ERROR_STR(-errno, "error sending control message: %s", strerror(errno));
  119. return ret;
  120. }
  121. #define URB_USERCONTEXT_COOKIE ((void *)0x1)
  122. /* Reading and writing are the same except for the endpoint */
  123. static int usb_urb_transfer(usb_dev_handle *dev, int ep, int urbtype,
  124. char *bytes, int size, int timeout)
  125. {
  126. struct usb_urb urb;
  127. int bytesdone = 0, requested;
  128. struct timeval tv, tv_ref, tv_now;
  129. struct usb_urb *context;
  130. int ret, waiting;
  131. /*
  132. * HACK: The use of urb.usercontext is a hack to get threaded applications
  133. * sort of working again. Threaded support is still not recommended, but
  134. * this should allow applications to work in the common cases. Basically,
  135. * if we get the completion for an URB we're not waiting for, then we update
  136. * the usercontext pointer to 1 for the other threads URB and it will see
  137. * the change after it wakes up from the the timeout. Ugly, but it works.
  138. */
  139. /*
  140. * Get actual time, and add the timeout value. The result is the absolute
  141. * time where we have to quit waiting for an message.
  142. */
  143. gettimeofday(&tv_ref, NULL);
  144. tv_ref.tv_sec = tv_ref.tv_sec + timeout / 1000;
  145. tv_ref.tv_usec = tv_ref.tv_usec + (timeout % 1000) * 1000;
  146. if (tv_ref.tv_usec > 1000000) {
  147. tv_ref.tv_usec -= 1000000;
  148. tv_ref.tv_sec++;
  149. }
  150. do {
  151. fd_set writefds;
  152. requested = size - bytesdone;
  153. if (requested > MAX_READ_WRITE)
  154. requested = MAX_READ_WRITE;
  155. urb.type = urbtype;
  156. urb.endpoint = ep;
  157. urb.flags = 0;
  158. urb.buffer = bytes + bytesdone;
  159. urb.buffer_length = requested;
  160. urb.signr = 0;
  161. urb.actual_length = 0;
  162. urb.number_of_packets = 0; /* don't do isochronous yet */
  163. urb.usercontext = NULL;
  164. ret = ioctl(dev->fd, IOCTL_USB_SUBMITURB, &urb);
  165. if (ret < 0) {
  166. USB_ERROR_STR(-errno, "error submitting URB: %s", strerror(errno));
  167. return ret;
  168. }
  169. FD_ZERO(&writefds);
  170. FD_SET(dev->fd, &writefds);
  171. restart:
  172. waiting = 1;
  173. context = NULL;
  174. while (!urb.usercontext && ((ret = ioctl(dev->fd, IOCTL_USB_REAPURBNDELAY, &context)) == -1) && waiting) {
  175. tv.tv_sec = 0;
  176. tv.tv_usec = 1000; // 1 msec
  177. select(dev->fd + 1, NULL, &writefds, NULL, &tv); //sub second wait
  178. if (timeout) {
  179. /* compare with actual time, as the select timeout is not that precise */
  180. gettimeofday(&tv_now, NULL);
  181. if ((tv_now.tv_sec > tv_ref.tv_sec) ||
  182. ((tv_now.tv_sec == tv_ref.tv_sec) && (tv_now.tv_usec >= tv_ref.tv_usec)))
  183. waiting = 0;
  184. }
  185. }
  186. if (context && context != &urb) {
  187. context->usercontext = URB_USERCONTEXT_COOKIE;
  188. /* We need to restart since we got a successful URB, but not ours */
  189. goto restart;
  190. }
  191. /*
  192. * If there was an error, that wasn't EAGAIN (no completion), then
  193. * something happened during the reaping and we should return that
  194. * error now
  195. */
  196. if (ret < 0 && !urb.usercontext && errno != EAGAIN)
  197. USB_ERROR_STR(-errno, "error reaping URB: %s", strerror(errno));
  198. bytesdone += urb.actual_length;
  199. } while ((ret == 0 || urb.usercontext) && bytesdone < size && urb.actual_length == requested);
  200. /* If the URB didn't complete in success or error, then let's unlink it */
  201. if (ret < 0 && !urb.usercontext) {
  202. int rc;
  203. if (!waiting)
  204. rc = -ETIMEDOUT;
  205. else
  206. rc = urb.status;
  207. ret = ioctl(dev->fd, IOCTL_USB_DISCARDURB, &urb);
  208. if (ret < 0 && errno != EINVAL && usb_debug >= 1)
  209. fprintf(stderr, "error discarding URB: %s", strerror(errno));
  210. /*
  211. * When the URB is unlinked, it gets moved to the completed list and
  212. * then we need to reap it or else the next time we call this function,
  213. * we'll get the previous completion and exit early
  214. */
  215. ioctl(dev->fd, IOCTL_USB_REAPURB, &context);
  216. return rc;
  217. }
  218. return bytesdone;
  219. }
  220. int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size,
  221. int timeout)
  222. {
  223. /* Ensure the endpoint address is correct */
  224. return usb_urb_transfer(dev, ep, USB_URB_TYPE_BULK, bytes, size,
  225. timeout);
  226. }
  227. int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size,
  228. int timeout)
  229. {
  230. /* Ensure the endpoint address is correct */
  231. ep |= USB_ENDPOINT_IN;
  232. return usb_urb_transfer(dev, ep, USB_URB_TYPE_BULK, bytes, size,
  233. timeout);
  234. }
  235. /*
  236. * FIXME: Packetize large buffers here. 2.4 HCDs (atleast, haven't checked
  237. * 2.5 HCDs yet) don't handle multi-packet Interrupt transfers. So we need
  238. * to lookup the endpoint packet size and packetize appropriately here.
  239. */
  240. int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
  241. int timeout)
  242. {
  243. /* Ensure the endpoint address is correct */
  244. return usb_urb_transfer(dev, ep, USB_URB_TYPE_INTERRUPT, bytes, size,
  245. timeout);
  246. }
  247. int usb_interrupt_read(usb_dev_handle *dev, int ep, char *bytes, int size,
  248. int timeout)
  249. {
  250. /* Ensure the endpoint address is correct */
  251. ep |= USB_ENDPOINT_IN;
  252. return usb_urb_transfer(dev, ep, USB_URB_TYPE_INTERRUPT, bytes, size,
  253. timeout);
  254. }
  255. int usb_os_find_busses(struct usb_bus **busses)
  256. {
  257. struct usb_bus *fbus = NULL;
  258. DIR *dir;
  259. struct dirent *entry;
  260. dir = opendir(usb_path);
  261. if (!dir)
  262. USB_ERROR_STR(-errno, "couldn't opendir(%s): %s", usb_path,
  263. strerror(errno));
  264. while ((entry = readdir(dir)) != NULL) {
  265. struct usb_bus *bus;
  266. /* Skip anything starting with a . */
  267. if (entry->d_name[0] == '.')
  268. continue;
  269. if (!strchr("0123456789", entry->d_name[strlen(entry->d_name) - 1])) {
  270. if (usb_debug >= 2)
  271. fprintf(stderr, "usb_os_find_busses: Skipping non bus directory %s\n",
  272. entry->d_name);
  273. continue;
  274. }
  275. bus = malloc(sizeof(*bus));
  276. if (!bus)
  277. USB_ERROR(-ENOMEM);
  278. memset((void *)bus, 0, sizeof(*bus));
  279. strncpy(bus->dirname, entry->d_name, sizeof(bus->dirname) - 1);
  280. bus->dirname[sizeof(bus->dirname) - 1] = 0;
  281. LIST_ADD(fbus, bus);
  282. if (usb_debug >= 2)
  283. fprintf(stderr, "usb_os_find_busses: Found %s\n", bus->dirname);
  284. }
  285. closedir(dir);
  286. *busses = fbus;
  287. return 0;
  288. }
  289. int usb_os_find_devices(struct usb_bus *bus, struct usb_device **devices)
  290. {
  291. struct usb_device *fdev = NULL;
  292. DIR *dir;
  293. struct dirent *entry;
  294. char dirpath[PATH_MAX + 1];
  295. snprintf(dirpath, PATH_MAX, "%s/%s", usb_path, bus->dirname);
  296. dir = opendir(dirpath);
  297. if (!dir)
  298. USB_ERROR_STR(-errno, "couldn't opendir(%s): %s", dirpath,
  299. strerror(errno));
  300. while ((entry = readdir(dir)) != NULL) {
  301. unsigned char device_desc[DEVICE_DESC_LENGTH];
  302. char filename[PATH_MAX + 1];
  303. struct usb_device *dev;
  304. struct usb_connectinfo connectinfo;
  305. int i, fd, ret;
  306. /* Skip anything starting with a . */
  307. if (entry->d_name[0] == '.')
  308. continue;
  309. dev = malloc(sizeof(*dev));
  310. if (!dev)
  311. USB_ERROR(-ENOMEM);
  312. memset((void *)dev, 0, sizeof(*dev));
  313. dev->bus = bus;
  314. strncpy(dev->filename, entry->d_name, sizeof(dev->filename) - 1);
  315. dev->filename[sizeof(dev->filename) - 1] = 0;
  316. snprintf(filename, sizeof(filename) - 1, "%s/%s", dirpath, entry->d_name);
  317. fd = open(filename, O_RDWR);
  318. if (fd < 0) {
  319. fd = open(filename, O_RDONLY);
  320. if (fd < 0) {
  321. if (usb_debug >= 2)
  322. fprintf(stderr, "usb_os_find_devices: Couldn't open %s\n",
  323. filename);
  324. free(dev);
  325. continue;
  326. }
  327. }
  328. /* Get the device number */
  329. ret = ioctl(fd, IOCTL_USB_CONNECTINFO, &connectinfo);
  330. if (ret < 0) {
  331. if (usb_debug)
  332. fprintf(stderr, "usb_os_find_devices: couldn't get connect info\n");
  333. } else
  334. dev->devnum = connectinfo.devnum;
  335. ret = read(fd, (void *)device_desc, DEVICE_DESC_LENGTH);
  336. if (ret < 0) {
  337. if (usb_debug)
  338. fprintf(stderr, "usb_os_find_devices: Couldn't read descriptor\n");
  339. free(dev);
  340. goto err;
  341. }
  342. /*
  343. * Linux kernel converts the words in this descriptor to CPU endian, so
  344. * we use the undocumented W character for usb_parse_descriptor() that
  345. * doesn't convert endianess when parsing the descriptor
  346. */
  347. usb_parse_descriptor(device_desc, "bbWbbbbWWWbbbb", &dev->descriptor);
  348. LIST_ADD(fdev, dev);
  349. if (usb_debug >= 2)
  350. fprintf(stderr, "usb_os_find_devices: Found %s on %s\n",
  351. dev->filename, bus->dirname);
  352. /* Now try to fetch the rest of the descriptors */
  353. if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG)
  354. /* Silent since we'll try again later */
  355. goto err;
  356. if (dev->descriptor.bNumConfigurations < 1)
  357. /* Silent since we'll try again later */
  358. goto err;
  359. dev->config = (struct usb_config_descriptor *)malloc(dev->descriptor.bNumConfigurations * sizeof(struct usb_config_descriptor));
  360. if (!dev->config)
  361. /* Silent since we'll try again later */
  362. goto err;
  363. memset(dev->config, 0, dev->descriptor.bNumConfigurations *
  364. sizeof(struct usb_config_descriptor));
  365. for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
  366. unsigned char buffer[8], *bigbuffer;
  367. struct usb_config_descriptor config;
  368. /* Get the first 8 bytes so we can figure out what the total length is */
  369. ret = read(fd, (void *)buffer, 8);
  370. if (ret < 8) {
  371. if (usb_debug >= 1) {
  372. if (ret < 0)
  373. fprintf(stderr, "Unable to get descriptor (%d)\n", ret);
  374. else
  375. fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", 8, ret);
  376. }
  377. goto err;
  378. }
  379. usb_parse_descriptor(buffer, "bbw", &config);
  380. bigbuffer = malloc(config.wTotalLength);
  381. if (!bigbuffer) {
  382. if (usb_debug >= 1)
  383. fprintf(stderr, "Unable to allocate memory for descriptors\n");
  384. goto err;
  385. }
  386. /* Read the rest of the config descriptor */
  387. memcpy(bigbuffer, buffer, 8);
  388. ret = read(fd, (void *)(bigbuffer + 8), config.wTotalLength - 8);
  389. if (ret < config.wTotalLength - 8) {
  390. if (usb_debug >= 1) {
  391. if (ret < 0)
  392. fprintf(stderr, "Unable to get descriptor (%d)\n", ret);
  393. else
  394. fprintf(stderr, "Config descriptor too short (expected %d, got %d)\n", config.wTotalLength, ret);
  395. }
  396. free(bigbuffer);
  397. goto err;
  398. }
  399. ret = usb_parse_configuration(&dev->config[i], bigbuffer);
  400. if (usb_debug >= 2) {
  401. if (ret > 0)
  402. fprintf(stderr, "Descriptor data still left\n");
  403. else if (ret < 0)
  404. fprintf(stderr, "Unable to parse descriptors\n");
  405. }
  406. free(bigbuffer);
  407. }
  408. err:
  409. close(fd);
  410. }
  411. closedir(dir);
  412. *devices = fdev;
  413. return 0;
  414. }
  415. int usb_os_determine_children(struct usb_bus *bus)
  416. {
  417. struct usb_device *dev, *devices[256];
  418. struct usb_ioctl command;
  419. int ret, i, i1;
  420. /* Create a list of devices first */
  421. memset(devices, 0, sizeof(devices));
  422. for (dev = bus->devices; dev; dev = dev->next)
  423. if (dev->devnum)
  424. devices[dev->devnum] = dev;
  425. /* Now fetch the children for each device */
  426. for (dev = bus->devices; dev; dev = dev->next) {
  427. struct usb_hub_portinfo portinfo;
  428. int fd;
  429. fd = device_open(dev);
  430. if (fd < 0)
  431. continue;
  432. /* Query the hub driver for the children of this device */
  433. if (dev->config && dev->config->interface && dev->config->interface->altsetting)
  434. command.ifno = dev->config->interface->altsetting->bInterfaceNumber;
  435. else
  436. command.ifno = 0;
  437. command.ioctl_code = IOCTL_USB_HUB_PORTINFO;
  438. command.data = &portinfo;
  439. ret = ioctl(fd, IOCTL_USB_IOCTL, &command);
  440. if (ret < 0) {
  441. /* errno == ENOSYS means the device probably wasn't a hub */
  442. if (errno != ENOSYS && usb_debug > 1)
  443. fprintf(stderr, "error obtaining child information: %s\n",
  444. strerror(errno));
  445. close(fd);
  446. continue;
  447. }
  448. dev->num_children = 0;
  449. for (i = 0; i < portinfo.numports; i++)
  450. if (portinfo.port[i])
  451. dev->num_children++;
  452. /* Free any old children first */
  453. free(dev->children);
  454. dev->children = malloc(sizeof(struct usb_device *) * dev->num_children);
  455. if (!dev->children) {
  456. if (usb_debug > 1)
  457. fprintf(stderr, "error allocating %zu bytes memory for dev->children\n",
  458. sizeof(struct usb_device *) * dev->num_children);
  459. dev->num_children = 0;
  460. close(fd);
  461. continue;
  462. }
  463. for (i = 0, i1 = 0; i < portinfo.numports; i++) {
  464. if (!portinfo.port[i])
  465. continue;
  466. dev->children[i1++] = devices[portinfo.port[i]];
  467. devices[portinfo.port[i]] = NULL;
  468. }
  469. close(fd);
  470. }
  471. /*
  472. * There should be one device left in the devices list and that should be
  473. * the root device
  474. */
  475. for (i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
  476. if (devices[i])
  477. bus->root_dev = devices[i];
  478. }
  479. return 0;
  480. }
  481. static int check_usb_vfs(const char *dirname)
  482. {
  483. DIR *dir;
  484. struct dirent *entry;
  485. int found = 0;
  486. dir = opendir(dirname);
  487. if (!dir)
  488. return 0;
  489. while ((entry = readdir(dir)) != NULL) {
  490. /* Skip anything starting with a . */
  491. if (entry->d_name[0] == '.')
  492. continue;
  493. /* We assume if we find any files that it must be the right place */
  494. found = 1;
  495. break;
  496. }
  497. closedir(dir);
  498. return found;
  499. }
  500. void usb_os_init(void)
  501. {
  502. /* Find the path to the virtual filesystem */
  503. if (getenv("USB_DEVFS_PATH")) {
  504. if (check_usb_vfs(getenv("USB_DEVFS_PATH"))) {
  505. strncpy(usb_path, getenv("USB_DEVFS_PATH"), sizeof(usb_path) - 1);
  506. usb_path[sizeof(usb_path) - 1] = 0;
  507. } else if (usb_debug)
  508. fprintf(stderr, "usb_os_init: couldn't find USB VFS in USB_DEVFS_PATH\n");
  509. }
  510. if (!usb_path[0]) {
  511. if (check_usb_vfs("/dev/bus/usb")) {
  512. strncpy(usb_path, "/dev/bus/usb", sizeof(usb_path) - 1);
  513. usb_path[sizeof(usb_path) - 1] = 0;
  514. } else if (check_usb_vfs("/proc/bus/usb")) {
  515. strncpy(usb_path, "/proc/bus/usb", sizeof(usb_path) - 1);
  516. usb_path[sizeof(usb_path) - 1] = 0;
  517. } else
  518. usb_path[0] = 0; /* No path, no USB support */
  519. }
  520. if (usb_debug) {
  521. if (usb_path[0])
  522. fprintf(stderr, "usb_os_init: Found USB VFS at %s\n", usb_path);
  523. else
  524. fprintf(stderr, "usb_os_init: No USB VFS found, is it mounted?\n");
  525. }
  526. }
  527. int usb_resetep(usb_dev_handle *dev, unsigned int ep)
  528. {
  529. int ret;
  530. ret = ioctl(dev->fd, IOCTL_USB_RESETEP, &ep);
  531. if (ret)
  532. USB_ERROR_STR(-errno, "could not reset ep %d: %s", ep,
  533. strerror(errno));
  534. return 0;
  535. }
  536. int usb_clear_halt(usb_dev_handle *dev, unsigned int ep)
  537. {
  538. int ret;
  539. ret = ioctl(dev->fd, IOCTL_USB_CLEAR_HALT, &ep);
  540. if (ret)
  541. USB_ERROR_STR(-errno, "could not clear/halt ep %d: %s", ep,
  542. strerror(errno));
  543. return 0;
  544. }
  545. int usb_reset(usb_dev_handle *dev)
  546. {
  547. int ret;
  548. ret = ioctl(dev->fd, IOCTL_USB_RESET, NULL);
  549. if (ret)
  550. USB_ERROR_STR(-errno, "could not reset: %s", strerror(errno));
  551. return 0;
  552. }
  553. int usb_get_driver_np(usb_dev_handle *dev, int interface, char *name,
  554. unsigned int namelen)
  555. {
  556. struct usb_getdriver getdrv;
  557. int ret;
  558. getdrv.interface = interface;
  559. ret = ioctl(dev->fd, IOCTL_USB_GETDRIVER, &getdrv);
  560. if (ret)
  561. USB_ERROR_STR(-errno, "could not get bound driver: %s", strerror(errno));
  562. strncpy(name, getdrv.driver, namelen - 1);
  563. name[namelen - 1] = 0;
  564. return 0;
  565. }
  566. int usb_detach_kernel_driver_np(usb_dev_handle *dev, int interface)
  567. {
  568. struct usb_ioctl command;
  569. int ret;
  570. command.ifno = interface;
  571. command.ioctl_code = IOCTL_USB_DISCONNECT;
  572. command.data = NULL;
  573. ret = ioctl(dev->fd, IOCTL_USB_IOCTL, &command);
  574. if (ret)
  575. USB_ERROR_STR(-errno, "could not detach kernel driver from interface %d: %s",
  576. interface, strerror(errno));
  577. return 0;
  578. }