core: Add debug statements to help trace transfers
[platform/upstream/libusb.git] / libusb / os / darwin_usb.c
index dc80281..19174b1 100644 (file)
@@ -1,7 +1,7 @@
 /* -*- 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
@@ -151,7 +151,7 @@ static void darwin_ref_cached_device(struct darwin_cached_device *cached_dev) {
   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 */
@@ -168,8 +168,14 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
       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;
         }
       }
@@ -179,7 +185,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
   /* 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) {
@@ -278,6 +284,8 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
   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);
@@ -285,8 +293,6 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
     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);
 
@@ -298,9 +304,20 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
         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) {
@@ -1121,7 +1138,7 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
 
     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;
@@ -1293,22 +1310,18 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand
 }
 
 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)
@@ -1422,24 +1435,21 @@ static void darwin_destroy_device(struct libusb_device *dev) {
 
 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);
 
@@ -1486,19 +1496,16 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
 #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))
@@ -1521,10 +1528,9 @@ static int submit_stream_transfer(struct usbi_transfer *itransfer) {
 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;
@@ -1550,14 +1556,12 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
     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);
@@ -1612,7 +1616,6 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
   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;
@@ -1637,16 +1640,14 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
 
   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 */
@@ -1700,19 +1701,16 @@ static int cancel_control_transfer(struct usbi_transfer *itransfer) {
 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;
 
@@ -1772,10 +1770,9 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0)
   /* 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);
   }
@@ -1909,20 +1906,17 @@ static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
 #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;
@@ -1934,9 +1928,7 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
 
   /* 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)
@@ -1947,18 +1939,15 @@ static int darwin_alloc_streams (struct libusb_device_handle *dev_handle, uint32
 }
 
 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;
@@ -1968,7 +1957,7 @@ static int darwin_free_streams (struct libusb_device_handle *dev_handle, unsigne
       return darwin_to_libusb(rc);
   }
 
-  return LIBUSB_SUCCESS;;
+  return LIBUSB_SUCCESS;
 }
 #endif
 
@@ -1981,6 +1970,7 @@ const struct usbi_os_backend darwin_backend = {
         .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,