Changeset 28574 in vbox for trunk/src/VBox/Main/linux
- Timestamp:
- Apr 21, 2010 8:50:48 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/linux/HostHardwareLinux.cpp
r28553 r28574 30 30 #include <HostHardwareLinux.h> 31 31 32 #include <VBox/err.h> 32 33 #include <VBox/log.h> 33 # ifdef VBOX_WITH_DBUS 34 # include <VBox/dbus.h> 35 # endif 34 35 #ifdef VBOX_WITH_DBUS 36 # include <VBox/dbus.h> 37 #endif 36 38 37 39 #include <iprt/dir.h> … … 47 49 #include <iprt/thread.h> /* for RTThreadSleep() */ 48 50 49 #ifdef RT_OS_LINUX 50 # include <sys/types.h> 51 # include <sys/stat.h> 52 # include <unistd.h> 53 # include <fcntl.h> 54 /* bird: This is a hack to work around conflicts between these linux kernel headers 55 * and the GLIBC tcpip headers. They have different declarations of the 4 56 * standard byte order functions. */ 57 // # define _LINUX_BYTEORDER_GENERIC_H 58 # define _LINUX_BYTEORDER_SWABB_H 59 # include <linux/cdrom.h> 60 # include <linux/fd.h> 61 # include <linux/major.h> 62 # include <errno.h> 63 # include <scsi/scsi.h> 64 65 # include <iprt/linux/sysfs.h> 66 #endif /* RT_OS_LINUX */ 67 68 #include <fam.h> 51 #include <linux/cdrom.h> 52 #include <linux/fd.h> 53 #include <linux/major.h> 54 #include <scsi/scsi.h> 55 56 #include <iprt/linux/sysfs.h> 57 58 #ifdef VBOX_USB_WITH_SYSFS 59 # include <fam.h> 60 #endif 69 61 70 62 #include <vector> 63 64 #include <errno.h> 71 65 72 66 /****************************************************************************** … … 99 93 static int getDriveInfoFromSysfs(DriveInfoList *pList, bool isDVD, 100 94 bool *pfSuccess); 95 #ifdef VBOX_USB_WITH_SYSFS 101 96 static int getUSBDeviceInfoFromSysfs(USBDeviceInfoList *pList, bool *pfSuccess); 102 # ifdef VBOX_WITH_DBUS97 # ifdef VBOX_WITH_DBUS 103 98 /* These must be extern to be usable in the RTMemAutoPtr template */ 104 99 extern void VBoxHalShutdown (DBusConnection *pConnection); … … 136 131 static DBusHandlerResult dbusFilterFunction (DBusConnection *pConnection, 137 132 DBusMessage *pMessage, void *pvUser); 138 #endif /* VBOX_WITH_DBUS */ 133 # endif /* VBOX_WITH_DBUS */ 134 #endif /* VBOX_USB_WITH_SYSFS */ 139 135 140 136 … … 1031 1027 try 1032 1028 { 1029 mDeviceList.clear(); 1030 #ifdef VBOX_USB_WITH_SYSFS 1031 # ifdef VBOX_WITH_DBUS 1033 1032 bool halSuccess = false; 1034 mDeviceList.clear();1035 #if defined(RT_OS_LINUX)1036 #ifdef VBOX_WITH_DBUS1037 1033 if ( RT_SUCCESS(rc) 1038 1034 && RT_SUCCESS(RTDBusLoadLib()) … … 1045 1041 if (!success) 1046 1042 success = halSuccess; 1047 # endif /* VBOX_WITH_DBUS defined*/1043 # endif /* VBOX_WITH_DBUS */ 1048 1044 if ( RT_SUCCESS(rc) 1049 1045 && (!success || testing())) 1050 rc = getUSBDeviceInfoFromSysfs(&mDeviceList, &halSuccess); 1051 #endif /* RT_OS_LINUX */ 1046 rc = getUSBDeviceInfoFromSysfs(&mDeviceList, &success); 1047 #else /* !VBOX_USB_WITH_SYSFS */ 1048 NOREF(success); 1049 #endif /* !VBOX_USB_WITH_SYSFS */ 1052 1050 } 1053 1051 catch(std::bad_alloc &e) … … 1059 1057 } 1060 1058 1061 #if defined RT_OS_LINUX&& defined VBOX_WITH_DBUS1059 #if defined VBOX_USB_WITH_SYSFS && defined VBOX_WITH_DBUS 1062 1060 class hotplugDBusImpl : public VBoxMainHotplugWaiterImpl 1063 1061 { … … 1166 1164 mInterrupt = true; 1167 1165 } 1168 #endif /* !(defined RT_OS_LINUX && defined VBOX_WITH_DBUS)*/1166 #endif /* VBOX_USB_WITH_SYSFS && VBOX_WITH_DBUS */ 1169 1167 1170 1168 class hotplugNullImpl : public VBoxMainHotplugWaiterImpl … … 1183 1181 1184 1182 #ifdef VBOX_USB_WITH_SYSFS 1185 1186 /** @todo move these elsewhere, but wait for words of wisdom from the iprt1187 * maintainer first :)1188 * The ideas behind the macros are on the one hand to increase code readability1189 * by reducing the space taken by the error handling (exceptions using pure C1190 * if you like, where a do {} while(0) block replaces the try {} catch() and a1191 * variable at a higher scope remembers the success or failure); and on the1192 * other to reduce duplication in error handling code, hopefully thereby1193 * raising the chances that error paths will actually work.1194 */1195 1196 /**1197 * Store an iprt status code (expected to be a function call with the status1198 * code as its return value) in a variable and execute a break statement if1199 * the status is unsuccessful.1200 * @param rc where to store the value1201 * @param expr the expression returning the status. @a expr will only be1202 * evaluated once by the macro call1203 */1204 #define SETRCBREAK(rc, expr) \1205 if (RT_FAILURE(((rc) = (expr)))) \1206 break; \1207 else do {} while (0)1208 1209 /**1210 * Store an iprt status code (expected to be a function call with the status1211 * code as its return value) in a variable and execute a return statement if1212 * the status is unsuccessful.1213 * @param rc where to store the value1214 * @param expr the expression returning the status. @a expr will only be1215 * evaluated once by the macro call1216 */1217 #define SETRCRETURN(rc, expr) \1218 do \1219 { \1220 (rc) = (expr); \1221 if (RT_FAILURE(rc)) \1222 return (rc); \1223 } while (0)1224 1225 static void testSetRCBreak(void)1226 {1227 int rc = VINF_SUCCESS;1228 do {1229 SETRCBREAK(rc, VERR_WRONG_ORDER);1230 rc = VINF_SUCCESS;1231 } while(0);1232 Assert(rc == VERR_WRONG_ORDER);1233 rc = VERR_GENERAL_FAILURE;1234 do {1235 SETRCBREAK(rc, VINF_BUFFER_OVERFLOW);1236 Assert(rc == VINF_BUFFER_OVERFLOW);1237 rc = VERR_WRONG_ORDER;1238 } while(0);1239 Assert(rc == VERR_WRONG_ORDER);1240 }1241 1242 static int testSetRCReturnWorker(int rc)1243 {1244 int rc2 = VERR_WRONG_ORDER;1245 SETRCRETURN(rc2, rc);1246 Assert(rc == rc2);1247 return VINF_SUCCESS;1248 }1249 1250 static void testSetRCReturn(void)1251 {1252 Assert(testSetRCReturnWorker(VERR_GENERAL_FAILURE) == VERR_GENERAL_FAILURE);1253 AssertRCSuccess(testSetRCReturnWorker(VINF_BUFFER_OVERFLOW));1254 }1255 1183 1256 1184 #define SYSFS_USB_DEVICE_PATH "/dev/bus/usb" … … 1294 1222 { 1295 1223 if (FAMOpen(&mFAMConnection) < 0) 1296 return VERR_ UNRESOLVED_ERROR; /* VERR_FAM_OPEN_FAILED */1224 return VERR_FAM_OPEN_FAILED; 1297 1225 mfFAMInitialised = true; 1298 1226 return VINF_SUCCESS; … … 1305 1233 FAMRequest dummyReq; 1306 1234 if (FAMMonitorDirectory(&mFAMConnection, pszName, &dummyReq, NULL) < 0) 1307 return VERR_ UNRESOLVED_ERROR; /* VERR_FAM_MONITOR_FILE_FAILED */1235 return VERR_FAM_MONITOR_DIRECTORY_FAILED; 1308 1236 return VINF_SUCCESS; 1309 1237 } … … 1315 1243 int oldFD = FAMCONNECTION_GETFD(&mFAMConnection); 1316 1244 FAMCONNECTION_GETFD(&mFAMConnection) = -1; 1317 Assert(monitorDirectoryFAM(NULL) == VERR_ UNRESOLVED_ERROR);1245 Assert(monitorDirectoryFAM(NULL) == VERR_FAM_MONITOR_DIRECTORY_FAILED); 1318 1246 FAMCONNECTION_GETFD(&mFAMConnection) = oldFD; 1319 1247 } … … 1328 1256 mfFAMInitialised = false; 1329 1257 } 1258 1259 /** Read the wakeup string from the wakeup pipe */ 1260 int drainWakeupPipe(void); 1330 1261 public: 1331 1262 hotplugSysfsFAMImpl(void); … … 1361 1292 * no-op. */ 1362 1293 term(); 1363 /** Unit test our macros above */ 1364 testSetRCBreak(); 1365 testSetRCReturn(); 1294 /* For now this probing method should only be used if nothing else is 1295 * available */ 1296 if (!testing()) 1297 { 1298 #ifndef VBOX_USB_WITH_SYSFS_BY_DEFAULT 1299 Assert(!RTFileExists("/proc/bus/usb/devices")); 1300 #endif 1301 #ifdef VBOX_WITH_DBUS 1302 Assert(!hotplugDBusImpl::HalAvailable()); 1303 #endif 1304 } 1366 1305 #endif 1367 1306 int rc; 1368 1307 do { 1369 SETRCBREAK(rc, RTPipeCreate(&mhWakeupPipeR, &mhWakeupPipeW, 0)); 1370 SETRCBREAK(rc, openFAM()); 1371 SETRCBREAK(rc, RTSocketFromNative 1372 (&mhFAMFD, FAMCONNECTION_GETFD(&mFAMConnection))); 1373 SETRCBREAK(rc, monitorDirectoryFAM(SYSFS_USB_DEVICE_PATH)); 1374 SETRCBREAK(rc, RTPollSetCreate(&mhPollSet)); 1375 SETRCBREAK(rc, RTPollSetAddSocket 1376 (mhPollSet, mhFAMFD, RTPOLL_EVT_READ, FAMFD_ID)); 1377 SETRCBREAK(rc, RTPollSetAddPipe 1378 (mhPollSet, mhWakeupPipeR, RTPOLL_EVT_READ, RPIPE_ID)); 1308 if (RT_FAILURE(rc = RTPipeCreate(&mhWakeupPipeR, &mhWakeupPipeW, 0))) 1309 break; 1310 if (RT_FAILURE(rc = openFAM())) 1311 break; 1312 if (RT_FAILURE(rc = RTSocketFromNative 1313 (&mhFAMFD, FAMCONNECTION_GETFD(&mFAMConnection)))) 1314 break; 1315 if (RT_FAILURE(rc = monitorDirectoryFAM(SYSFS_USB_DEVICE_PATH))) 1316 break; 1317 if (RT_FAILURE(rc = RTPollSetCreate(&mhPollSet))) 1318 break; 1319 if (RT_FAILURE(rc = RTPollSetAddSocket 1320 (mhPollSet, mhFAMFD, RTPOLL_EVT_READ, FAMFD_ID))) 1321 break; 1322 if (RT_FAILURE(rc = RTPollSetAddPipe 1323 (mhPollSet, mhWakeupPipeR, RTPOLL_EVT_READ, RPIPE_ID))) 1324 break; 1379 1325 #ifdef DEBUG 1380 1326 /** Other tests */ … … 1399 1345 } 1400 1346 1347 /** Does a FAM event code mean that the available devices have (probably) 1348 * changed? */ 1349 static int sysfsGetStatusForFAMCode(enum FAMCodes enmCode) 1350 { 1351 if (enmCode == FAMExists || enmCode == FAMEndExist) 1352 return VERR_TRY_AGAIN; 1353 return VINF_SUCCESS; 1354 } 1355 1356 int hotplugSysfsFAMImpl::drainWakeupPipe(void) 1357 { 1358 char szBuf[sizeof(SYSFS_WAKEUP_STRING)]; 1359 int rc = RTPipeRead(mhWakeupPipeR, szBuf, sizeof(szBuf), NULL); 1360 AssertRC(rc); 1361 return VINF_SUCCESS; 1362 } 1363 1401 1364 int hotplugSysfsFAMImpl::Wait(RTMSINTERVAL aMillies) 1402 1365 { … … 1408 1371 return VERR_NOT_SUPPORTED; 1409 1372 /* timeout returns */ 1410 SETRCRETURN(rc, RTPoll(mhPollSet, aMillies, NULL, &id)); 1373 if (RT_FAILURE(rc = RTPoll(mhPollSet, aMillies, NULL, &id))) 1374 return rc; 1411 1375 if (id == RPIPE_ID) 1412 { 1413 /* drain the pipe */ 1414 char szBuf[sizeof(SYSFS_WAKEUP_STRING)]; 1415 rc = RTPipeRead(mhWakeupPipeR, szBuf, sizeof(szBuf), NULL); 1416 AssertRC(rc); 1417 return VINF_SUCCESS; 1418 } 1376 return drainWakeupPipe(); 1419 1377 AssertReturn(id == FAMFD_ID, VERR_NOT_SUPPORTED); 1420 1378 /* Samba re-opens the connection to FAM if this happens. */ 1421 1379 AssertReturn(FAMNextEvent(&mFAMConnection, &ev) == 1, 1422 1380 VERR_NOT_SUPPORTED); 1423 switch(ev.code) 1424 { 1425 case FAMExists: 1426 case FAMEndExist: 1427 return VERR_TRY_AGAIN; 1428 default: 1429 break; 1430 } 1431 return VINF_SUCCESS; 1381 return sysfsGetStatusForFAMCode(ev.code); 1432 1382 } 1433 1383 … … 1445 1395 VBoxMainHotplugWaiter::VBoxMainHotplugWaiter(void) 1446 1396 { 1447 #if defined RT_OS_LINUX && defined VBOX_WITH_DBUS 1397 #ifdef VBOX_USB_WITH_SYSFS 1398 # ifdef VBOX_WITH_DBUS 1448 1399 if (hotplugDBusImpl::HalAvailable()) 1449 1400 { … … 1451 1402 return; 1452 1403 } 1453 #endif /* !(defined RT_OS_LINUX && defined VBOX_WITH_DBUS) */ 1454 #if defined VBOX_USB_WITH_SYSFS 1404 # endif /* VBOX_WITH_DBUS */ 1455 1405 if (hotplugSysfsFAMImpl::SysfsAvailable()) 1456 1406 { … … 1458 1408 return; 1459 1409 } 1460 #endif /* !(defined RT_OS_LINUX && defined VBOX_WITH_DBUS)*/1410 #endif /* VBOX_USB_WITH_SYSFS */ 1461 1411 mImpl = new hotplugNullImpl; 1462 1412 } 1463 1413 1414 #ifdef VBOX_USB_WITH_SYSFS 1464 1415 class sysfsPathHandler 1465 1416 { … … 1672 1623 return rc; 1673 1624 } 1674 1675 1676 #if defined (RT_OS_LINUX) && defined(VBOX_WITH_DBUS)1625 #endif /* VBOX_USB_WITH_SYSFS */ 1626 1627 #if defined VBOX_USB_WITH_SYSFS && defined VBOX_WITH_DBUS 1677 1628 /** Wrapper class around DBusError for automatic cleanup */ 1678 1629 class autoDBusError … … 2443 2394 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 2444 2395 } 2445 #endif /* RT_OS_LINUX&& VBOX_WITH_DBUS */2446 2396 #endif /* VBOX_USB_WITH_SYSFS && VBOX_WITH_DBUS */ 2397
Note:
See TracChangeset
for help on using the changeset viewer.