--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -288,13 +288,21 @@ struct libusb_device_handle {
 	unsigned char os_priv[0];
 };
 
-#define USBI_TRANSFER_TIMED_OUT	 			(1<<0)
-
 enum {
   USBI_CLOCK_MONOTONIC,
   USBI_CLOCK_REALTIME
 };
 
+/* flags for struct usbi_transfer:
+ *  USBI_TRANSFER_TIMED_OUT
+ *  USBI_TRANSFER_OS_HANDLES_TIMEOUT - set in the backend submit_transfer if the os will handle the timeout
+ */
+enum {
+  USBI_TRANSFER_TIMED_OUT          = (1 << 0),
+  USBI_TRANSFER_OS_HANDLES_TIMEOUT = (1 << 1)
+};
+
+
 /* in-memory transfer layout:
  *
  * 1. struct usbi_transfer
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c
index 646c938..79ba6c6 100644
--- a/libusb/os/darwin_usb.c
+++ b/libusb/os/darwin_usb.c
@@ -1137,6 +1137,8 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
       ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer,
 						       transfer->length, darwin_async_io_callback, itransfer);
   } else {
+    itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
+  
     if (is_read)
       ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
 							transfer->length, transfer->timeout, transfer->timeout,
@@ -1171,10 +1173,19 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
   /* are we reading or writing? */
   is_read = transfer->endpoint & LIBUSB_ENDPOINT_IN;
 
-  /* construct an array of IOUSBIsocFrames */
-  tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame));
-  if (!tpriv->isoc_framelist)
-    return LIBUSB_ERROR_NO_MEM;
+  /* construct an array of IOUSBIsocFrames, reuse the old one if possible */
+  if (tpriv->isoc_framelist != NULL && tpriv->num_iso_packets != transfer->num_iso_packets)
+  {
+    free(tpriv->isoc_framelist);
+    tpriv->isoc_framelist = NULL;
+  }
+  if (tpriv->isoc_framelist == NULL)
+  {
+    tpriv->isoc_framelist = (IOUSBIsocFrame*) calloc (transfer->num_iso_packets, sizeof(IOUSBIsocFrame));
+    tpriv->num_iso_packets = transfer->num_iso_packets;
+    if (!tpriv->isoc_framelist)
+      return LIBUSB_ERROR_NO_MEM;
+  }
 
   /* copy the frame list from the libusb descriptor (the structures differ only is member order) */
   for (i = 0 ; i < transfer->num_iso_packets ; i++)
@@ -1198,9 +1209,11 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
 
     return darwin_to_libusb (kresult);
   }
-
   /* schedule for a frame a little in the future */
-  frame += 2;
+  frame += 4;
+
+  if(cInterface->frames[transfer->endpoint] && frame < cInterface->frames[transfer->endpoint])
+    frame = cInterface->frames[transfer->endpoint];
 
   /* submit the request */
   if (is_read)
@@ -1211,6 +1224,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
     kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
 							      transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
 							      itransfer);
+  cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets / 8;
 
   if (kresult != kIOReturnSuccess) {
     usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", is_read ? "In" : "Out",
@@ -1243,6 +1257,8 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) {
   tpriv->req.pData             = transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE;
   tpriv->req.completionTimeout = transfer->timeout;
   tpriv->req.noDataTimeout     = transfer->timeout;
+  
+  itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
 
   /* all transfers in libusb-1.0 are async */
   kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer);
@@ -1358,6 +1374,9 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0)
 }
 
 static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) {
+	if (itransfer->flags & USBI_TRANSFER_TIMED_OUT)
+		result = kIOUSBTransactionTimeout;
+		
   switch (result) {
   case kIOReturnUnderrun:
   case kIOReturnSuccess:
@@ -1372,6 +1391,7 @@ static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_
     return LIBUSB_TRANSFER_OVERFLOW;
   case kIOUSBTransactionTimeout:
     usbi_err (ITRANSFER_CTX (itransfer), "transfer error: timed out");
+	itransfer->flags |= USBI_TRANSFER_TIMED_OUT;
     return LIBUSB_TRANSFER_TIMED_OUT;
   default:
     usbi_err (ITRANSFER_CTX (itransfer), "transfer error: %s (value = 0x%08x)", darwin_error_str (result), result);
diff --git a/libusb/os/darwin_usb.h b/libusb/os/darwin_usb.h
index a71d464..4aadf8c 100644
--- a/libusb/os/darwin_usb.h
+++ b/libusb/os/darwin_usb.h
@@ -139,6 +139,7 @@ struct darwin_device_handle_priv {
     usb_interface_t    **interface;
     uint8_t              num_endpoints;
     CFRunLoopSourceRef   cfSource;
+    UInt64               frames[256];
     uint8_t            endpoint_addrs[USB_MAXENDPOINTS];
   } interfaces[USB_MAXINTERFACES];
 };
@@ -146,6 +147,7 @@ struct darwin_device_handle_priv {
 struct darwin_transfer_priv {
   /* Isoc */
   IOUSBIsocFrame *isoc_framelist;
+  size_t num_iso_packets;
 
   /* Control */
 #if !defined (LIBUSB_NO_TIMEOUT_DEVICE)