/* -*- Mode: C; indent-tabs-mode:nil -*- */
/*
* darwin backend for libusb 1.0
- * Copyright © 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net>
+ * Copyright © 2008-2014 Nathan Hjelm <hjelmn@users.sourceforge.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
cached_dev->refcount++;
}
-static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, uint8_t *pipep, uint8_t *ifcp) {
+static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, uint8_t *pipep, uint8_t *ifcp, struct darwin_interface **interface_out) {
struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
/* current interface */
for (i = 0 ; i < cInterface->num_endpoints ; i++) {
if (cInterface->endpoint_addrs[i] == ep) {
*pipep = i + 1;
- *ifcp = iface;
- usbi_dbg ("pipe %d on interface %d matches", *pipep, *ifcp);
+
+ if (ifcp)
+ *ifcp = iface;
+
+ if (interface_out)
+ *interface_out = cInterface;
+
+ usbi_dbg ("pipe %d on interface %d matches", *pipep, iface);
return 0;
}
}
/* No pipe found with the correct endpoint address */
usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep);
- return -1;
+ return LIBUSB_ERROR_NOT_FOUND;
}
static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) {
UInt64 session;
int ret;
+ usbi_mutex_lock(&active_contexts_lock);
+
while ((device = IOIteratorNext (rem_devices)) != 0) {
/* get the location from the i/o registry */
ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
if (!ret)
continue;
- usbi_mutex_lock(&active_contexts_lock);
-
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
usbi_dbg ("notifying context %p of device disconnect", ctx);
libusb_unref_device(dev);
}
}
-
- usbi_mutex_unlock(&active_contexts_lock);
}
+
+ usbi_mutex_unlock(&active_contexts_lock);
+}
+
+static void darwin_hotplug_poll (void)
+{
+ /* not sure if 5 seconds will be too long/short but it should work ok */
+ mach_timespec_t timeout = {.tv_sec = 5, .tv_nsec = 0};
+
+ /* since a kernel thread may nodify the IOInterators used for
+ * hotplug notidication we can't just clear the iterators.
+ * instead just wait until all IOService providers are quiet */
+ (void) IOKitWaitQuiet (kIOMasterPortDefault, &timeout);
}
static void darwin_clear_iterator (io_iterator_t iter) {
usbi_dbg ("interface: %i pipe %i: dir: %i number: %i", iface, i, direction, number);
- cInterface->endpoint_addrs[i - 1] = ((direction << 7 & LIBUSB_ENDPOINT_DIR_MASK) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
+ cInterface->endpoint_addrs[i - 1] = (((kUSBIn == direction) << kUSBRqDirnShift) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK));
}
cInterface->num_endpoints = numep;
}
static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint) {
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
-
/* current interface */
struct darwin_interface *cInterface;
- uint8_t pipeRef, iface;
IOReturn kresult;
+ uint8_t pipeRef;
/* determine the interface/endpoint to use */
- if (ep_to_pipeRef (dev_handle, endpoint, &pipeRef, &iface) != 0) {
+ if (ep_to_pipeRef (dev_handle, endpoint, &pipeRef, NULL, &cInterface) != 0) {
usbi_err (HANDLE_CTX (dev_handle), "endpoint not found on any open interface");
return LIBUSB_ERROR_NOT_FOUND;
}
- cInterface = &priv->interfaces[iface];
-
/* newer versions of darwin support clearing additional bits on the device's endpoint */
kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
if (kresult)
static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv;
IOReturn ret;
uint8_t transferType;
- /* None of the values below are used in libusb for bulk transfers */
- uint8_t direction, number, interval, pipeRef, iface;
+ /* None of the values below are used in libusbx for bulk transfers */
+ uint8_t direction, number, interval, pipeRef;
uint16_t maxPacketSize;
struct darwin_interface *cInterface;
- if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) {
+ if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
return LIBUSB_ERROR_NOT_FOUND;
}
- cInterface = &priv->interfaces[iface];
-
ret = (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
&transferType, &maxPacketSize, &interval);
#if InterfaceVersion >= 550
static int submit_stream_transfer(struct usbi_transfer *itransfer) {
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv;
struct darwin_interface *cInterface;
- uint8_t pipeRef, iface;
+ uint8_t pipeRef;
IOReturn ret;
- if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) {
+ if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
return LIBUSB_ERROR_NOT_FOUND;
}
- cInterface = &priv->interfaces[iface];
-
itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
if (IS_XFERIN(transfer))
static int submit_iso_transfer(struct usbi_transfer *itransfer) {
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv;
IOReturn kresult;
- uint8_t direction, number, interval, pipeRef, iface, transferType;
+ uint8_t direction, number, interval, pipeRef, transferType;
uint16_t maxPacketSize;
UInt64 frame;
AbsoluteTime atTime;
tpriv->isoc_framelist[i].frReqCount = transfer->iso_packet_desc[i].length;
/* determine the interface/endpoint to use */
- if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) {
+ if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
return LIBUSB_ERROR_NOT_FOUND;
}
- cInterface = &priv->interfaces[iface];
-
/* determine the properties of this endpoint and the speed of the device */
(*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
&transferType, &maxPacketSize, &interval);
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer;
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev);
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv;
struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
IOReturn kresult;
if (transfer->endpoint) {
struct darwin_interface *cInterface;
- uint8_t pipeRef, iface;
+ uint8_t pipeRef;
- if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) {
+ if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface) != 0) {
usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
return LIBUSB_ERROR_NOT_FOUND;
}
- cInterface = &priv->interfaces[iface];
-
kresult = (*(cInterface->interface))->ControlRequestAsyncTO (cInterface->interface, pipeRef, &(tpriv->req), darwin_async_io_callback, itransfer);
} else
/* control request on endpoint 0 */
static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev);
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv;
struct darwin_interface *cInterface;
uint8_t pipeRef, iface;
IOReturn kresult;
- if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) {
+ if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface, &cInterface) != 0) {
usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
return LIBUSB_ERROR_NOT_FOUND;
}
- cInterface = &priv->interfaces[iface];
-
if (!dpriv->device)
return LIBUSB_ERROR_NO_DEVICE;
/* if requested write a zero packet */
if (kIOReturnSuccess == result && IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
struct darwin_interface *cInterface;
- uint8_t iface, pipeRef;
+ uint8_t pipeRef;
- (void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface);
- cInterface = &priv->interfaces[iface];
+ (void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, NULL, &cInterface);
(*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0);
}
#if InterfaceVersion >= 550
static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32_t num_streams, unsigned char *endpoints,
int num_endpoints) {
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *) dev_handle->os_priv;
struct darwin_interface *cInterface;
- uint8_t pipeRef, iface;
UInt32 supportsStreams;
+ uint8_t pipeRef;
int rc, i;
/* find the mimimum number of supported streams on the endpoint list */
for (i = 0 ; i < num_endpoints ; ++i) {
- if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, &iface))) {
+ if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface))) {
return rc;
}
- cInterface = &priv->interfaces[iface];
-
(*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams);
if (num_streams > supportsStreams)
num_streams = supportsStreams;
/* create the streams */
for (i = 0 ; i < num_endpoints ; ++i) {
- (void) ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, &iface);
-
- cInterface = &priv->interfaces[iface];
+ (void) ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface);
rc = (*(cInterface->interface))->CreateStreams (cInterface->interface, pipeRef, num_streams);
if (kIOReturnSuccess != rc)
}
static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigned char *endpoints, int num_endpoints) {
- struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *) dev_handle->os_priv;
struct darwin_interface *cInterface;
- uint8_t pipeRef, iface;
UInt32 supportsStreams;
+ uint8_t pipeRef;
int rc;
for (int i = 0 ; i < num_endpoints ; ++i) {
- if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, &iface)))
+ if (0 != (rc = ep_to_pipeRef (dev_handle, endpoints[i], &pipeRef, NULL, &cInterface)))
return rc;
- cInterface = &priv->interfaces[iface];
-
(*(cInterface->interface))->SupportsStreams (cInterface->interface, pipeRef, &supportsStreams);
if (0 == supportsStreams)
return LIBUSB_ERROR_INVALID_PARAM;
return darwin_to_libusb(rc);
}
- return LIBUSB_SUCCESS;;
+ return LIBUSB_SUCCESS;
}
#endif
.get_device_descriptor = darwin_get_device_descriptor,
.get_active_config_descriptor = darwin_get_active_config_descriptor,
.get_config_descriptor = darwin_get_config_descriptor,
+ .hotplug_poll = darwin_hotplug_poll,
.open = darwin_open,
.close = darwin_close,