Index: devel/libusb1/distinfo =================================================================== RCS file: /cvsroot/pkgsrc/devel/libusb1/distinfo,v retrieving revision 1.6 diff -p -u -r1.6 distinfo --- devel/libusb1/distinfo 3 Nov 2015 03:27:46 -0000 1.6 +++ devel/libusb1/distinfo 2 Apr 2016 23:25:54 -0000 @@ -1,4 +1,4 @@ -$NetBSD: distinfo,v 1.6 2015/11/03 03:27:46 agc Exp $ +$NetBSD$ SHA1 (libusb-1.0.19.tar.bz2) = c5d14ced155233ceeb5107c7eb3b94b16649ae05 RMD160 (libusb-1.0.19.tar.bz2) = 0b6818be6bb2c36628ad22e332c39dcab6c762b9 @@ -6,3 +6,4 @@ SHA512 (libusb-1.0.19.tar.bz2) = f42f018 Size (libusb-1.0.19.tar.bz2) = 521496 bytes SHA1 (patch-configure) = bef1f2108e35aa5cbddd25857dff25cdb9065388 SHA1 (patch-configure.ac) = 1cc779623ce05635d8ce8fde03fde3fbeef1ce84 +SHA1 (patch-libusb_os_netbsd__usb.c) = fbf658250ba0a0481bf5223d2ceb8cf38c729985 Index: devel/libusb1/patches/patch-libusb_os_netbsd__usb.c =================================================================== RCS file: devel/libusb1/patches/patch-libusb_os_netbsd__usb.c diff -N devel/libusb1/patches/patch-libusb_os_netbsd__usb.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ devel/libusb1/patches/patch-libusb_os_netbsd__usb.c 2 Apr 2016 23:25:54 -0000 @@ -0,0 +1,311 @@ +$NetBSD$ + +Support asynchronous transfers by doing each one in a new thread. + +This is expensive, but there does not appear to be a good alternative +with NetBSD's ugen(4) as is. + +--- libusb/os/netbsd_usb.c.orig 2014-04-22 12:31:42.000000000 +0000 ++++ libusb/os/netbsd_usb.c +@@ -21,6 +21,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -42,6 +43,13 @@ struct device_priv { + struct handle_priv { + int pipe[2]; /* for event notification */ + int endpoints[USB_MAX_ENDPOINTS]; ++ pthread_mutex_t lock; /* serialize endpoints */ ++}; ++ ++struct transfer_priv { ++ pthread_t thread; ++ int (*transfer_method)(struct usbi_transfer *); ++ enum libusb_transfer_status status; + }; + + /* +@@ -86,6 +94,9 @@ static int _cache_active_config_descript + static int _sync_control_transfer(struct usbi_transfer *); + static int _sync_gen_transfer(struct usbi_transfer *); + static int _access_endpoint(struct libusb_transfer *); ++static int _async_transfer(struct usbi_transfer *, ++ int (*)(struct usbi_transfer *)); ++static void *_async_transfer_thread(void *); + + const struct usbi_os_backend netbsd_backend = { + "Synchronous NetBSD backend", +@@ -130,7 +141,7 @@ const struct usbi_os_backend netbsd_back + netbsd_clock_gettime, + sizeof(struct device_priv), + sizeof(struct handle_priv), +- 0, /* transfer_priv_size */ ++ sizeof(struct transfer_priv), + 0, /* add_iso_packet_size */ + }; + +@@ -212,20 +223,44 @@ netbsd_open(struct libusb_device_handle + { + struct handle_priv *hpriv = (struct handle_priv *)handle->os_priv; + struct device_priv *dpriv = (struct device_priv *)handle->dev->os_priv; ++ int err, ptherr; + + dpriv->fd = open(dpriv->devnode, O_RDWR); + if (dpriv->fd < 0) { + dpriv->fd = open(dpriv->devnode, O_RDONLY); +- if (dpriv->fd < 0) +- return _errno_to_libusb(errno); ++ if (dpriv->fd < 0) { ++ err = _errno_to_libusb(errno); ++ goto fail0; ++ } + } + + usbi_dbg("open %s: fd %d", dpriv->devnode, dpriv->fd); + +- if (pipe(hpriv->pipe) < 0) +- return _errno_to_libusb(errno); ++ if (pipe(hpriv->pipe) < 0) { ++ err = _errno_to_libusb(errno); ++ goto fail1; ++ } ++ ++ ptherr = pthread_mutex_init(&hpriv->lock, NULL); ++ if (ptherr) { ++ err = _errno_to_libusb(ptherr); ++ goto fail2; ++ } ++ ++ err = usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN); ++ if (err) ++ goto fail3; ++ ++ return (0); + +- return usbi_add_pollfd(HANDLE_CTX(handle), hpriv->pipe[0], POLLIN); ++fail3: pthread_mutex_destroy(&hpriv->lock); ++fail2: close(hpriv->pipe[0]); ++ close(hpriv->pipe[1]); ++ hpriv->pipe[0] = -1; ++ hpriv->pipe[1] = -1; ++fail1: close(dpriv->fd); ++ dpriv->fd = -1; ++fail0: return (err); + } + + void +@@ -236,13 +271,17 @@ netbsd_close(struct libusb_device_handle + + usbi_dbg("close: fd %d", dpriv->fd); + +- close(dpriv->fd); +- dpriv->fd = -1; +- + usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->pipe[0]); + ++ pthread_mutex_destroy(&hpriv->lock); ++ + close(hpriv->pipe[0]); + close(hpriv->pipe[1]); ++ hpriv->pipe[0] = -1; ++ hpriv->pipe[1] = -1; ++ ++ close(dpriv->fd); ++ dpriv->fd = -1; + } + + int +@@ -442,7 +481,7 @@ netbsd_submit_transfer(struct usbi_trans + + switch (transfer->type) { + case LIBUSB_TRANSFER_TYPE_CONTROL: +- err = _sync_control_transfer(itransfer); ++ err = _async_transfer(itransfer, _sync_control_transfer); + break; + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + if (IS_XFEROUT(transfer)) { +@@ -450,7 +489,7 @@ netbsd_submit_transfer(struct usbi_trans + err = LIBUSB_ERROR_NOT_SUPPORTED; + break; + } +- err = _sync_gen_transfer(itransfer); ++ err = _async_transfer(itransfer, _sync_gen_transfer); + break; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: +@@ -459,7 +498,7 @@ netbsd_submit_transfer(struct usbi_trans + err = LIBUSB_ERROR_NOT_SUPPORTED; + break; + } +- err = _sync_gen_transfer(itransfer); ++ err = _async_transfer(itransfer, _sync_gen_transfer); + break; + case LIBUSB_TRANSFER_TYPE_BULK_STREAM: + err = LIBUSB_ERROR_NOT_SUPPORTED; +@@ -469,9 +508,6 @@ netbsd_submit_transfer(struct usbi_trans + if (err) + return (err); + +- if (write(hpriv->pipe[1], &itransfer, sizeof(itransfer)) < 0) +- return _errno_to_libusb(errno); +- + return (LIBUSB_SUCCESS); + } + +@@ -498,6 +534,7 @@ netbsd_handle_events(struct libusb_conte + struct libusb_device_handle *handle; + struct handle_priv *hpriv = NULL; + struct usbi_transfer *itransfer; ++ struct transfer_priv *tpriv; + struct pollfd *pollfd; + int i, err = 0; + +@@ -524,7 +561,7 @@ netbsd_handle_events(struct libusb_conte + + if (NULL == hpriv) { + usbi_dbg("fd %d is not an event pipe!", pollfd->fd); +- err = ENOENT; ++ err = _errno_to_libusb(ENOENT); + break; + } + +@@ -535,20 +572,18 @@ netbsd_handle_events(struct libusb_conte + } + + if (read(hpriv->pipe[0], &itransfer, sizeof(itransfer)) < 0) { +- err = errno; ++ err = _errno_to_libusb(errno); + break; + } + ++ tpriv = usbi_transfer_get_os_priv(itransfer); + if ((err = usbi_handle_transfer_completion(itransfer, +- LIBUSB_TRANSFER_COMPLETED))) ++ tpriv->status)) != 0) + break; + } + pthread_mutex_unlock(&ctx->open_devs_lock); + +- if (err) +- return _errno_to_libusb(err); +- +- return (LIBUSB_SUCCESS); ++ return (err); + } + + int +@@ -625,7 +660,7 @@ _cache_active_config_descriptor(struct l + return (0); + } + +-int ++static int + _sync_control_transfer(struct usbi_transfer *itransfer) + { + struct libusb_transfer *transfer; +@@ -646,9 +681,9 @@ _sync_control_transfer(struct usbi_trans + req.ucr_request.bmRequestType = setup->bmRequestType; + req.ucr_request.bRequest = setup->bRequest; + /* Don't use USETW, libusb already deals with the endianness */ +- (*(uint16_t *)req.ucr_request.wValue) = setup->wValue; +- (*(uint16_t *)req.ucr_request.wIndex) = setup->wIndex; +- (*(uint16_t *)req.ucr_request.wLength) = setup->wLength; ++ memcpy(req.ucr_request.wValue, &setup->wValue, 2); ++ memcpy(req.ucr_request.wIndex, &setup->wIndex, 2); ++ memcpy(req.ucr_request.wLength, &setup->wLength, 2); + req.ucr_data = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; + + if ((transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) == 0) +@@ -684,6 +719,10 @@ _access_endpoint(struct libusb_transfer + + usbi_dbg("endpoint %d mode %d", endpt, mode); + ++ if (hpriv->endpoints[endpt] >= 0) ++ return hpriv->endpoints[endpt]; ++ ++ pthread_mutex_lock(&hpriv->lock); + if (hpriv->endpoints[endpt] < 0) { + /* Pick the right node given the control one */ + strlcpy(devnode, dpriv->devnode, sizeof(devnode)); +@@ -697,11 +736,12 @@ _access_endpoint(struct libusb_transfer + + hpriv->endpoints[endpt] = fd; + } ++ pthread_mutex_unlock(&hpriv->lock); + + return (hpriv->endpoints[endpt]); + } + +-int ++static int + _sync_gen_transfer(struct usbi_transfer *itransfer) + { + struct libusb_transfer *transfer; +@@ -736,3 +776,63 @@ _sync_gen_transfer(struct usbi_transfer + + return (0); + } ++ ++static int ++_async_transfer(struct usbi_transfer *itransfer, ++ int (*transfer_method)(struct usbi_transfer *)) ++{ ++ pthread_attr_t attr; ++ struct transfer_priv *tpriv; ++ int ptherr; ++ ++ tpriv = usbi_transfer_get_os_priv(itransfer); ++ ++ /* Create a thread to do the transfer. */ ++ tpriv->transfer_method = transfer_method; ++ ptherr = pthread_attr_init(&attr); ++ if (ptherr) ++ goto fail0; ++ ptherr = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); ++ if (ptherr) ++ goto fail1; ++ ptherr = pthread_create(&tpriv->thread, &attr, _async_transfer_thread, ++ itransfer); ++ if (ptherr) ++ goto fail1; ++ ++ /* Success! */ ++ pthread_attr_destroy(&attr); ++ return (0); ++ ++fail1: pthread_attr_destroy(&attr); ++fail0: return _errno_to_libusb(ptherr); ++} ++ ++static void * ++_async_transfer_thread(void *cookie) ++{ ++ struct usbi_transfer *itransfer = cookie; ++ struct libusb_transfer *transfer; ++ struct transfer_priv *tpriv; ++ struct handle_priv *hpriv; ++ int err; ++ ++ transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); ++ tpriv = usbi_transfer_get_os_priv(itransfer); ++ hpriv = (struct handle_priv *)transfer->dev_handle->os_priv; ++ ++ /* Attempt the transfer. */ ++ err = (*tpriv->transfer_method)(itransfer); ++ if (err) { ++ tpriv->status = LIBUSB_TRANSFER_ERROR; ++ goto out; ++ } ++ tpriv->status = LIBUSB_TRANSFER_COMPLETED; ++ ++out: ++ /* Can't do anything if this fails. */ ++ if (write(hpriv->pipe[1], &itransfer, sizeof(itransfer)) < 0) ++ usbi_err(TRANSFER_CTX(transfer), "write failed (%d): %s", ++ errno, strerror(errno)); ++ return (NULL); ++}