netbsd_usb.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. /*
  2. * Copyright © 2011 Martin Pieuchot <mpi@openbsd.org>
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include <sys/time.h>
  19. #include <sys/types.h>
  20. #include <errno.h>
  21. #include <fcntl.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <unistd.h>
  26. #include <dev/usb/usb.h>
  27. #include "libusb.h"
  28. #include "libusbi.h"
  29. struct device_priv {
  30. char devnode[16];
  31. int fd;
  32. unsigned char *cdesc; /* active config descriptor */
  33. usb_device_descriptor_t ddesc; /* usb device descriptor */
  34. };
  35. struct handle_priv {
  36. int pipe[2]; /* for event notification */
  37. int endpoints[USB_MAX_ENDPOINTS];
  38. };
  39. /*
  40. * Backend functions
  41. */
  42. static int netbsd_get_device_list(struct libusb_context *,
  43. struct discovered_devs **);
  44. static int netbsd_open(struct libusb_device_handle *);
  45. static void netbsd_close(struct libusb_device_handle *);
  46. static int netbsd_get_device_descriptor(struct libusb_device *, unsigned char *,
  47. int *);
  48. static int netbsd_get_active_config_descriptor(struct libusb_device *,
  49. unsigned char *, size_t, int *);
  50. static int netbsd_get_config_descriptor(struct libusb_device *, uint8_t,
  51. unsigned char *, size_t, int *);
  52. static int netbsd_get_configuration(struct libusb_device_handle *, int *);
  53. static int netbsd_set_configuration(struct libusb_device_handle *, int);
  54. static int netbsd_claim_interface(struct libusb_device_handle *, int);
  55. static int netbsd_release_interface(struct libusb_device_handle *, int);
  56. static int netbsd_set_interface_altsetting(struct libusb_device_handle *, int,
  57. int);
  58. static int netbsd_clear_halt(struct libusb_device_handle *, unsigned char);
  59. static int netbsd_reset_device(struct libusb_device_handle *);
  60. static void netbsd_destroy_device(struct libusb_device *);
  61. static int netbsd_submit_transfer(struct usbi_transfer *);
  62. static int netbsd_cancel_transfer(struct usbi_transfer *);
  63. static void netbsd_clear_transfer_priv(struct usbi_transfer *);
  64. static int netbsd_handle_events(struct libusb_context *ctx, struct pollfd *,
  65. nfds_t, int);
  66. static int netbsd_clock_gettime(int, struct timespec *);
  67. /*
  68. * Private functions
  69. */
  70. static int _errno_to_libusb(int);
  71. static int _cache_active_config_descriptor(struct libusb_device *, int);
  72. static int _sync_control_transfer(struct usbi_transfer *);
  73. static int _sync_gen_transfer(struct usbi_transfer *);
  74. static int _access_endpoint(struct libusb_transfer *);
  75. const struct usbi_os_backend netbsd_backend = {
  76. "Synchronous NetBSD backend",
  77. 0,
  78. NULL, /* init() */
  79. NULL, /* exit() */
  80. netbsd_get_device_list,
  81. NULL, /* hotplug_poll */
  82. netbsd_open,
  83. netbsd_close,
  84. netbsd_get_device_descriptor,
  85. netbsd_get_active_config_descriptor,
  86. netbsd_get_config_descriptor,
  87. NULL, /* get_config_descriptor_by_value() */
  88. netbsd_get_configuration,
  89. netbsd_set_configuration,
  90. netbsd_claim_interface,
  91. netbsd_release_interface,
  92. netbsd_set_interface_altsetting,
  93. netbsd_clear_halt,
  94. netbsd_reset_device,
  95. NULL, /* kernel_driver_active() */
  96. NULL, /* detach_kernel_driver() */
  97. NULL, /* attach_kernel_driver() */
  98. netbsd_destroy_device,
  99. netbsd_submit_transfer,
  100. netbsd_cancel_transfer,
  101. netbsd_clear_transfer_priv,
  102. netbsd_handle_events,
  103. netbsd_clock_gettime,
  104. sizeof(struct device_priv),
  105. sizeof(struct handle_priv),
  106. 0, /* transfer_priv_size */
  107. 0, /* add_iso_packet_size */
  108. };
  109. int
  110. netbsd_get_device_list(struct libusb_context * ctx,
  111. struct discovered_devs **discdevs)
  112. {
  113. struct libusb_device *dev;
  114. struct device_priv *dpriv;
  115. struct usb_device_info di;
  116. unsigned long session_id;
  117. char devnode[16];
  118. int fd, err, i;
  119. usbi_dbg("");
  120. /* Only ugen(4) is supported */
  121. for (i = 0; i < USB_MAX_DEVICES; i++) {
  122. /* Control endpoint is always .00 */
  123. snprintf(devnode, sizeof(devnode), "/dev/ugen%d.00", i);
  124. if ((fd = open(devnode, O_RDONLY)) < 0) {
  125. if (errno != ENOENT && errno != ENXIO)
  126. usbi_err(ctx, "could not open %s", devnode);
  127. continue;
  128. }
  129. if (ioctl(fd, USB_GET_DEVICEINFO, &di) < 0)
  130. continue;
  131. session_id = (di.udi_bus << 8 | di.udi_addr);
  132. dev = usbi_get_device_by_session_id(ctx, session_id);
  133. if (dev) {
  134. dev = libusb_ref_device(dev);
  135. } else {
  136. dev = usbi_alloc_device(ctx, session_id);
  137. if (dev == NULL)
  138. return (LIBUSB_ERROR_NO_MEM);
  139. dev->bus_number = di.udi_bus;
  140. dev->device_address = di.udi_addr;
  141. dev->speed = di.udi_speed;
  142. dpriv = (struct device_priv *)dev->os_priv;
  143. strlcpy(dpriv->devnode, devnode, sizeof(devnode));
  144. dpriv->fd = -1;
  145. if (ioctl(fd, USB_GET_DEVICE_DESC, &dpriv->ddesc) < 0) {
  146. err = errno;
  147. goto error;
  148. }
  149. dpriv->cdesc = NULL;
  150. if (_cache_active_config_descriptor(dev, fd)) {
  151. err = errno;
  152. goto error;
  153. }
  154. if ((err = usbi_sanitize_device(dev)))
  155. goto error;
  156. }
  157. close(fd);
  158. if (discovered_devs_append(*discdevs, dev) == NULL)
  159. return (LIBUSB_ERROR_NO_MEM);
  160. libusb_unref_device(dev);
  161. }
  162. return (LIBUSB_SUCCESS);
  163. error:
  164. close(fd);
  165. libusb_unref_device(dev);
  166. return _errno_to_libusb(err);
  167. }
  168. int
  169. netbsd_open(struct libusb_device_handle *handle)
  170. {
  171. struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
  172. struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
  173. dpriv->fd = open(dpriv->devnode, O_RDWR);
  174. if (dpriv->fd < 0) {
  175. dpriv->fd = open(dpriv->devnode, O_RDONLY);
  176. if (dpriv->fd < 0)
  177. return _errno_to_libusb(errno);
  178. }
  179. usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd);
  180. if (pipe(hpriv->pipe) < 0)
  181. return _errno_to_libusb(errno);
  182. return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN);
  183. }
  184. void
  185. netbsd_close(struct libusb_device_handle *handle)
  186. {
  187. struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
  188. struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
  189. usbi_dbg("close: fd %d", dpriv->fd);
  190. close(dpriv->fd);
  191. dpriv->fd = -1;
  192. usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
  193. close(hpriv->pipe[0]);
  194. close(hpriv->pipe[1]);
  195. }
  196. int
  197. netbsd_get_device_descriptor(struct libusb_device *dev, unsigned char *buf,
  198. int *host_endian)
  199. {
  200. struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
  201. usbi_dbg("");
  202. memcpy(buf, &dpriv->ddesc, DEVICE_DESC_LENGTH);
  203. *host_endian = 0;
  204. return (LIBUSB_SUCCESS);
  205. }
  206. int
  207. netbsd_get_active_config_descriptor(struct libusb_device *dev,
  208. unsigned char *buf, size_t len, int *host_endian)
  209. {
  210. struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
  211. usb_config_descriptor_t *ucd;
  212. ucd = (usb_config_descriptor_t *) dpriv->cdesc;
  213. len = MIN(len, UGETW(ucd->wTotalLength));
  214. usbi_dbg("len %d", len);
  215. memcpy(buf, dpriv->cdesc, len);
  216. *host_endian = 0;
  217. return len;
  218. }
  219. int
  220. netbsd_get_config_descriptor(struct libusb_device *dev, uint8_t idx,
  221. unsigned char *buf, size_t len, int *host_endian)
  222. {
  223. struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
  224. struct usb_full_desc ufd;
  225. int fd, err;
  226. usbi_dbg("index %d, len %d", idx, len);
  227. /* A config descriptor may be requested before opening the device */
  228. if (dpriv->fd >= 0) {
  229. fd = dpriv->fd;
  230. } else {
  231. fd = open(dpriv->devnode, O_RDONLY);
  232. if (fd < 0)
  233. return _errno_to_libusb(errno);
  234. }
  235. ufd.ufd_config_index = idx;
  236. ufd.ufd_size = len;
  237. ufd.ufd_data = buf;
  238. if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
  239. err = errno;
  240. if (dpriv->fd < 0)
  241. close(fd);
  242. return _errno_to_libusb(err);
  243. }
  244. if (dpriv->fd < 0)
  245. close(fd);
  246. *host_endian = 0;
  247. return len;
  248. }
  249. int
  250. netbsd_get_configuration(struct libusb_device_handle *handle, int *config)
  251. {
  252. struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
  253. usbi_dbg("");
  254. if (ioctl(dpriv->fd, USB_GET_CONFIG, config) < 0)
  255. return _errno_to_libusb(errno);
  256. usbi_dbg("configuration %d", *config);
  257. return (LIBUSB_SUCCESS);
  258. }
  259. int
  260. netbsd_set_configuration(struct libusb_device_handle *handle, int config)
  261. {
  262. struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
  263. usbi_dbg("configuration %d", config);
  264. if (ioctl(dpriv->fd, USB_SET_CONFIG, &config) < 0)
  265. return _errno_to_libusb(errno);
  266. return _cache_active_config_descriptor(handle->dev, dpriv->fd);
  267. }
  268. int
  269. netbsd_claim_interface(struct libusb_device_handle *handle, int iface)
  270. {
  271. struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
  272. int i;
  273. for (i = 0; i < USB_MAX_ENDPOINTS; i++)
  274. hpriv->endpoints[i] = -1;
  275. return (LIBUSB_SUCCESS);
  276. }
  277. int
  278. netbsd_release_interface(struct libusb_device_handle *handle, int iface)
  279. {
  280. struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv;
  281. int i;
  282. for (i = 0; i < USB_MAX_ENDPOINTS; i++)
  283. if (hpriv->endpoints[i] >= 0)
  284. close(hpriv->endpoints[i]);
  285. return (LIBUSB_SUCCESS);
  286. }
  287. int
  288. netbsd_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
  289. int altsetting)
  290. {
  291. struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
  292. struct usb_alt_interface intf;
  293. usbi_dbg("iface %d, setting %d", iface, altsetting);
  294. memset(&intf, 0, sizeof(intf));
  295. intf.uai_interface_index = iface;
  296. intf.uai_alt_no = altsetting;
  297. if (ioctl(dpriv->fd, USB_SET_ALTINTERFACE, &intf) < 0)
  298. return _errno_to_libusb(errno);
  299. return (LIBUSB_SUCCESS);
  300. }
  301. int
  302. netbsd_clear_halt(struct libusb_device_handle *handle, unsigned char endpoint)
  303. {
  304. struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv;
  305. struct usb_ctl_request req;
  306. usbi_dbg("");
  307. req.ucr_request.bmRequestType = UT_WRITE_ENDPOINT;
  308. req.ucr_request.bRequest = UR_CLEAR_FEATURE;
  309. USETW(req.ucr_request.wValue, UF_ENDPOINT_HALT);
  310. USETW(req.ucr_request.wIndex, endpoint);
  311. USETW(req.ucr_request.wLength, 0);
  312. if (ioctl(dpriv->fd, USB_DO_REQUEST, &req) < 0)
  313. return _errno_to_libusb(errno);
  314. return (LIBUSB_SUCCESS);
  315. }
  316. int
  317. netbsd_reset_device(struct libusb_device_handle *handle)
  318. {
  319. usbi_dbg("");
  320. return (LIBUSB_ERROR_NOT_SUPPORTED);
  321. }
  322. void
  323. netbsd_destroy_device(struct libusb_device *dev)
  324. {
  325. struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
  326. usbi_dbg("");
  327. free(dpriv->cdesc);
  328. }
  329. int
  330. netbsd_submit_transfer(struct usbi_transfer *itransfer)
  331. {
  332. struct libusb_transfer *transfer;
  333. struct handle_priv *hpriv;
  334. int err = 0;
  335. usbi_dbg("");
  336. transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  337. hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
  338. switch (transfer->type) {
  339. case LIBUSB_TRANSFER_TYPE_CONTROL:
  340. err = _sync_control_transfer(itransfer);
  341. break;
  342. case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
  343. if (IS_XFEROUT(transfer)) {
  344. /* Isochronous write is not supported */
  345. err = LIBUSB_ERROR_NOT_SUPPORTED;
  346. break;
  347. }
  348. err = _sync_gen_transfer(itransfer);
  349. break;
  350. case LIBUSB_TRANSFER_TYPE_BULK:
  351. case LIBUSB_TRANSFER_TYPE_INTERRUPT:
  352. if (IS_XFEROUT(transfer) &&
  353. transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
  354. err = LIBUSB_ERROR_NOT_SUPPORTED;
  355. break;
  356. }
  357. err = _sync_gen_transfer(itransfer);
  358. break;
  359. }
  360. if (err)
  361. return (err);
  362. if (write(hpriv->pipe[1], &itransfer, sizeof(itransfer)) < 0)
  363. return _errno_to_libusb(errno);
  364. return (LIBUSB_SUCCESS);
  365. }
  366. int
  367. netbsd_cancel_transfer(struct usbi_transfer *itransfer)
  368. {
  369. usbi_dbg("");
  370. return (LIBUSB_ERROR_NOT_SUPPORTED);
  371. }
  372. void
  373. netbsd_clear_transfer_priv(struct usbi_transfer *itransfer)
  374. {
  375. usbi_dbg("");
  376. /* Nothing to do */
  377. }
  378. int
  379. netbsd_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds_t nfds,
  380. int num_ready)
  381. {
  382. struct libusb_device_handle *handle;
  383. struct handle_priv *hpriv = NULL;
  384. struct usbi_transfer *itransfer;
  385. struct pollfd *pollfd;
  386. int i, err = 0;
  387. usbi_dbg("");
  388. pthread_mutex_lock(&ctx->open_devs_lock);
  389. for (i = 0; i < nfds && num_ready > 0; i++) {
  390. pollfd = &fds[i];
  391. if (!pollfd->revents)
  392. continue;
  393. hpriv = NULL;
  394. num_ready--;
  395. list_for_each_entry(handle, &ctx->open_devs, list,
  396. struct libusb_device_handle) {
  397. hpriv = (struct handle_priv *)handle->os_priv;
  398. if (hpriv->pipe[0] == pollfd->fd)
  399. break;
  400. hpriv = NULL;
  401. }
  402. if (NULL == hpriv) {
  403. usbi_dbg("fd %d is not an event pipe!", pollfd->fd);
  404. err = ENOENT;
  405. break;
  406. }
  407. if (pollfd->revents & POLLERR) {
  408. usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]);
  409. usbi_handle_disconnect(handle);
  410. continue;
  411. }
  412. if (read(hpriv->pipe[0], &itransfer, sizeof(itransfer)) < 0) {
  413. err = errno;
  414. break;
  415. }
  416. if ((err = usbi_handle_transfer_completion(itransfer,
  417. LIBUSB_TRANSFER_COMPLETED)))
  418. break;
  419. }
  420. pthread_mutex_unlock(&ctx->open_devs_lock);
  421. if (err)
  422. return _errno_to_libusb(err);
  423. return (LIBUSB_SUCCESS);
  424. }
  425. int
  426. netbsd_clock_gettime(int clkid, struct timespec *tp)
  427. {
  428. usbi_dbg("clock %d", clkid);
  429. if (clkid == USBI_CLOCK_REALTIME)
  430. return clock_gettime(CLOCK_REALTIME, tp);
  431. if (clkid == USBI_CLOCK_MONOTONIC)
  432. return clock_gettime(CLOCK_MONOTONIC, tp);
  433. return (LIBUSB_ERROR_INVALID_PARAM);
  434. }
  435. int
  436. _errno_to_libusb(int err)
  437. {
  438. switch (err) {
  439. case EIO:
  440. return (LIBUSB_ERROR_IO);
  441. case EACCES:
  442. return (LIBUSB_ERROR_ACCESS);
  443. case ENOENT:
  444. return (LIBUSB_ERROR_NO_DEVICE);
  445. case ENOMEM:
  446. return (LIBUSB_ERROR_NO_MEM);
  447. }
  448. usbi_dbg("error: %s", strerror(err));
  449. return (LIBUSB_ERROR_OTHER);
  450. }
  451. int
  452. _cache_active_config_descriptor(struct libusb_device *dev, int fd)
  453. {
  454. struct device_priv *dpriv = (struct device_priv *)dev->os_priv;
  455. struct usb_config_desc ucd;
  456. struct usb_full_desc ufd;
  457. unsigned char* buf;
  458. int len;
  459. usbi_dbg("fd %d", fd);
  460. ucd.ucd_config_index = USB_CURRENT_CONFIG_INDEX;
  461. if ((ioctl(fd, USB_GET_CONFIG_DESC, &ucd)) < 0)
  462. return _errno_to_libusb(errno);
  463. usbi_dbg("active bLength %d", ucd.ucd_desc.bLength);
  464. len = UGETW(ucd.ucd_desc.wTotalLength);
  465. buf = malloc(len);
  466. if (buf == NULL)
  467. return (LIBUSB_ERROR_NO_MEM);
  468. ufd.ufd_config_index = ucd.ucd_config_index;
  469. ufd.ufd_size = len;
  470. ufd.ufd_data = buf;
  471. usbi_dbg("index %d, len %d", ufd.ufd_config_index, len);
  472. if ((ioctl(fd, USB_GET_FULL_DESC, &ufd)) < 0) {
  473. free(buf);
  474. return _errno_to_libusb(errno);
  475. }
  476. if (dpriv->cdesc)
  477. free(dpriv->cdesc);
  478. dpriv->cdesc = buf;
  479. return (0);
  480. }
  481. int
  482. _sync_control_transfer(struct usbi_transfer *itransfer)
  483. {
  484. struct libusb_transfer *transfer;
  485. struct libusb_control_setup *setup;
  486. struct device_priv *dpriv;
  487. struct usb_ctl_request req;
  488. transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  489. dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
  490. setup = (struct libusb_control_setup *)transfer->buffer;
  491. usbi_dbg("type %d request %d value %d index %d length %d timeout %d",
  492. setup->bmRequestType, setup->bRequest,
  493. libusb_le16_to_cpu(setup->wValue),
  494. libusb_le16_to_cpu(setup->wIndex),
  495. libusb_le16_to_cpu(setup->wLength), transfer->timeout);
  496. req.ucr_request.bmRequestType = setup->bmRequestType;
  497. req.ucr_request.bRequest = setup->bRequest;
  498. /* Don't use USETW, libusbx already deals with the endianness */
  499. (*(uint16_t *)req.ucr_request.wValue) = setup->wValue;
  500. (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex;
  501. (*(uint16_t *)req.ucr_request.wLength) = setup->wLength;
  502. req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
  503. if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
  504. req.ucr_flags = USBD_SHORT_XFER_OK;
  505. if ((ioctl(dpriv->fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
  506. return _errno_to_libusb(errno);
  507. if ((ioctl(dpriv->fd, USB_DO_REQUEST, &req)) < 0)
  508. return _errno_to_libusb(errno);
  509. itransfer->transferred = req.ucr_actlen;
  510. usbi_dbg("transferred %d", itransfer->transferred);
  511. return (0);
  512. }
  513. int
  514. _access_endpoint(struct libusb_transfer *transfer)
  515. {
  516. struct handle_priv *hpriv;
  517. struct device_priv *dpriv;
  518. char *s, devnode[16];
  519. int fd, endpt;
  520. mode_t mode;
  521. hpriv = (struct handle_priv *)transfer->dev_handle->os_priv;
  522. dpriv = (struct device_priv *)transfer->dev_handle->dev->os_priv;
  523. endpt = UE_GET_ADDR(transfer->endpoint);
  524. mode = IS_XFERIN(transfer) ? O_RDONLY : O_WRONLY;
  525. usbi_dbg("endpoint %d mode %d", endpt, mode);
  526. if (hpriv->endpoints[endpt] < 0) {
  527. /* Pick the right node given the control one */
  528. strlcpy(devnode, dpriv->devnode, sizeof(devnode));
  529. s = strchr(devnode, '.');
  530. snprintf(s, 4, ".%02d", endpt);
  531. /* We may need to read/write to the same endpoint later. */
  532. if (((fd = open(devnode, O_RDWR)) < 0) && (errno == ENXIO))
  533. if ((fd = open(devnode, mode)) < 0)
  534. return (-1);
  535. hpriv->endpoints[endpt] = fd;
  536. }
  537. return (hpriv->endpoints[endpt]);
  538. }
  539. int
  540. _sync_gen_transfer(struct usbi_transfer *itransfer)
  541. {
  542. struct libusb_transfer *transfer;
  543. int fd, nr = 1;
  544. transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
  545. /*
  546. * Bulk, Interrupt or Isochronous transfer depends on the
  547. * endpoint and thus the node to open.
  548. */
  549. if ((fd = _access_endpoint(transfer)) < 0)
  550. return _errno_to_libusb(errno);
  551. if ((ioctl(fd, USB_SET_TIMEOUT, &transfer->timeout)) < 0)
  552. return _errno_to_libusb(errno);
  553. if (IS_XFERIN(transfer)) {
  554. if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0)
  555. if ((ioctl(fd, USB_SET_SHORT_XFER, &nr)) < 0)
  556. return _errno_to_libusb(errno);
  557. nr = read(fd, transfer->buffer, transfer->length);
  558. } else {
  559. nr = write(fd, transfer->buffer, transfer->length);
  560. }
  561. if (nr < 0)
  562. return _errno_to_libusb(errno);
  563. itransfer->transferred = nr;
  564. return (0);
  565. }