summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/USB/darwin
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/USB/darwin')
-rw-r--r--src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp120
1 files changed, 98 insertions, 22 deletions
diff --git a/src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp b/src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp
index 79102d08..e8f1a767 100644
--- a/src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp
+++ b/src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -36,6 +36,7 @@
#include <iprt/assert.h>
#include <iprt/critsect.h>
+#include <iprt/list.h>
#include <iprt/mem.h>
#include <iprt/once.h>
#include <iprt/string.h>
@@ -165,6 +166,13 @@ typedef struct USBPROXYPIPEOSX
uint64_t u64NextFrameNo;
} USBPROXYPIPEOSX, *PUSBPROXYPIPEOSX, **PPUSBPROXYPIPEOSX;
+typedef struct RUNLOOPREFLIST
+{
+ RTLISTNODE List;
+ CFRunLoopRef RunLoopRef;
+} RUNLOOPREFLIST, *PRUNLOOPREFLIST;
+typedef RUNLOOPREFLIST **PPRUNLOOPREFLIST;
+
/**
* Per-interface data for the Darwin usb proxy backend.
*/
@@ -191,6 +199,7 @@ typedef struct USBPROXYIFOSX
CFRunLoopSourceRef RunLoopSrcRef;
/** List of isochronous buffer collections.
* These are allocated on demand by the URB queuing routine and then recycled until the interface is destroyed. */
+ RTLISTANCHOR HeadOfRunLoopLst;
PUSBPROXYISOCBUFCOL pIsocBufCols;
} USBPROXYIFOSX, *PUSBPROXYIFOSX, **PPUSBPROXYIFOSX;
/** Pointer to a pointer to an darwin interface. */
@@ -208,9 +217,9 @@ typedef struct USBPROXYDEVOSX
/** The run loop source for the async operations on the device level
* (i.e. the default control pipe stuff). */
CFRunLoopSourceRef RunLoopSrcRef;
- /** The run loop this device and its interfaces send their events to. */
- CFRunLoopRef RunLoopRef;
-
+ /** we want to add and remove RunLoopSourceRefs to run loop's of
+ * every EMT thread participated in USB processing. */
+ RTLISTANCHOR HeadOfRunLoopLst;
/** Pointer to the proxy device instance. */
PUSBPROXYDEV pProxyDev;
@@ -255,7 +264,7 @@ static mach_port_t g_MasterPort = NULL;
* @param pvUser1 NULL, ignored.
* @param pvUser2 NULL, ignored.
*/
-static DECLCALLBACK(int32_t) usbProxyDarwinInitOnce(void *pvUser1, void *pvUser2)
+static DECLCALLBACK(int32_t) usbProxyDarwinInitOnce(void *pvUser1)
{
int rc;
kern_return_t krc = IOMasterPort(MACH_PORT_NULL, &g_MasterPort);
@@ -271,6 +280,65 @@ static DECLCALLBACK(int32_t) usbProxyDarwinInitOnce(void *pvUser1, void *pvUser2
return rc;
}
+/**
+ * Adds Source ref to current run loop and adds it the list of runloops.
+ */
+static int usbProxyDarwinAddRunLoopRef(PRTLISTANCHOR pListHead,
+ CFRunLoopSourceRef SourceRef)
+{
+ AssertPtrReturn(pListHead, VERR_INVALID_PARAMETER);
+ AssertReturn(CFRunLoopSourceIsValid(SourceRef), VERR_INVALID_PARAMETER);
+
+ if (CFRunLoopContainsSource(CFRunLoopGetCurrent(), SourceRef, g_pRunLoopMode))
+ return VINF_SUCCESS;
+
+ /* Add to the list */
+ PRUNLOOPREFLIST pListNode = (PRUNLOOPREFLIST)RTMemAllocZ(sizeof(RUNLOOPREFLIST));
+ if (!pListNode)
+ return VERR_NO_MEMORY;
+
+ pListNode->RunLoopRef = CFRunLoopGetCurrent();
+
+ CFRetain(pListNode->RunLoopRef);
+ CFRetain(SourceRef); /* We want to be aware of releasing */
+
+ CFRunLoopAddSource(pListNode->RunLoopRef, SourceRef, g_pRunLoopMode);
+
+ RTListInit(&pListNode->List);
+
+ RTListAppend((PRTLISTNODE)pListHead, &pListNode->List);
+
+ return VINF_SUCCESS;
+}
+
+
+/*
+ * Removes all source reference from mode of run loop's we've registered them.
+ *
+ */
+static int usbProxyDarwinRemoveSourceRefFromAllRunLoops(PRTLISTANCHOR pHead,
+ CFRunLoopSourceRef SourceRef)
+{
+ AssertPtrReturn(pHead, VERR_INVALID_PARAMETER);
+
+ while (!RTListIsEmpty(pHead))
+ {
+ PRUNLOOPREFLIST pNode = RTListGetFirst(pHead, RUNLOOPREFLIST, List);
+ /* XXX: Should Release Reference? */
+ Assert(CFGetRetainCount(pNode->RunLoopRef));
+
+ CFRunLoopRemoveSource(pNode->RunLoopRef, SourceRef, g_pRunLoopMode);
+ CFRelease(SourceRef);
+ CFRelease(pNode->RunLoopRef);
+
+ RTListNodeRemove(&pNode->List);
+
+ RTMemFree(pNode);
+ }
+
+ return VINF_SUCCESS;
+}
+
/**
* Allocates a Darwin URB request structure.
@@ -616,9 +684,12 @@ static void usbProxyDarwinReleaseAllInterfaces(PUSBPROXYDEVOSX pDevOsX)
if (pIf->RunLoopSrcRef)
{
- CFRunLoopRemoveSource(pDevOsX->RunLoopRef, pIf->RunLoopSrcRef, g_pRunLoopMode);
+ int rc = usbProxyDarwinRemoveSourceRefFromAllRunLoops((PRTLISTANCHOR)&pIf->HeadOfRunLoopLst, pIf->RunLoopSrcRef);
+ AssertRC(rc);
+
CFRelease(pIf->RunLoopSrcRef);
pIf->RunLoopSrcRef = NULL;
+ RTListInit((PRTLISTNODE)&pIf->HeadOfRunLoopLst);
}
while (pIf->pIsocBufCols)
@@ -823,7 +894,9 @@ static int usbProxyDarwinSeizeAllInterfaces(PUSBPROXYDEVOSX pDevOsX, bool fMakeT
irc = (*ppIfI)->CreateInterfaceAsyncEventSource(ppIfI, &pIf->RunLoopSrcRef);
if (irc == kIOReturnSuccess)
{
- CFRunLoopAddSource(pDevOsX->RunLoopRef, pIf->RunLoopSrcRef, g_pRunLoopMode);
+ RTListInit((PRTLISTNODE)&pIf->HeadOfRunLoopLst);
+ usbProxyDarwinAddRunLoopRef(&pIf->HeadOfRunLoopLst,
+ pIf->RunLoopSrcRef);
/*
* Just link the interface into the list and we're good.
@@ -1009,7 +1082,7 @@ static int usbProxyDarwinOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, vo
/*
* Init globals once.
*/
- vrc = RTOnce(&g_usbProxyDarwinOnce, usbProxyDarwinInitOnce, NULL, NULL);
+ vrc = RTOnce(&g_usbProxyDarwinOnce, usbProxyDarwinInitOnce, NULL);
AssertRCReturn(vrc, vrc);
/*
@@ -1151,14 +1224,13 @@ static int usbProxyDarwinOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, vo
PUSBPROXYDEVOSX pDevOsX = (PUSBPROXYDEVOSX)RTMemAllocZ(sizeof(*pDevOsX));
if (pDevOsX)
{
+ RTListInit((PRTLISTNODE)&pDevOsX->HeadOfRunLoopLst);
vrc = RTCritSectInit(&pDevOsX->CritSect);
if (RT_SUCCESS(vrc))
{
pDevOsX->USBDevice = USBDevice;
pDevOsX->ppDevI = ppDevI;
pDevOsX->pProxyDev = pProxyDev;
- pDevOsX->RunLoopRef = CFRunLoopGetCurrent();
- CFRetain(pDevOsX->RunLoopRef); /* paranoia */
/*
* Try seize all the interface.
@@ -1175,8 +1247,6 @@ static int usbProxyDarwinOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, vo
irc = (*ppDevI)->CreateDeviceAsyncEventSource(ppDevI, &pDevOsX->RunLoopSrcRef);
if (irc == kIOReturnSuccess)
{
- CFRunLoopAddSource(pDevOsX->RunLoopRef, pDevOsX->RunLoopSrcRef, g_pRunLoopMode);
-
/*
* Determine the active configuration.
* Can cause hangs, so drop it for now.
@@ -1191,11 +1261,10 @@ static int usbProxyDarwinOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, vo
pProxyDev->cIgnoreSetConfigs = 1;
pProxyDev->Backend.pv = pDevOsX;
+ usbProxyDarwinAddRunLoopRef(&pDevOsX->HeadOfRunLoopLst, pDevOsX->RunLoopSrcRef);
return VINF_SUCCESS; /* return */
}
vrc = VERR_VUSB_DEVICE_NOT_ATTACHED;
-
- CFRunLoopRemoveSource(pDevOsX->RunLoopRef, pDevOsX->RunLoopSrcRef, g_pRunLoopMode);
}
else
vrc = RTErrConvertFromDarwin(irc);
@@ -1268,7 +1337,11 @@ static void usbProxyDarwinClose(PUSBPROXYDEV pProxyDev)
if (pDevOsX->RunLoopSrcRef)
{
- CFRunLoopRemoveSource(pDevOsX->RunLoopRef, pDevOsX->RunLoopSrcRef, g_pRunLoopMode);
+ int rc = usbProxyDarwinRemoveSourceRefFromAllRunLoops(&pDevOsX->HeadOfRunLoopLst, pDevOsX->RunLoopSrcRef);
+ AssertRC(rc);
+
+ RTListInit((PRTLISTNODE)&pDevOsX->HeadOfRunLoopLst);
+
CFRelease(pDevOsX->RunLoopSrcRef);
pDevOsX->RunLoopSrcRef = NULL;
}
@@ -1297,12 +1370,6 @@ static void usbProxyDarwinClose(PUSBPROXYDEV pProxyDev)
*/
RTCritSectDelete(&pDevOsX->CritSect);
- if (pDevOsX->RunLoopRef)
- {
- CFRelease(pDevOsX->RunLoopRef);
- pDevOsX->RunLoopRef = NULL;
- }
-
PUSBPROXYURBOSX pUrbOsX;
while ((pUrbOsX = pDevOsX->pInFlightHead) != NULL)
{
@@ -1529,9 +1596,16 @@ static int usbProxyDarwinUrbQueue(PVUSBURB pUrb)
pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb->EndPt, pUrb->cbData));
return false;
}
+
+ if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), pIf->RunLoopSrcRef, g_pRunLoopMode))
+ usbProxyDarwinAddRunLoopRef(&pIf->HeadOfRunLoopLst, pIf->RunLoopSrcRef);
+
}
/* else: pIf == NULL -> default control pipe.*/
+ if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevOsX->RunLoopSrcRef, g_pRunLoopMode))
+ usbProxyDarwinAddRunLoopRef(&pDevOsX->HeadOfRunLoopLst, pDevOsX->RunLoopSrcRef);
+
/*
* Allocate a Darwin urb.
*/
@@ -1748,7 +1822,9 @@ static PVUSBURB usbProxyDarwinUrbReap(PUSBPROXYDEV pProxyDev, RTMSINTERVAL cMill
}
if (pUrb)
- LogFlow(("%s: usbProxyDarwinUrbReap: pProxyDev=%s returns %p\n", pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb));
+ LogFlowFunc(("LEAVE: %s: pProxyDev=%s returns %p\n", pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb));
+ else
+ LogFlowFunc(("LEAVE: NULL pProxyDev=%s returns NULL", pProxyDev->pUsbIns->pszName));
return pUrb;
}