VirtualBox

Ignore:
Timestamp:
Jan 22, 2021 7:22:03 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
142364
Message:

USB/Darwin: Capture USB devices directly through IOUSBLib, no longer use VBoxUSB.kext (see bugref:9808).

Location:
trunk/src/VBox/Main/src-server/darwin
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/darwin/USBProxyBackendDarwin.cpp

    r82968 r87376  
    4141 */
    4242USBProxyBackendDarwin::USBProxyBackendDarwin()
    43     : USBProxyBackend(), mServiceRunLoopRef(NULL), mNotifyOpaque(NULL), mWaitABitNextTime(false), mUSBLibInitialized(false)
     43    : USBProxyBackend(), mServiceRunLoopRef(NULL), mNotifyOpaque(NULL), mWaitABitNextTime(false)
    4444{
    4545}
     
    6060
    6161    unconst(m_strBackend) = Utf8Str("host");
    62 
    63     /*
    64      * Initialize the USB library.
    65      */
    66     int rc = USBLibInit();
    67     if (RT_FAILURE(rc))
    68         return rc;
    69 
    70     mUSBLibInitialized = true;
    7162
    7263    /*
     
    9182        stop();
    9283
    93     /*
    94      * Terminate the USB library - it'll
    95      */
    96     if (mUSBLibInitialized)
    97     {
    98         USBLibTerm();
    99         mUSBLibInitialized = false;
    100     }
    101 
    10284    USBProxyBackend::uninit();
    103 }
    104 
    105 
    106 void *USBProxyBackendDarwin::insertFilter(PCUSBFILTER aFilter)
    107 {
    108     return USBLibAddFilter(aFilter);
    109 }
    110 
    111 
    112 void USBProxyBackendDarwin::removeFilter(void *aId)
    113 {
    114     USBLibRemoveFilter(aId);
    11585}
    11686
     
    12999    Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_Capturing);
    130100
    131     /*
    132      * Create a one-shot capture filter for the device (don't
    133      * match on port) and trigger a re-enumeration of it.
    134      */
    135     USBFILTER Filter;
    136     USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_CAPTURE);
    137     initFilterFromDevice(&Filter, aDevice);
    138 
    139     void *pvId = USBLibAddFilter(&Filter);
    140     if (!pvId)
    141         return VERR_GENERAL_FAILURE;
    142 
    143     int rc = DarwinReEnumerateUSBDevice(aDevice->i_getUsbData());
    144     if (RT_SUCCESS(rc))
    145         aDevice->i_setBackendUserData(pvId);
    146     else
    147     {
    148         USBLibRemoveFilter(pvId);
    149         pvId = NULL;
    150     }
    151     LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
    152     return rc;
    153 }
    154 
    155 
    156 void USBProxyBackendDarwin::captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
    157 {
    158     AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
    159 
    160     /*
    161      * Remove the one-shot filter if necessary.
    162      */
    163     LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice->i_getBackendUserData()));
    164     if (!aSuccess && aDevice->i_getBackendUserData())
    165         USBLibRemoveFilter(aDevice->i_getBackendUserData());
    166     aDevice->i_setBackendUserData(NULL);
    167     USBProxyBackend::captureDeviceCompleted(aDevice, aSuccess);
     101    devLock.release();
     102    interruptWait();
     103    return VINF_SUCCESS;
    168104}
    169105
     
    182118    Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_ReleasingToHost);
    183119
    184     /*
    185      * Create a one-shot ignore filter for the device
    186      * and trigger a re-enumeration of it.
    187      */
    188     USBFILTER Filter;
    189     USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_IGNORE);
    190     initFilterFromDevice(&Filter, aDevice);
    191     Log(("USBFILTERIDX_PORT=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_PORT)));
    192     Log(("USBFILTERIDX_BUS=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_BUS)));
    193 
    194     void *pvId = USBLibAddFilter(&Filter);
    195     if (!pvId)
    196         return VERR_GENERAL_FAILURE;
    197 
    198     int rc = DarwinReEnumerateUSBDevice(aDevice->i_getUsbData());
    199     if (RT_SUCCESS(rc))
    200         aDevice->i_setBackendUserData(pvId);
    201     else
    202     {
    203         USBLibRemoveFilter(pvId);
    204         pvId = NULL;
    205     }
    206     LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
    207     return rc;
     120    devLock.release();
     121    interruptWait();
     122    return VINF_SUCCESS;
    208123}
    209124
    210125
    211 void USBProxyBackendDarwin::releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
    212 {
    213     AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
    214 
    215     /*
    216      * Remove the one-shot filter if necessary.
    217      */
    218     LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice->i_getBackendUserData()));
    219     if (!aSuccess && aDevice->i_getBackendUserData())
    220         USBLibRemoveFilter(aDevice->i_getBackendUserData());
    221     aDevice->i_setBackendUserData(NULL);
    222     USBProxyBackend::releaseDeviceCompleted(aDevice, aSuccess);
    223 }
    224 
    225 
    226 /**
    227  * Returns whether devices reported by this backend go through a de/re-attach
    228  * and device re-enumeration cycle when they are captured or released.
    229  */
    230 bool USBProxyBackendDarwin::i_isDevReEnumerationRequired()
     126bool USBProxyBackendDarwin::isFakeUpdateRequired()
    231127{
    232128    return true;
  • trunk/src/VBox/Main/src-server/darwin/iokit.cpp

    r85929 r87376  
    12761276
    12771277    return pHead;
    1278 }
    1279 
    1280 
    1281 /**
    1282  * Triggers re-enumeration of a device.
    1283  *
    1284  * @returns VBox status code.
    1285  * @param   pCur    The USBDEVICE structure for the device.
    1286  */
    1287 int DarwinReEnumerateUSBDevice(PCUSBDEVICE pCur)
    1288 {
    1289     int vrc;
    1290     const char *pszAddress = pCur->pszAddress;
    1291     AssertPtrReturn(pszAddress, VERR_INVALID_POINTER);
    1292     AssertReturn(darwinOpenMasterPort(), VERR_GENERAL_FAILURE);
    1293 
    1294     /*
    1295      * This code is a short version of the Open method in USBProxyDevice-darwin.cpp stuff.
    1296      * Fixes made to this code probably applies there too!
    1297      */
    1298 
    1299     CFMutableDictionaryRef RefMatchingDict = IOServiceMatching(kIOUSBDeviceClassName);
    1300     AssertReturn(RefMatchingDict, VERR_INTERNAL_ERROR_4);
    1301 
    1302     uint64_t u64SessionId = 0;
    1303     uint32_t u32LocationId = 0;
    1304     const char *psz = pszAddress;
    1305     do
    1306     {
    1307         const char chValue = *psz;
    1308         AssertReleaseReturn(psz[1] == '=', VERR_INTERNAL_ERROR);
    1309         uint64_t u64Value;
    1310         int rc = RTStrToUInt64Ex(psz + 2, (char **)&psz, 0, &u64Value);
    1311         AssertReleaseRCReturn(rc, rc);
    1312         AssertReleaseReturn(!*psz || *psz == ';', rc);
    1313         switch (chValue)
    1314         {
    1315             case 'l':
    1316                 u32LocationId = (uint32_t)u64Value;
    1317                 break;
    1318             case 's':
    1319                 u64SessionId = u64Value;
    1320                 break;
    1321             case 'p':
    1322             case 'v':
    1323             {
    1324 #if 0 /* Guess what, this doesn't 'ing work either! */
    1325                 SInt32 i32 = (int16_t)u64Value;
    1326                 CFNumberRef Num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i32);
    1327                 AssertBreak(Num);
    1328                 CFDictionarySetValue(RefMatchingDict, chValue == 'p' ? CFSTR(kUSBProductID) : CFSTR(kUSBVendorID), Num);
    1329                 CFRelease(Num);
    1330 #endif
    1331                 break;
    1332             }
    1333             default:
    1334                 AssertReleaseMsgFailedReturn(("chValue=%#x\n", chValue), VERR_INTERNAL_ERROR);
    1335         }
    1336         if (*psz == ';')
    1337             psz++;
    1338     } while (*psz);
    1339 
    1340     io_iterator_t USBDevices = IO_OBJECT_NULL;
    1341     IOReturn irc = IOServiceGetMatchingServices(g_MasterPort, RefMatchingDict, &USBDevices);
    1342     AssertMsgReturn(irc == kIOReturnSuccess, ("irc=%#x\n", irc), VERR_INTERNAL_ERROR_5);
    1343     RefMatchingDict = NULL; /* the reference is consumed by IOServiceGetMatchingServices. */
    1344 
    1345     unsigned cMatches = 0;
    1346     io_object_t USBDevice;
    1347     while ((USBDevice = IOIteratorNext(USBDevices)) != IO_OBJECT_NULL)
    1348     {
    1349         cMatches++;
    1350         CFMutableDictionaryRef PropsRef = 0;
    1351         kern_return_t krc = IORegistryEntryCreateCFProperties(USBDevice, &PropsRef, kCFAllocatorDefault, kNilOptions);
    1352         if (krc == KERN_SUCCESS)
    1353         {
    1354             uint64_t u64CurSessionId;
    1355             uint32_t u32CurLocationId;
    1356             if (    (    !u64SessionId
    1357                      || (   darwinDictGetU64(PropsRef, CFSTR("sessionID"), &u64CurSessionId)
    1358                          && u64CurSessionId == u64SessionId))
    1359                 &&  (   !u32LocationId
    1360                      || (   darwinDictGetU32(PropsRef, CFSTR(kUSBDevicePropertyLocationID), &u32CurLocationId)
    1361                          && u32CurLocationId == u32LocationId))
    1362                 )
    1363             {
    1364                 CFRelease(PropsRef);
    1365                 break;
    1366             }
    1367             CFRelease(PropsRef);
    1368         }
    1369         IOObjectRelease(USBDevice);
    1370     }
    1371     IOObjectRelease(USBDevices);
    1372     USBDevices = IO_OBJECT_NULL;
    1373     if (!USBDevice)
    1374     {
    1375         LogRel(("USB: Device '%s' not found (%d pid+vid matches)\n", pszAddress, cMatches));
    1376         IOObjectRelease(USBDevices);
    1377         return VERR_VUSB_DEVICE_NAME_NOT_FOUND;
    1378     }
    1379 
    1380     /*
    1381      * Create a plugin interface for the device and query its IOUSBDeviceInterface.
    1382      */
    1383     SInt32 Score = 0;
    1384     IOCFPlugInInterface **ppPlugInInterface = NULL;
    1385     irc = IOCreatePlugInInterfaceForService(USBDevice, kIOUSBDeviceUserClientTypeID,
    1386                                             kIOCFPlugInInterfaceID, &ppPlugInInterface, &Score);
    1387     if (irc == kIOReturnSuccess)
    1388     {
    1389         IOUSBDeviceInterface245 **ppDevI = NULL;
    1390         HRESULT hrc = (*ppPlugInInterface)->QueryInterface(ppPlugInInterface,
    1391                                                            CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID245),
    1392                                                            (LPVOID *)&ppDevI);
    1393         irc = IODestroyPlugInInterface(ppPlugInInterface); Assert(irc == kIOReturnSuccess);
    1394         ppPlugInInterface = NULL;
    1395         if (hrc == S_OK)
    1396         {
    1397             /*
    1398              * Try open the device for exclusive access.
    1399              */
    1400             irc = (*ppDevI)->USBDeviceOpenSeize(ppDevI);
    1401             if (irc == kIOReturnExclusiveAccess)
    1402             {
    1403                 RTThreadSleep(20);
    1404                 irc = (*ppDevI)->USBDeviceOpenSeize(ppDevI);
    1405             }
    1406             if (irc == kIOReturnSuccess)
    1407             {
    1408                 /*
    1409                  * Re-enumerate the device and bail out.
    1410                  */
    1411                 irc = (*ppDevI)->USBDeviceReEnumerate(ppDevI, 0);
    1412                 if (irc == kIOReturnSuccess)
    1413                     vrc = VINF_SUCCESS;
    1414                 else
    1415                 {
    1416                     LogRel(("USB: Failed to open device '%s', plug-in creation failed with irc=%#x.\n", pszAddress, irc));
    1417                     vrc = RTErrConvertFromDarwinIO(irc);
    1418                 }
    1419 
    1420                 (*ppDevI)->USBDeviceClose(ppDevI);
    1421             }
    1422             else if (irc == kIOReturnExclusiveAccess)
    1423             {
    1424                 LogRel(("USB: Device '%s' is being used by another process\n", pszAddress));
    1425                 vrc = VERR_SHARING_VIOLATION;
    1426             }
    1427             else
    1428             {
    1429                 LogRel(("USB: Failed to open device '%s', irc=%#x.\n", pszAddress, irc));
    1430                 vrc = VERR_OPEN_FAILED;
    1431             }
    1432         }
    1433         else
    1434         {
    1435             LogRel(("USB: Failed to create plugin interface for device '%s', hrc=%#x.\n", pszAddress, hrc));
    1436             vrc = VERR_OPEN_FAILED;
    1437         }
    1438 
    1439         (*ppDevI)->Release(ppDevI);
    1440     }
    1441     else
    1442     {
    1443         LogRel(("USB: Failed to open device '%s', plug-in creation failed with irc=%#x.\n", pszAddress, irc));
    1444         vrc = RTErrConvertFromDarwinIO(irc);
    1445     }
    1446 
    1447     return vrc;
    14481278}
    14491279
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette