- Timestamp:
- Sep 7, 2010 9:25:05 PM (14 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/HostHardwareLinux.h
r32262 r32299 131 131 132 132 /** 133 * Class for probing and returning information about host USB devices. 134 * To use this class, create an instance, call the update methods to do the 135 * actual probing and use the iterator methods to get the result of the probe. 136 */ 137 typedef struct VBoxMainUSBDeviceInfo 138 { 139 /** The list of currently available USB devices */ 140 VECTOR_OBJ(USBDeviceInfo) mvecDevInfo; 141 } VBoxMainUSBDeviceInfo; 142 143 /** Constructor */ 144 static inline void VBoxMainUSBDevInfoInit(VBoxMainUSBDeviceInfo *pSelf) 145 { 146 VEC_INIT_OBJ(&pSelf->mvecDevInfo, USBDeviceInfo, USBDevInfoCleanup); 147 } 148 149 /** Destructor */ 150 static inline void VBoxMainUSBDevInfoCleanup(VBoxMainUSBDeviceInfo *pSelf) 151 { 152 VEC_CLEANUP_OBJ(&pSelf->mvecDevInfo); 153 } 154 155 /** 156 * Search for host USB devices and rebuild the list, which remains empty 157 * until the first time this method is called. 133 * Enumerate USB devices attached to the host using sysfs and return them as a 134 * vector 158 135 * @returns iprt status code 159 */ 160 int USBDevInfoUpdateDevices(VBoxMainUSBDeviceInfo *pSelf); 136 * @param pvecDevInfo vector to add the devices onto the end of. Should be 137 * initialised and empty. 138 */ 139 int USBSysfsEnumerateHostDevices(VECTOR_OBJ(USBDeviceInfo) *pvecDevInfo); 161 140 162 141 -
trunk/src/VBox/Main/include/USBProxyService.h
r31892 r32299 219 219 virtual int interruptWait(void); 220 220 virtual PUSBDEVICE getDevices(void); 221 PUSBDEVICE getDevicesFromUsbfs(void);222 PUSBDEVICE getDevicesFromSysfs(void);223 int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc);224 221 virtual void deviceAdded(ComObjPtr<HostUSBDevice> &aDevice, SessionMachinesList &llOpenedMachines, PUSBDEVICE aUSBDevice); 225 222 virtual bool updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine); … … 245 242 unsigned mUdevPolls; 246 243 # ifdef VBOX_USB_WITH_SYSFS 247 /** Object used for querying device information from hal. */248 VBoxMainUSBDeviceInfo mDeviceList;249 244 /** Object used for polling for hotplug events from hal. */ 250 245 VBoxMainHotplugWaiter mWaiter; -
trunk/src/VBox/Main/linux/HostHardwareLinux.cpp
r32262 r32299 1549 1549 1550 1550 /** 1551 * Logic for USB DevInfoUpdateDevices.1551 * Logic for USBSysfsEnumerateHostDevices. 1552 1552 * @param pvecDevInfo vector of device information structures to add device 1553 1553 * information to 1554 1554 * @param pvecpchDevs empty scratch vector which will be freed by the caller 1555 1555 */ 1556 static int do UpdateUSBDevices(VECTOR_OBJ(USBDeviceInfo) *pvecDevInfo,1556 static int doSysfsEnumerateHostDevices(VECTOR_OBJ(USBDeviceInfo) *pvecDevInfo, 1557 1557 VECTOR_PTR(char *) *pvecpchDevs) 1558 1558 { … … 1579 1579 #endif /* VBOX_USB_WITH_SYSFS */ 1580 1580 1581 int USBDevInfoUpdateDevices (VBoxMainUSBDeviceInfo *pSelf) 1582 { 1583 int rc = VINF_SUCCESS; 1584 1581 int USBSysfsEnumerateHostDevices(VECTOR_OBJ(USBDeviceInfo) *pvecDevInfo) 1582 { 1583 VECTOR_PTR(char *) vecpchDevs; 1584 int rc = VERR_NOT_IMPLEMENTED; 1585 1586 AssertReturn(VEC_SIZE_OBJ(pvecDevInfo) == 0, VERR_INVALID_PARAMETER); 1585 1587 LogFlowFunc(("entered\n")); 1586 VECTOR_PTR(char *) vecpchDevs;1587 1588 VEC_INIT_PTR(&vecpchDevs, char *, RTStrFree); 1588 VEC_CLEAR_OBJ(&pSelf->mvecDevInfo);1589 1589 #ifdef VBOX_USB_WITH_SYSFS 1590 1590 # ifdef VBOX_USB_WITH_INOTIFY 1591 rc = do UpdateUSBDevices(&pSelf->mvecDevInfo, &vecpchDevs);1591 rc = doSysfsEnumerateHostDevices(pvecDevInfo, &vecpchDevs); 1592 1592 # endif 1593 1593 #endif /* !VBOX_USB_WITH_SYSFS */ -
trunk/src/VBox/Main/linux/USBProxyServiceLinux.cpp
r32262 r32299 263 263 264 264 #ifdef VBOX_USB_WITH_SYSFS 265 VBoxMainUSBDevInfoInit(&mDeviceList);266 265 int rc = mWaiter.getStatus(); 267 266 if (RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_TRY_AGAIN) … … 475 474 } 476 475 476 /** 477 * Free all the members of a USB device created by the Linux enumeration code. 478 * @note this duplicates a USBProxyService method which we needed access too 479 * without pulling in the rest of the proxy service code. 480 * 481 * @param pDevice Pointer to the device. 482 */ 483 static void deviceFreeMembers(PUSBDEVICE pDevice) 484 { 485 RTStrFree((char *)pDevice->pszManufacturer); 486 pDevice->pszManufacturer = NULL; 487 RTStrFree((char *)pDevice->pszProduct); 488 pDevice->pszProduct = NULL; 489 RTStrFree((char *)pDevice->pszSerialNumber); 490 pDevice->pszSerialNumber = NULL; 491 492 RTStrFree((char *)pDevice->pszAddress); 493 pDevice->pszAddress = NULL; 494 } 495 496 /** 497 * Free one USB device created by the Linux enumeration code. 498 * @note this duplicates a USBProxyService method which we needed access too 499 * without pulling in the rest of the proxy service code. 500 * 501 * @param pDevice Pointer to the device. 502 */ 503 static void deviceFree(PUSBDEVICE pDevice) 504 { 505 deviceFreeMembers(pDevice); 506 RTMemFree(pDevice); 507 } 477 508 478 509 /** … … 836 867 837 868 /** Just a worker for USBProxyServiceLinux::getDevices that avoids some code duplication. */ 838 int USBProxyServiceLinux::addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, int rc)869 static int addDeviceToChain(PUSBDEVICE pDev, PUSBDEVICE *ppFirst, PUSBDEVICE **pppNext, const char *pcszUsbfsRoot, int rc) 839 870 { 840 871 /* usbDeterminState requires the address. */ … … 842 873 if (pDevNew) 843 874 { 844 RTStrAPrintf((char **)&pDevNew->pszAddress, "%s/%03d/%03d", mUsbfsRoot.c_str(), pDevNew->bBus, pDevNew->bDevNum);875 RTStrAPrintf((char **)&pDevNew->pszAddress, "%s/%03d/%03d", pcszUsbfsRoot, pDevNew->bBus, pDevNew->bDevNum); 845 876 if (pDevNew->pszAddress) 846 877 { … … 855 886 } 856 887 else 857 freeDevice(pDevNew);888 deviceFree(pDevNew); 858 889 } 859 890 else 860 891 { 861 freeDevice(pDevNew);892 deviceFree(pDevNew); 862 893 rc = VERR_NO_MEMORY; 863 894 } … … 866 897 { 867 898 rc = VERR_NO_MEMORY; 868 freeDeviceMembers(pDev);899 deviceFreeMembers(pDev); 869 900 } 870 901 … … 873 904 874 905 906 static int openDevicesFile(const char *pcszUsbfsRoot, FILE **ppFile) 907 { 908 char *pszPath; 909 FILE *pFile; 910 RTStrAPrintf(&pszPath, "%s/devices", pcszUsbfsRoot); 911 if (!pszPath) 912 return VERR_NO_MEMORY; 913 pFile = fopen(pszPath, "r"); 914 RTStrFree(pszPath); 915 if (!pFile) 916 return RTErrConvertFromErrno(errno); 917 *ppFile = pFile; 918 return VINF_SUCCESS; 919 } 920 875 921 /** 876 922 * USBProxyService::getDevices() implementation for usbfs. 877 923 */ 878 PUSBDEVICE USBProxyServiceLinux::getDevicesFromUsbfs(void)924 static PUSBDEVICE getDevicesFromUsbfs(const char *pcszUsbfsRoot) 879 925 { 880 926 PUSBDEVICE pFirst = NULL; 881 if (mStream) 927 FILE *pFile; 928 int rc; 929 rc = openDevicesFile(pcszUsbfsRoot, &pFile); 930 if (RT_SUCCESS(rc)) 882 931 { 883 932 PUSBDEVICE *ppNext = NULL; … … 888 937 Dev.enmState = USBDEVICESTATE_UNUSED; 889 938 890 /* 891 * Rewind the stream and make 100% sure we flush the buffer. 892 * 893 * We've had trouble with rewind() messing up on buffered streams when attaching 894 * device clusters such as the Bloomberg keyboard. Therefor the stream is now 895 * without a permanent buffer (see the constructor) and we'll employ a temporary 896 * stack buffer while parsing the file (speed). 897 */ 898 rewind(mStream); 899 char szBuf[1024]; 900 setvbuf(mStream, szBuf, _IOFBF, sizeof(szBuf)); 901 902 int rc = VINF_SUCCESS; 939 rc = VINF_SUCCESS; 903 940 while ( RT_SUCCESS(rc) 904 && fgets(szLine, sizeof(szLine), mStream))941 && fgets(szLine, sizeof(szLine), pFile)) 905 942 { 906 943 char *psz; … … 909 946 /* validate and remove the trailing newline. */ 910 947 psz = strchr(szLine, '\0'); 911 if (psz[-1] != '\n' && !feof( mStream))948 if (psz[-1] != '\n' && !feof(pFile)) 912 949 { 913 950 AssertMsgFailed(("Line too long. (cch=%d)\n", strlen(szLine))); … … 947 984 AssertMsg(cHits >= 3 || cHits == 0, ("cHits=%d\n", cHits)); 948 985 if (cHits >= 3) 949 rc = addDeviceToChain(&Dev, &pFirst, &ppNext, rc);986 rc = addDeviceToChain(&Dev, &pFirst, &ppNext, pcszUsbfsRoot, rc); 950 987 else 951 freeDeviceMembers(&Dev);988 deviceFreeMembers(&Dev); 952 989 953 990 /* Reset device state */ … … 1139 1176 AssertMsg(cHits >= 3 || cHits == 0, ("cHits=%d\n", cHits)); 1140 1177 if (cHits >= 3) 1141 rc = addDeviceToChain(&Dev, &pFirst, &ppNext, rc);1178 rc = addDeviceToChain(&Dev, &pFirst, &ppNext, pcszUsbfsRoot, rc); 1142 1179 1143 1180 /* … … 1146 1183 if (RT_FAILURE(rc)) 1147 1184 { 1148 LogFlow(("USBProxyServiceLinux::getDevices: rc=%Rrc\n", rc));1149 1185 while (pFirst) 1150 1186 { 1151 1187 PUSBDEVICE pFree = pFirst; 1152 1188 pFirst = pFirst->pNext; 1153 freeDevice(pFree);1189 deviceFree(pFree); 1154 1190 } 1155 1191 } 1156 1157 /* 1158 * Turn buffering off to detach it from the local buffer and to 1159 * make subsequent rewind() calls work correctly. 1160 */ 1161 setvbuf(mStream, NULL, _IONBF, 0); 1162 } 1192 } 1193 if (RT_FAILURE(rc)) 1194 LogFlow(("USBProxyServiceLinux::getDevices: rc=%Rrc\n", rc)); 1163 1195 return pFirst; 1164 1196 } … … 1333 1365 #endif /* VBOX_USB_WITH_SYSFS */ 1334 1366 1367 static void fillInDeviceFromSysfs(USBDEVICE *Dev, USBDeviceInfo *pInfo) 1368 { 1369 int rc; 1370 const char *pszSysfsPath = pInfo->mSysfsPath; 1371 1372 /* Fill in the simple fields */ 1373 Dev->enmState = USBDEVICESTATE_UNUSED; 1374 Dev->bBus = RTLinuxSysFsReadIntFile(10, "%s/busnum", pszSysfsPath); 1375 Dev->bDeviceClass = RTLinuxSysFsReadIntFile(16, "%s/bDeviceClass", pszSysfsPath); 1376 Dev->bDeviceSubClass = RTLinuxSysFsReadIntFile(16, "%s/bDeviceSubClass", pszSysfsPath); 1377 Dev->bDeviceProtocol = RTLinuxSysFsReadIntFile(16, "%s/bDeviceProtocol", pszSysfsPath); 1378 Dev->bNumConfigurations = RTLinuxSysFsReadIntFile(10, "%s/bNumConfigurations", pszSysfsPath); 1379 Dev->idVendor = RTLinuxSysFsReadIntFile(16, "%s/idVendor", pszSysfsPath); 1380 Dev->idProduct = RTLinuxSysFsReadIntFile(16, "%s/idProduct", pszSysfsPath); 1381 Dev->bDevNum = RTLinuxSysFsReadIntFile(10, "%s/devnum", pszSysfsPath); 1382 1383 /* Now deal with the non-numeric bits. */ 1384 char szBuf[1024]; /* Should be larger than anything a sane device 1385 * will need, and insane devices can be unsupported 1386 * until further notice. */ 1387 ssize_t cchRead; 1388 1389 /* For simplicity, we just do strcmps on the next one. */ 1390 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/speed", 1391 pszSysfsPath); 1392 if (cchRead <= 0 || (size_t) cchRead == sizeof(szBuf)) 1393 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1394 else 1395 Dev->enmSpeed = !strcmp(szBuf, "1.5") ? USBDEVICESPEED_LOW 1396 : !strcmp(szBuf, "12") ? USBDEVICESPEED_FULL 1397 : !strcmp(szBuf, "480") ? USBDEVICESPEED_HIGH 1398 : USBDEVICESPEED_UNKNOWN; 1399 1400 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/version", 1401 pszSysfsPath); 1402 if (cchRead <= 0 || (size_t) cchRead == sizeof(szBuf)) 1403 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1404 else 1405 { 1406 rc = convertSysfsStrToBCD(szBuf, &Dev->bcdUSB); 1407 if (RT_FAILURE(rc)) 1408 { 1409 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1410 Dev->bcdUSB = (uint16_t)-1; 1411 } 1412 } 1413 1414 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/bcdDevice", 1415 pszSysfsPath); 1416 if (cchRead <= 0 || (size_t) cchRead == sizeof(szBuf)) 1417 Dev->bcdDevice = (uint16_t)-1; 1418 else 1419 { 1420 rc = convertSysfsStrToBCD(szBuf, &Dev->bcdDevice); 1421 if (RT_FAILURE(rc)) 1422 Dev->bcdDevice = (uint16_t)-1; 1423 } 1424 1425 /* Now do things that need string duplication */ 1426 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/product", 1427 pszSysfsPath); 1428 if (cchRead > 0 && (size_t) cchRead < sizeof(szBuf)) 1429 { 1430 RTStrPurgeEncoding(szBuf); 1431 Dev->pszProduct = RTStrDup(szBuf); 1432 } 1433 1434 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/serial", 1435 pszSysfsPath); 1436 if (cchRead > 0 && (size_t) cchRead < sizeof(szBuf)) 1437 { 1438 RTStrPurgeEncoding(szBuf); 1439 Dev->pszSerialNumber = RTStrDup(szBuf); 1440 Dev->u64SerialHash = USBLibHashSerial(szBuf); 1441 } 1442 1443 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/manufacturer", 1444 pszSysfsPath); 1445 if (cchRead > 0 && (size_t) cchRead < sizeof(szBuf)) 1446 { 1447 RTStrPurgeEncoding(szBuf); 1448 Dev->pszManufacturer = RTStrDup(szBuf); 1449 } 1450 1451 /* Work out the port number */ 1452 if (RT_FAILURE(usbGetPortFromSysfsPath(pszSysfsPath, &Dev->bPort))) 1453 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1454 1455 /* Check the interfaces to see if we can support the device. */ 1456 char **ppszIf; 1457 VEC_FOR_EACH(&pInfo->mvecpszInterfaces, char *, ppszIf) 1458 { 1459 ssize_t cb = RTLinuxSysFsGetLinkDest(szBuf, sizeof(szBuf), "%s/driver", 1460 *ppszIf); 1461 if (cb > 0 && Dev->enmState != USBDEVICESTATE_UNSUPPORTED) 1462 Dev->enmState = (strcmp(szBuf, "hub") == 0) 1463 ? USBDEVICESTATE_UNSUPPORTED 1464 : USBDEVICESTATE_USED_BY_HOST_CAPTURABLE; 1465 if (RTLinuxSysFsReadIntFile(16, "%s/bInterfaceClass", 1466 *ppszIf) == 9 /* hub */) 1467 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1468 } 1469 1470 /* We want a copy of the device node and sysfs paths guaranteed not to 1471 * contain double slashes, since we use a double slash as a separator in 1472 * the pszAddress field. */ 1473 char szDeviceClean[RTPATH_MAX]; 1474 char szSysfsClean[RTPATH_MAX]; 1475 char *pszAddress = NULL; 1476 if ( RT_SUCCESS(RTPathReal(pInfo->mDevice, szDeviceClean, 1477 sizeof(szDeviceClean))) 1478 && RT_SUCCESS(RTPathReal(pszSysfsPath, szSysfsClean, 1479 sizeof(szSysfsClean))) 1480 ) 1481 RTStrAPrintf(&pszAddress, "sysfs:%s//device:%s", szSysfsClean, 1482 szDeviceClean); 1483 Dev->pszAddress = pszAddress; 1484 1485 /* Work out from the data collected whether we can support this device. */ 1486 Dev->enmState = usbDeterminState(Dev); 1487 usbLogDevice(Dev); 1488 } 1489 1335 1490 /** 1336 1491 * USBProxyService::getDevices() implementation for sysfs. 1337 1492 */ 1338 PUSBDEVICE USBProxyServiceLinux::getDevicesFromSysfs(void)1493 static PUSBDEVICE getDevicesFromSysfs(void) 1339 1494 { 1340 1495 #ifdef VBOX_USB_WITH_SYSFS … … 1342 1497 PUSBDEVICE pFirst = NULL; 1343 1498 PUSBDEVICE pLast = NULL; 1344 int rc = USBDevInfoUpdateDevices(&mDeviceList);1499 VECTOR_OBJ(USBDeviceInfo) vecDevInfo; 1345 1500 USBDeviceInfo *pInfo; 1346 VEC_FOR_EACH(&mDeviceList.mvecDevInfo, USBDeviceInfo, pInfo) 1501 int rc; 1502 1503 VEC_INIT_OBJ(&vecDevInfo, USBDeviceInfo, USBDevInfoCleanup); 1504 rc = USBSysfsEnumerateHostDevices(&vecDevInfo); 1505 if (RT_FAILURE(rc)) 1506 return NULL; 1507 VEC_FOR_EACH(&vecDevInfo, USBDeviceInfo, pInfo) 1347 1508 { 1348 1509 USBDEVICE *Dev = (USBDEVICE *)RTMemAllocZ(sizeof(USBDEVICE)); … … 1351 1512 if (RT_SUCCESS(rc)) 1352 1513 { 1353 const char *pszSysfsPath = pInfo->mSysfsPath; 1354 1355 /* Fill in the simple fields */ 1356 Dev->enmState = USBDEVICESTATE_UNUSED; 1357 Dev->bBus = RTLinuxSysFsReadIntFile(10, "%s/busnum", pszSysfsPath); 1358 Dev->bDeviceClass = RTLinuxSysFsReadIntFile(16, "%s/bDeviceClass", pszSysfsPath); 1359 Dev->bDeviceSubClass = RTLinuxSysFsReadIntFile(16, "%s/bDeviceSubClass", pszSysfsPath); 1360 Dev->bDeviceProtocol = RTLinuxSysFsReadIntFile(16, "%s/bDeviceProtocol", pszSysfsPath); 1361 Dev->bNumConfigurations = RTLinuxSysFsReadIntFile(10, "%s/bNumConfigurations", pszSysfsPath); 1362 Dev->idVendor = RTLinuxSysFsReadIntFile(16, "%s/idVendor", pszSysfsPath); 1363 Dev->idProduct = RTLinuxSysFsReadIntFile(16, "%s/idProduct", pszSysfsPath); 1364 Dev->bDevNum = RTLinuxSysFsReadIntFile(10, "%s/devnum", pszSysfsPath); 1365 1366 /* Now deal with the non-numeric bits. */ 1367 char szBuf[1024]; /* Should be larger than anything a sane device 1368 * will need, and insane devices can be unsupported 1369 * until further notice. */ 1370 ssize_t cchRead; 1371 1372 /* For simplicity, we just do strcmps on the next one. */ 1373 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/speed", 1374 pszSysfsPath); 1375 if (cchRead <= 0 || (size_t) cchRead == sizeof(szBuf)) 1376 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1377 else 1378 Dev->enmSpeed = !strcmp(szBuf, "1.5") ? USBDEVICESPEED_LOW 1379 : !strcmp(szBuf, "12") ? USBDEVICESPEED_FULL 1380 : !strcmp(szBuf, "480") ? USBDEVICESPEED_HIGH 1381 : USBDEVICESPEED_UNKNOWN; 1382 1383 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/version", 1384 pszSysfsPath); 1385 if (cchRead <= 0 || (size_t) cchRead == sizeof(szBuf)) 1386 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1387 else 1388 { 1389 rc = convertSysfsStrToBCD(szBuf, &Dev->bcdUSB); 1390 if (RT_FAILURE(rc)) 1391 { 1392 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1393 Dev->bcdUSB = (uint16_t)-1; 1394 } 1395 } 1396 1397 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/bcdDevice", 1398 pszSysfsPath); 1399 if (cchRead <= 0 || (size_t) cchRead == sizeof(szBuf)) 1400 Dev->bcdDevice = (uint16_t)-1; 1401 else 1402 { 1403 rc = convertSysfsStrToBCD(szBuf, &Dev->bcdDevice); 1404 if (RT_FAILURE(rc)) 1405 Dev->bcdDevice = (uint16_t)-1; 1406 } 1407 1408 /* Now do things that need string duplication */ 1409 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/product", 1410 pszSysfsPath); 1411 if (cchRead > 0 && (size_t) cchRead < sizeof(szBuf)) 1412 { 1413 RTStrPurgeEncoding(szBuf); 1414 Dev->pszProduct = RTStrDup(szBuf); 1415 } 1416 1417 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/serial", 1418 pszSysfsPath); 1419 if (cchRead > 0 && (size_t) cchRead < sizeof(szBuf)) 1420 { 1421 RTStrPurgeEncoding(szBuf); 1422 Dev->pszSerialNumber = RTStrDup(szBuf); 1423 Dev->u64SerialHash = USBLibHashSerial(szBuf); 1424 } 1425 1426 cchRead = RTLinuxSysFsReadStrFile(szBuf, sizeof(szBuf), "%s/manufacturer", 1427 pszSysfsPath); 1428 if (cchRead > 0 && (size_t) cchRead < sizeof(szBuf)) 1429 { 1430 RTStrPurgeEncoding(szBuf); 1431 Dev->pszManufacturer = RTStrDup(szBuf); 1432 } 1433 1434 /* Work out the port number */ 1435 if (RT_FAILURE(usbGetPortFromSysfsPath(pszSysfsPath, &Dev->bPort))) 1436 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1437 1438 /* Check the interfaces to see if we can support the device. */ 1439 char **ppszIf; 1440 VEC_FOR_EACH(&pInfo->mvecpszInterfaces, char *, ppszIf) 1441 { 1442 ssize_t cb = RTLinuxSysFsGetLinkDest(szBuf, sizeof(szBuf), "%s/driver", 1443 *ppszIf); 1444 if (cb > 0 && Dev->enmState != USBDEVICESTATE_UNSUPPORTED) 1445 Dev->enmState = (strcmp(szBuf, "hub") == 0) 1446 ? USBDEVICESTATE_UNSUPPORTED 1447 : USBDEVICESTATE_USED_BY_HOST_CAPTURABLE; 1448 if (RTLinuxSysFsReadIntFile(16, "%s/bInterfaceClass", 1449 *ppszIf) == 9 /* hub */) 1450 Dev->enmState = USBDEVICESTATE_UNSUPPORTED; 1451 } 1452 1453 /* We want a copy of the device node and sysfs paths guaranteed not to 1454 * contain double slashes, since we use a double slash as a separator in 1455 * the pszAddress field. */ 1456 char szDeviceClean[RTPATH_MAX]; 1457 char szSysfsClean[RTPATH_MAX]; 1458 char *pszAddress = NULL; 1459 if ( RT_SUCCESS(RTPathReal(pInfo->mDevice, szDeviceClean, 1460 sizeof(szDeviceClean))) 1461 && RT_SUCCESS(RTPathReal(pszSysfsPath, szSysfsClean, 1462 sizeof(szSysfsClean))) 1463 ) 1464 RTStrAPrintf(&pszAddress, "sysfs:%s//device:%s", szSysfsClean, 1465 szDeviceClean); 1466 Dev->pszAddress = pszAddress; 1467 1468 /* Work out from the data collected whether we can support this device. */ 1469 Dev->enmState = usbDeterminState(Dev); 1470 usbLogDevice(Dev); 1514 fillInDeviceFromSysfs(Dev, pInfo); 1471 1515 } 1472 1516 if ( RT_SUCCESS(rc) … … 1484 1528 } 1485 1529 else 1486 freeDevice(Dev);1530 deviceFree(Dev); 1487 1531 if (RT_FAILURE(rc)) 1488 1532 break; … … 1492 1536 { 1493 1537 PUSBDEVICE pNext = pFirst->pNext; 1494 freeDevice(pFirst);1538 deviceFree(pFirst); 1495 1539 pFirst = pNext; 1496 1540 } 1497 1541 1498 /* Eliminate any duplicates. This was originally a sanity check, but it 1499 * turned out that hal can get confused and return devices twice. */ 1500 for (PUSBDEVICE pDev = pFirst; pDev != NULL; pDev = pDev->pNext) 1501 for (PUSBDEVICE pDev2 = pDev; pDev2 != NULL && pDev2->pNext != NULL; 1502 pDev2 = pDev2->pNext) 1503 while ( pDev2->pNext != NULL 1504 && RTStrCmp(pDev->pszAddress, pDev2->pNext->pszAddress) == 0) 1505 { 1506 PUSBDEVICE pDup = pDev2->pNext; 1507 pDev2->pNext = pDup->pNext; 1508 freeDevice(pDup); 1509 } 1542 VEC_CLEANUP_OBJ(&vecDevInfo); 1510 1543 return pFirst; 1511 1544 #else /* !VBOX_USB_WITH_SYSFS */ … … 1514 1547 } 1515 1548 1549 static PUSBDEVICE USBProxyLinuxGetDevices(const char *pcszUsbfsRoot) 1550 { 1551 if (pcszUsbfsRoot) 1552 return getDevicesFromUsbfs(pcszUsbfsRoot); 1553 else 1554 return getDevicesFromSysfs(); 1555 } 1516 1556 1517 1557 PUSBDEVICE USBProxyServiceLinux::getDevices(void) 1518 1558 { 1519 PUSBDEVICE pDevices;1520 1559 if (mUsingUsbfsDevices) 1521 pDevices = getDevicesFromUsbfs();1560 return USBProxyLinuxGetDevices(mUsbfsRoot.c_str()); 1522 1561 else 1523 pDevices = getDevicesFromSysfs(); 1524 return pDevices; 1525 } 1526 1562 return USBProxyLinuxGetDevices(NULL); 1563 } 1564 -
trunk/src/VBox/Main/testcase/tstHostHardwareLinux.cpp
r32262 r32299 91 91 } 92 92 #ifdef VBOX_USB_WITH_SYSFS 93 V BoxMainUSBDeviceInfo deviceInfo;94 V BoxMainUSBDevInfoInit(&deviceInfo);95 rc = USB DevInfoUpdateDevices(&deviceInfo);93 VECTOR_OBJ(USBDeviceInfo) vecDevInfo; 94 VEC_INIT_OBJ(&vecDevInfo, USBDeviceInfo, USBDevInfoCleanup); 95 rc = USBSysfsEnumerateHostDevices(&vecDevInfo); 96 96 if (RT_FAILURE(rc)) 97 97 { … … 102 102 RTPrintf ("Listing USB devices detected:\n"); 103 103 USBDeviceInfo *pInfo; 104 VEC_FOR_EACH(& deviceInfo.mvecDevInfo, USBDeviceInfo, pInfo)104 VEC_FOR_EACH(&vecDevInfo, USBDeviceInfo, pInfo) 105 105 { 106 106 char szProduct[1024]; … … 146 146 } 147 147 } 148 VEC_CLEANUP_OBJ(&vecDevInfo); 148 149 VBoxMainHotplugWaiter waiter; 149 150 RTPrintf ("Waiting for a hotplug event for five seconds...\n");
Note:
See TracChangeset
for help on using the changeset viewer.