Changeset 87376 in vbox for trunk/src/VBox/Main/src-server/darwin
- Timestamp:
- Jan 22, 2021 7:22:03 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 142364
- 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 41 41 */ 42 42 USBProxyBackendDarwin::USBProxyBackendDarwin() 43 : USBProxyBackend(), mServiceRunLoopRef(NULL), mNotifyOpaque(NULL), mWaitABitNextTime(false) , mUSBLibInitialized(false)43 : USBProxyBackend(), mServiceRunLoopRef(NULL), mNotifyOpaque(NULL), mWaitABitNextTime(false) 44 44 { 45 45 } … … 60 60 61 61 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;71 62 72 63 /* … … 91 82 stop(); 92 83 93 /*94 * Terminate the USB library - it'll95 */96 if (mUSBLibInitialized)97 {98 USBLibTerm();99 mUSBLibInitialized = false;100 }101 102 84 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);115 85 } 116 86 … … 129 99 Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_Capturing); 130 100 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; 168 104 } 169 105 … … 182 118 Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_ReleasingToHost); 183 119 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; 208 123 } 209 124 210 125 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() 126 bool USBProxyBackendDarwin::isFakeUpdateRequired() 231 127 { 232 128 return true; -
trunk/src/VBox/Main/src-server/darwin/iokit.cpp
r85929 r87376 1276 1276 1277 1277 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 do1306 {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 #endif1331 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 ( ( !u64SessionId1357 || ( darwinDictGetU64(PropsRef, CFSTR("sessionID"), &u64CurSessionId)1358 && u64CurSessionId == u64SessionId))1359 && ( !u32LocationId1360 || ( 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 else1415 {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 else1428 {1429 LogRel(("USB: Failed to open device '%s', irc=%#x.\n", pszAddress, irc));1430 vrc = VERR_OPEN_FAILED;1431 }1432 }1433 else1434 {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 else1442 {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;1448 1278 } 1449 1279
Note:
See TracChangeset
for help on using the changeset viewer.