openbsd_usb.c 17 KB

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