VirtualBox

Changeset 28315 in vbox


Ignore:
Timestamp:
Apr 14, 2010 4:34:00 PM (15 years ago)
Author:
vboxsync
Message:

Main/HostHardwareLinux: fix a burn when VBOX_WITH_DBUS is not defined

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/linux/HostHardwareLinux.cpp

    r28313 r28315  
    853853}
    854854
    855 /**
    856  * Helper function to query the sysfs subsystem for information about USB
    857  * devices attached to the system.
    858  * @returns iprt status code
    859  * @param   pList      where to add information about the drives detected
    860  * @param   pfSuccess  Did we find anything?
    861  *
    862  * @returns IPRT status code
    863  */
    864 static int getUSBDeviceInfoFromSysfs(USBDeviceInfoList *pList,
    865                                      bool *pfSuccess)
    866 {
    867     AssertPtrReturn(pList, VERR_INVALID_POINTER);
    868     AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */
    869     LogFlowFunc (("pList=%p, pfSuccess=%p\n",
    870                   pList, pfSuccess));
    871     size_t cDevices = pList->size();
    872     matchUSBDevice devHandler(pList);
    873     int rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &devHandler);
    874     do {
    875         if (RT_FAILURE(rc))
    876             break;
    877         for (USBDeviceInfoList::iterator pInfo = pList->begin();
    878              pInfo != pList->end(); ++pInfo)
    879         {
    880             matchUSBInterface ifaceHandler(&*pInfo);
    881             rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &ifaceHandler);
    882             if (RT_FAILURE(rc))
    883                 break;
    884         }
    885     } while(0);
    886     if (RT_FAILURE(rc))
    887         /* Clean up again */
    888         while (pList->size() > cDevices)
    889             pList->pop_back();
    890     if (pfSuccess)
    891         *pfSuccess = RT_SUCCESS(rc);
    892     LogFlow (("rc=%Rrc\n", rc));
    893     return rc;
    894 }
    895855
    896856/** Structure for holding information about a drive we have found */
     
    11971157
    11981158
    1199 #if defined(RT_OS_LINUX) && defined(VBOX_WITH_DBUS)
    1200 /** Wrapper class around DBusError for automatic cleanup */
    1201 class autoDBusError
    1202 {
    1203     DBusError mError;
    1204 public:
    1205     autoDBusError () { dbus_error_init (&mError); }
    1206     ~autoDBusError ()
    1207     {
    1208         if (IsSet())
    1209             dbus_error_free (&mError);
    1210     }
    1211     DBusError &get () { return mError; }
    1212     bool IsSet ()
    1213     {
    1214         Assert((mError.name == NULL) == (mError.message == NULL));
    1215         return (mError.name != NULL);
    1216     }
    1217     bool HasName (const char *pcszName)
    1218     {
    1219         Assert((mError.name == NULL) == (mError.message == NULL));
    1220         return (RTStrCmp (mError.name, pcszName) == 0);
    1221     }
    1222     void FlowLog ()
    1223     {
    1224         if (IsSet ())
    1225             LogFlow(("DBus error %s: %s\n", mError.name, mError.message));
    1226     }
    1227 };
    1228 
    1229 /**
    1230  * Helper function for setting up a connection to the DBus daemon and
    1231  * registering with the hal service.
    1232  *
    1233  * @note If libdbus is being loaded at runtime then be sure to call
    1234  *       VBoxDBusCheckPresence before calling this.
    1235  * @returns iprt status code
    1236  * @param   ppConnection  where to store the connection handle
    1237  */
    1238 /* static */
    1239 int halInit (RTMemAutoPtr <DBusConnection, VBoxHalShutdown> *pConnection)
    1240 {
    1241     AssertReturn(VALID_PTR (pConnection), VERR_INVALID_POINTER);
    1242     LogFlowFunc (("pConnection=%p\n", pConnection));
    1243     int rc = VINF_SUCCESS;
    1244     bool halSuccess = true;
    1245     autoDBusError dbusError;
    1246 
    1247     RTMemAutoPtr <DBusConnection, VBoxDBusConnectionUnref> dbusConnection;
    1248     dbusConnection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbusError.get());
    1249     if (!dbusConnection)
    1250         halSuccess = false;
    1251     if (halSuccess)
    1252     {
    1253         dbus_connection_set_exit_on_disconnect (dbusConnection.get(), false);
    1254         halSuccess = dbus_bus_name_has_owner (dbusConnection.get(),
    1255                                               "org.freedesktop.Hal", &dbusError.get());
    1256     }
    1257     if (halSuccess)
    1258     {
    1259         dbus_bus_add_match (dbusConnection.get(),
    1260                             "type='signal',"
    1261                             "interface='org.freedesktop.Hal.Manager',"
    1262                             "sender='org.freedesktop.Hal',"
    1263                             "path='/org/freedesktop/Hal/Manager'",
    1264                             &dbusError.get());
    1265         halSuccess = !dbusError.IsSet();
    1266     }
    1267     if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
    1268         rc = VERR_NO_MEMORY;
    1269     if (halSuccess)
    1270         *pConnection = dbusConnection.release();
    1271     LogFlowFunc(("rc=%Rrc, (*pConnection).get()=%p\n", rc, (*pConnection).get()));
    1272     dbusError.FlowLog();
    1273     return rc;
    1274 }
    1275 
    1276 /**
    1277  * Helper function for setting up a private connection to the DBus daemon and
    1278  * registering with the hal service.  Private connections are considered
    1279  * unsociable and should not be used unnecessarily (as per the DBus API docs).
    1280  *
    1281  * @note If libdbus is being loaded at runtime then be sure to call
    1282  *       VBoxDBusCheckPresence before calling this.
    1283  * @returns iprt status code
    1284  * @param   pConnection  where to store the connection handle
    1285  */
    1286 /* static */
    1287 int halInitPrivate (RTMemAutoPtr <DBusConnection, VBoxHalShutdownPrivate> *pConnection)
    1288 {
    1289     AssertReturn(VALID_PTR (pConnection), VERR_INVALID_POINTER);
    1290     LogFlowFunc (("pConnection=%p\n", pConnection));
    1291     int rc = VINF_SUCCESS;
    1292     bool halSuccess = true;
    1293     autoDBusError dbusError;
    1294 
    1295     RTMemAutoPtr <DBusConnection, VBoxDBusConnectionCloseAndUnref> dbusConnection;
    1296     dbusConnection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &dbusError.get());
    1297     if (!dbusConnection)
    1298         halSuccess = false;
    1299     if (halSuccess)
    1300     {
    1301         dbus_connection_set_exit_on_disconnect (dbusConnection.get(), false);
    1302         halSuccess = dbus_bus_name_has_owner (dbusConnection.get(),
    1303                                               "org.freedesktop.Hal", &dbusError.get());
    1304     }
    1305     if (halSuccess)
    1306     {
    1307         dbus_bus_add_match (dbusConnection.get(),
    1308                             "type='signal',"
    1309                             "interface='org.freedesktop.Hal.Manager',"
    1310                             "sender='org.freedesktop.Hal',"
    1311                             "path='/org/freedesktop/Hal/Manager'",
    1312                             &dbusError.get());
    1313         halSuccess = !dbusError.IsSet();
    1314     }
    1315     if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
    1316         rc = VERR_NO_MEMORY;
    1317     if (halSuccess)
    1318         *pConnection = dbusConnection.release();
    1319     LogFlowFunc(("rc=%Rrc, (*pConnection).get()=%p\n", rc, (*pConnection).get()));
    1320     dbusError.FlowLog();
    1321     return rc;
    1322 }
    1323 
    1324 /**
    1325  * Helper function for shutting down a connection to DBus and hal.
    1326  * @param   pConnection  the connection handle
    1327  */
    1328 /* extern */
    1329 void VBoxHalShutdown (DBusConnection *pConnection)
    1330 {
    1331     AssertReturnVoid(VALID_PTR (pConnection));
    1332     LogFlowFunc (("pConnection=%p\n", pConnection));
    1333     autoDBusError dbusError;
    1334 
    1335     dbus_bus_remove_match (pConnection,
    1336                            "type='signal',"
    1337                            "interface='org.freedesktop.Hal.Manager',"
    1338                            "sender='org.freedesktop.Hal',"
    1339                            "path='/org/freedesktop/Hal/Manager'",
    1340                            &dbusError.get());
    1341     dbus_connection_unref (pConnection);
    1342     LogFlowFunc(("returning\n"));
    1343     dbusError.FlowLog();
    1344 }
    1345 
    1346 /**
    1347  * Helper function for shutting down a private connection to DBus and hal.
    1348  * @param   pConnection  the connection handle
    1349  */
    1350 /* extern */
    1351 void VBoxHalShutdownPrivate (DBusConnection *pConnection)
    1352 {
    1353     AssertReturnVoid(VALID_PTR (pConnection));
    1354     LogFlowFunc (("pConnection=%p\n", pConnection));
    1355     autoDBusError dbusError;
    1356 
    1357     dbus_bus_remove_match (pConnection,
    1358                            "type='signal',"
    1359                            "interface='org.freedesktop.Hal.Manager',"
    1360                            "sender='org.freedesktop.Hal',"
    1361                            "path='/org/freedesktop/Hal/Manager'",
    1362                            &dbusError.get());
    1363     dbus_connection_close (pConnection);
    1364     dbus_connection_unref (pConnection);
    1365     LogFlowFunc(("returning\n"));
    1366     dbusError.FlowLog();
    1367 }
    1368 
    1369 /** Wrapper around dbus_connection_unref.  We need this to use it as a real
    1370  * function in auto pointers, as a function pointer won't wash here. */
    1371 /* extern */
    1372 void VBoxDBusConnectionUnref(DBusConnection *pConnection)
    1373 {
    1374     dbus_connection_unref(pConnection);
    1375 }
    1376 
    1377 /**
    1378  * This function closes and unrefs a private connection to dbus.  It should
    1379  * only be called once no-one else is referencing the connection.
    1380  */
    1381 /* extern */
    1382 void VBoxDBusConnectionCloseAndUnref(DBusConnection *pConnection)
    1383 {
    1384     dbus_connection_close(pConnection);
    1385     dbus_connection_unref(pConnection);
    1386 }
    1387 
    1388 /** Wrapper around dbus_message_unref.  We need this to use it as a real
    1389  * function in auto pointers, as a function pointer won't wash here. */
    1390 /* extern */
    1391 void VBoxDBusMessageUnref(DBusMessage *pMessage)
    1392 {
    1393     dbus_message_unref(pMessage);
    1394 }
    1395 
    1396 /**
    1397  * Find the UDIs of hal entries that contain Key=Value property.
    1398  * @returns iprt status code.  If a non-fatal error occurs, we return success
    1399  *          but reset pMessage to NULL.
    1400  * @param   pConnection an initialised connection DBus
    1401  * @param   pszKey      the property key
    1402  * @param   pszValue    the property value
    1403  * @param   pMessage    where to store the return DBus message.  This must be
    1404  *                      parsed to get at the UDIs.  NOT optional.
    1405  */
    1406 /* static */
    1407 int halFindDeviceStringMatch (DBusConnection *pConnection, const char *pszKey,
    1408                               const char *pszValue,
    1409                               RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage)
    1410 {
    1411     AssertReturn(   VALID_PTR (pConnection) && VALID_PTR (pszKey)
    1412                  && VALID_PTR (pszValue) && VALID_PTR (pMessage),
    1413                  VERR_INVALID_POINTER);
    1414     LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMessage=%p\n",
    1415                   pConnection, pszKey, pszValue, pMessage));
    1416     int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
    1417     bool halSuccess = true;  /* We set this to false to abort the operation. */
    1418     autoDBusError dbusError;
    1419 
    1420     RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
    1421     if (halSuccess && RT_SUCCESS(rc))
    1422     {
    1423         message = dbus_message_new_method_call ("org.freedesktop.Hal",
    1424                                                 "/org/freedesktop/Hal/Manager",
    1425                                                 "org.freedesktop.Hal.Manager",
    1426                                                 "FindDeviceStringMatch");
    1427         if (!message)
    1428             rc = VERR_NO_MEMORY;
    1429     }
    1430     if (halSuccess && RT_SUCCESS(rc))
    1431     {
    1432         DBusMessageIter iterAppend;
    1433         dbus_message_iter_init_append (message.get(), &iterAppend);
    1434         dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszKey);
    1435         dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszValue);
    1436         reply = dbus_connection_send_with_reply_and_block (pConnection,
    1437                                                             message.get(), -1,
    1438                                                             &dbusError.get());
    1439         if (!reply)
    1440             halSuccess = false;
    1441     }
    1442     *pMessage = reply.release ();
    1443     LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get()));
    1444     dbusError.FlowLog();
    1445     return rc;
    1446 }
    1447 
    1448 /**
    1449  * Find the UDIs of hal entries that contain Key=Value property and return the
    1450  * result on the end of a vector of iprt::MiniString.
    1451  * @returns iprt status code.  If a non-fatal error occurs, we return success
    1452  *          but set *pfSuccess to false.
    1453  * @param   pConnection an initialised connection DBus
    1454  * @param   pszKey      the property key
    1455  * @param   pszValue    the property value
    1456  * @param   pMatches    pointer to an array of iprt::MiniString to append the
    1457  *                      results to.  NOT optional.
    1458  * @param   pfSuccess   will be set to true if the operation succeeds
    1459  */
    1460 /* static */
    1461 int halFindDeviceStringMatchVector (DBusConnection *pConnection,
    1462                                     const char *pszKey, const char *pszValue,
    1463                                     std::vector<iprt::MiniString> *pMatches,
    1464                                     bool *pfSuccess)
    1465 {
    1466     AssertPtrReturn (pConnection, VERR_INVALID_POINTER);
    1467     AssertPtrReturn (pszKey, VERR_INVALID_POINTER);
    1468     AssertPtrReturn (pszValue, VERR_INVALID_POINTER);
    1469     AssertPtrReturn (pMatches, VERR_INVALID_POINTER);
    1470     AssertReturn(pfSuccess == NULL || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
    1471     LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMatches=%p, pfSuccess=%p\n",
    1472                   pConnection, pszKey, pszValue, pMatches, pfSuccess));
    1473     int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
    1474     bool halSuccess = true;  /* We set this to false to abort the operation. */
    1475 
    1476     RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind;
    1477     DBusMessageIter iterFind, iterUdis;
    1478 
    1479     if (halSuccess && RT_SUCCESS(rc))
    1480     {
    1481         rc = halFindDeviceStringMatch (pConnection, pszKey, pszValue,
    1482                                        &replyFind);
    1483         if (!replyFind)
    1484             halSuccess = false;
    1485     }
    1486     if (halSuccess && RT_SUCCESS(rc))
    1487     {
    1488         dbus_message_iter_init (replyFind.get(), &iterFind);
    1489         if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
    1490             halSuccess = false;
    1491     }
    1492     if (halSuccess && RT_SUCCESS(rc))
    1493         dbus_message_iter_recurse (&iterFind, &iterUdis);
    1494     for (;    halSuccess && RT_SUCCESS(rc)
    1495            && dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
    1496          dbus_message_iter_next(&iterUdis))
    1497     {
    1498         /* Now get all UDIs from the iterator */
    1499         const char *pszUdi;
    1500         dbus_message_iter_get_basic (&iterUdis, &pszUdi);
    1501         try
    1502         {
    1503             pMatches->push_back(pszUdi);
    1504         }
    1505         catch(std::bad_alloc &e)
    1506         {
    1507             rc = VERR_NO_MEMORY;
    1508         }
    1509     }
    1510     if (pfSuccess != NULL)
    1511         *pfSuccess = halSuccess;
    1512     LogFlow (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
    1513     return rc;
    1514 }
    1515 
    1516 /**
    1517  * Read a set of string properties for a device.  If some of the properties are
    1518  * not of type DBUS_TYPE_STRING or do not exist then a NULL pointer will be
    1519  * returned for them.
    1520  * @returns iprt status code.  If the operation failed for non-fatal reasons
    1521  *          then we return success and leave pMessage untouched - reset it
    1522  *          before the call to detect this.
    1523  * @param   pConnection  an initialised connection DBus
    1524  * @param   pszUdi       the Udi of the device
    1525  * @param   cProps       the number of property values to look up
    1526  * @param   papszKeys    the keys of the properties to be looked up
    1527  * @param   papszValues  where to store the values of the properties.  The
    1528  *                       strings returned will be valid until the message
    1529  *                       returned in @a ppMessage is freed.  Undefined if
    1530  *                       the message is NULL.
    1531  * @param   pMessage     where to store the return DBus message.  The caller
    1532  *                       is responsible for freeing this once they have
    1533  *                       finished with the value strings.  NOT optional.
    1534  */
    1535 /* static */
    1536 int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi,
    1537                            size_t cProps, const char **papszKeys,
    1538                            char **papszValues,
    1539                            RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage)
    1540 {
    1541     AssertReturn(   VALID_PTR (pConnection) && VALID_PTR (pszUdi)
    1542                  && VALID_PTR (papszKeys) && VALID_PTR (papszValues)
    1543                  && VALID_PTR (pMessage),
    1544                  VERR_INVALID_POINTER);
    1545     LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, papszValues=%p, pMessage=%p\n",
    1546                   pConnection, pszUdi, cProps, papszKeys, papszValues, pMessage));
    1547     int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
    1548     bool halSuccess = true;  /* We set this to false to abort the operation. */
    1549     autoDBusError dbusError;
    1550 
    1551     RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
    1552     DBusMessageIter iterGet, iterProps;
    1553 
    1554     /* Initialise the return array to NULLs */
    1555     for (size_t i = 0; i < cProps; ++i)
    1556         papszValues[i] = NULL;
    1557 
    1558     /* Send a GetAllProperties message to hald */
    1559     message = dbus_message_new_method_call ("org.freedesktop.Hal", pszUdi,
    1560                                             "org.freedesktop.Hal.Device",
    1561                                             "GetAllProperties");
    1562     if (!message)
    1563         rc = VERR_NO_MEMORY;
    1564     if (halSuccess && RT_SUCCESS(rc))
    1565     {
    1566         reply = dbus_connection_send_with_reply_and_block (pConnection,
    1567                                                            message.get(), -1,
    1568                                                            &dbusError.get());
    1569         if (!reply)
    1570             halSuccess = false;
    1571     }
    1572 
    1573     /* Parse the reply */
    1574     if (halSuccess && RT_SUCCESS(rc))
    1575     {
    1576         dbus_message_iter_init (reply.get(), &iterGet);
    1577         if (   dbus_message_iter_get_arg_type (&iterGet) != DBUS_TYPE_ARRAY
    1578             && dbus_message_iter_get_element_type (&iterGet) != DBUS_TYPE_DICT_ENTRY)
    1579             halSuccess = false;
    1580     }
    1581     if (halSuccess && RT_SUCCESS(rc))
    1582         dbus_message_iter_recurse (&iterGet, &iterProps);
    1583     /* Go through all entries in the reply and see if any match our keys. */
    1584     while (   halSuccess && RT_SUCCESS(rc)
    1585            &&    dbus_message_iter_get_arg_type (&iterProps)
    1586               == DBUS_TYPE_DICT_ENTRY)
    1587     {
    1588         const char *pszKey;
    1589         DBusMessageIter iterEntry, iterValue;
    1590         dbus_message_iter_recurse (&iterProps, &iterEntry);
    1591         dbus_message_iter_get_basic (&iterEntry, &pszKey);
    1592         dbus_message_iter_next (&iterEntry);
    1593         dbus_message_iter_recurse (&iterEntry, &iterValue);
    1594         /* Fill in any matches. */
    1595         for (size_t i = 0; i < cProps; ++i)
    1596             if (strcmp (pszKey, papszKeys[i]) == 0)
    1597             {
    1598                 if (dbus_message_iter_get_arg_type (&iterValue) == DBUS_TYPE_STRING)
    1599                     dbus_message_iter_get_basic (&iterValue, &papszValues[i]);
    1600             }
    1601         dbus_message_iter_next (&iterProps);
    1602     }
    1603     if (RT_SUCCESS(rc) && halSuccess)
    1604         *pMessage = reply.release();
    1605     if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
    1606         rc = VERR_NO_MEMORY;
    1607     LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get()));
    1608     dbusError.FlowLog();
    1609     return rc;
    1610 }
    1611 
    1612 /**
    1613  * Read a set of string properties for a device.  If some properties do not
    1614  * exist or are not of type DBUS_TYPE_STRING, we will still fetch the others.
    1615  * @returns iprt status code.  If the operation failed for non-fatal reasons
    1616  *          then we return success and set *pfSuccess to false.
    1617  * @param   pConnection  an initialised connection DBus
    1618  * @param   pszUdi       the Udi of the device
    1619  * @param   cProps       the number of property values to look up
    1620  * @param   papszKeys    the keys of the properties to be looked up
    1621  * @param   pMatches     pointer to an empty array of iprt::MiniString to append the
    1622  *                       results to.  NOT optional.
    1623  * @param   pfMatches    pointer to an array of boolean values indicating
    1624  *                       whether the respective property is a string.  If this
    1625  *                       is not supplied then all properties must be strings
    1626  *                       for the operation to be considered successful
    1627  * @param   pfSuccess    will be set to true if the operation succeeds
    1628  */
    1629 /* static */
    1630 int halGetPropertyStringsVector (DBusConnection *pConnection,
    1631                                  const char *pszUdi, size_t cProps,
    1632                                  const char **papszKeys,
    1633                                  std::vector<iprt::MiniString> *pMatches,
    1634                                  bool *pfMatches, bool *pfSuccess)
    1635 {
    1636     AssertPtrReturn (pConnection, VERR_INVALID_POINTER);
    1637     AssertPtrReturn (pszUdi, VERR_INVALID_POINTER);
    1638     AssertPtrReturn (papszKeys, VERR_INVALID_POINTER);
    1639     AssertPtrReturn (pMatches, VERR_INVALID_POINTER);
    1640     AssertReturn((pfMatches == NULL) || VALID_PTR (pfMatches), VERR_INVALID_POINTER);
    1641     AssertReturn((pfSuccess == NULL) || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
    1642     AssertReturn(pMatches->empty(), VERR_INVALID_PARAMETER);
    1643     LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, pMatches=%p, pfMatches=%p, pfSuccess=%p\n",
    1644                   pConnection, pszUdi, cProps, papszKeys, pMatches, pfMatches, pfSuccess));
    1645     RTMemAutoPtr <char *> values(cProps);
    1646     RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message;
    1647     bool halSuccess = true;
    1648     int rc = halGetPropertyStrings (pConnection, pszUdi, cProps, papszKeys,
    1649                                     values.get(), &message);
    1650     if (!message)
    1651         halSuccess = false;
    1652     for (size_t i = 0; RT_SUCCESS(rc) && halSuccess && i < cProps; ++i)
    1653     {
    1654         bool fMatches = values[i] != NULL;
    1655         if (pfMatches != NULL)
    1656             pfMatches[i] = fMatches;
    1657         else
    1658             halSuccess = fMatches;
    1659         try
    1660         {
    1661             pMatches->push_back(fMatches ? values[i] : "");
    1662         }
    1663         catch(std::bad_alloc &e)
    1664         {
    1665             rc = VERR_NO_MEMORY;
    1666         }
    1667     }
    1668     if (pfSuccess != NULL)
    1669         *pfSuccess = halSuccess;
    1670     if (RT_SUCCESS(rc) && halSuccess)
    1671     {
    1672         Assert(pMatches->size() == cProps);
    1673         AssertForEach(j, size_t, 0, cProps,    (pfMatches == NULL)
    1674                                             || (pfMatches[j] == true)
    1675                                             || ((pfMatches[j] == false) && (pMatches[j].size() == 0)));
    1676     }
    1677     LogFlowFunc (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
    1678     return rc;
    1679 }
    1680 
    1681 
    1682 /**
    1683  * Helper function to query the hal subsystem for information about USB devices
    1684  * attached to the system.
    1685  * @returns iprt status code
    1686  * @param   pList      where to add information about the devices detected
    1687  * @param   pfSuccess  will be set to true if all interactions with hal
    1688  *                     succeeded and to false otherwise.  Optional.
    1689  *
    1690  * @returns IPRT status code
    1691  */
    1692 /* static */
    1693 int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
    1694 {
    1695     AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
    1696                  VERR_INVALID_POINTER);
    1697     LogFlowFunc (("pList=%p, pfSuccess=%p\n", pList, pfSuccess));
    1698     int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
    1699     bool halSuccess = true;  /* We set this to false to abort the operation. */
    1700     autoDBusError dbusError;
    1701 
    1702     RTMemAutoPtr<DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
    1703     RTMemAutoPtr<DBusConnection, VBoxHalShutdown> dbusConnection;
    1704     DBusMessageIter iterFind, iterUdis;
    1705 
    1706     /* Connect to hal */
    1707     rc = halInit (&dbusConnection);
    1708     if (!dbusConnection)
    1709         halSuccess = false;
    1710     /* Get an array of all devices in the usb_device subsystem */
    1711     if (halSuccess && RT_SUCCESS(rc))
    1712     {
    1713         rc = halFindDeviceStringMatch(dbusConnection.get(), "info.subsystem",
    1714                                       "usb_device", &replyFind);
    1715         if (!replyFind)
    1716             halSuccess = false;
    1717     }
    1718     if (halSuccess && RT_SUCCESS(rc))
    1719     {
    1720         dbus_message_iter_init(replyFind.get(), &iterFind);
    1721         if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
    1722             halSuccess = false;
    1723     }
    1724     /* Recurse down into the array and query interesting information about the
    1725      * entries. */
    1726     if (halSuccess && RT_SUCCESS(rc))
    1727         dbus_message_iter_recurse(&iterFind, &iterUdis);
    1728     for (;    halSuccess && RT_SUCCESS(rc)
    1729            && dbus_message_iter_get_arg_type(&iterUdis) == DBUS_TYPE_STRING;
    1730          dbus_message_iter_next(&iterUdis))
    1731     {
    1732         /* Get the device node and the sysfs path for the current entry. */
    1733         const char *pszUdi;
    1734         dbus_message_iter_get_basic (&iterUdis, &pszUdi);
    1735         static const char *papszKeys[] = { "linux.device_file", "linux.sysfs_path" };
    1736         char *papszValues[RT_ELEMENTS(papszKeys)];
    1737         rc = halGetPropertyStrings(dbusConnection.get(), pszUdi, RT_ELEMENTS(papszKeys),
    1738                                    papszKeys, papszValues, &replyGet);
    1739         const char *pszDevice = papszValues[0], *pszSysfsPath = papszValues[1];
    1740         /* Get the interfaces. */
    1741         if (!!replyGet && pszDevice && pszSysfsPath)
    1742         {
    1743             USBDeviceInfo info(pszDevice, pszSysfsPath);
    1744             bool ifaceSuccess = true;  /* If we can't get the interfaces, just
    1745                                         * skip this one device. */
    1746             rc = getUSBInterfacesFromHal(&info.mInterfaces, pszUdi, &ifaceSuccess);
    1747             if (RT_SUCCESS(rc) && halSuccess && ifaceSuccess)
    1748                 try
    1749                 {
    1750                     pList->push_back(info);
    1751                 }
    1752                 catch(std::bad_alloc &e)
    1753                 {
    1754                     rc = VERR_NO_MEMORY;
    1755                 }
    1756         }
    1757     }
    1758     if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
    1759         rc = VERR_NO_MEMORY;
    1760     if (pfSuccess != NULL)
    1761         *pfSuccess = halSuccess;
    1762     LogFlow(("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
    1763     dbusError.FlowLog();
    1764     return rc;
    1765 }
    1766 
    1767 /**
    1768  * Helper function to query the hal subsystem for information about USB devices
    1769  * attached to the system, using the older API.
    1770  * @returns iprt status code
    1771  * @param   pList      where to add information about the devices detected
    1772  * @param   pfSuccess  will be set to true if all interactions with hal
    1773  *                     succeeded and to false otherwise.  Optional.
    1774  *
    1775  * @returns IPRT status code
    1776  */
    1777 /* static */
    1778 int getOldUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
    1779 {
    1780     AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
    1781                  VERR_INVALID_POINTER);
    1782     LogFlowFunc (("pList=%p, pfSuccess=%p\n", pList, pfSuccess));
    1783     int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
    1784     bool halSuccess = true;  /* We set this to false to abort the operation. */
    1785     autoDBusError dbusError;
    1786 
    1787     RTMemAutoPtr<DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
    1788     RTMemAutoPtr<DBusConnection, VBoxHalShutdown> dbusConnection;
    1789     DBusMessageIter iterFind, iterUdis;
    1790 
    1791     /* Connect to hal */
    1792     rc = halInit(&dbusConnection);
    1793     if (!dbusConnection)
    1794         halSuccess = false;
    1795     /* Get an array of all devices in the usb_device subsystem */
    1796     if (halSuccess && RT_SUCCESS(rc))
    1797     {
    1798         rc = halFindDeviceStringMatch(dbusConnection.get(), "info.category",
    1799                                        "usbraw", &replyFind);
    1800         if (!replyFind)
    1801             halSuccess = false;
    1802     }
    1803     if (halSuccess && RT_SUCCESS(rc))
    1804     {
    1805         dbus_message_iter_init(replyFind.get(), &iterFind);
    1806         if (dbus_message_iter_get_arg_type(&iterFind) != DBUS_TYPE_ARRAY)
    1807             halSuccess = false;
    1808     }
    1809     /* Recurse down into the array and query interesting information about the
    1810      * entries. */
    1811     if (halSuccess && RT_SUCCESS(rc))
    1812         dbus_message_iter_recurse(&iterFind, &iterUdis);
    1813     for (;    halSuccess && RT_SUCCESS(rc)
    1814            && dbus_message_iter_get_arg_type(&iterUdis) == DBUS_TYPE_STRING;
    1815          dbus_message_iter_next(&iterUdis))
    1816     {
    1817         /* Get the device node and the sysfs path for the current entry. */
    1818         const char *pszUdi;
    1819         dbus_message_iter_get_basic(&iterUdis, &pszUdi);
    1820         static const char *papszKeys[] = { "linux.device_file", "info.parent" };
    1821         char *papszValues[RT_ELEMENTS(papszKeys)];
    1822         rc = halGetPropertyStrings(dbusConnection.get(), pszUdi, RT_ELEMENTS(papszKeys),
    1823                                    papszKeys, papszValues, &replyGet);
    1824         const char *pszDevice = papszValues[0], *pszSysfsPath = papszValues[1];
    1825         /* Get the interfaces. */
    1826         if (!!replyGet && pszDevice && pszSysfsPath)
    1827         {
    1828             USBDeviceInfo info(pszDevice, pszSysfsPath);
    1829             bool ifaceSuccess = false;  /* If we can't get the interfaces, just
    1830                                          * skip this one device. */
    1831             rc = getUSBInterfacesFromHal(&info.mInterfaces, pszSysfsPath,
    1832                                          &ifaceSuccess);
    1833             if (RT_SUCCESS(rc) && halSuccess && ifaceSuccess)
    1834                 try
    1835                 {
    1836                     pList->push_back(info);
    1837                 }
    1838                 catch(std::bad_alloc &e)
    1839                 {
    1840                     rc = VERR_NO_MEMORY;
    1841                 }
    1842         }
    1843     }
    1844     if (dbusError.HasName(DBUS_ERROR_NO_MEMORY))
    1845         rc = VERR_NO_MEMORY;
    1846     if (pfSuccess != NULL)
    1847         *pfSuccess = halSuccess;
    1848     LogFlow(("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
    1849     dbusError.FlowLog();
    1850     return rc;
    1851 }
    1852 
    18531159class sysfsPathHandler
    18541160{
     
    20201326    }
    20211327};
     1328
     1329/**
     1330 * Helper function to query the sysfs subsystem for information about USB
     1331 * devices attached to the system.
     1332 * @returns iprt status code
     1333 * @param   pList      where to add information about the drives detected
     1334 * @param   pfSuccess  Did we find anything?
     1335 *
     1336 * @returns IPRT status code
     1337 */
     1338static int getUSBDeviceInfoFromSysfs(USBDeviceInfoList *pList,
     1339                                     bool *pfSuccess)
     1340{
     1341    AssertPtrReturn(pList, VERR_INVALID_POINTER);
     1342    AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */
     1343    LogFlowFunc (("pList=%p, pfSuccess=%p\n",
     1344                  pList, pfSuccess));
     1345    size_t cDevices = pList->size();
     1346    matchUSBDevice devHandler(pList);
     1347    int rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &devHandler);
     1348    do {
     1349        if (RT_FAILURE(rc))
     1350            break;
     1351        for (USBDeviceInfoList::iterator pInfo = pList->begin();
     1352             pInfo != pList->end(); ++pInfo)
     1353        {
     1354            matchUSBInterface ifaceHandler(&*pInfo);
     1355            rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &ifaceHandler);
     1356            if (RT_FAILURE(rc))
     1357                break;
     1358        }
     1359    } while(0);
     1360    if (RT_FAILURE(rc))
     1361        /* Clean up again */
     1362        while (pList->size() > cDevices)
     1363            pList->pop_back();
     1364    if (pfSuccess)
     1365        *pfSuccess = RT_SUCCESS(rc);
     1366    LogFlow (("rc=%Rrc\n", rc));
     1367    return rc;
     1368}
     1369
     1370
     1371#if defined(RT_OS_LINUX) && defined(VBOX_WITH_DBUS)
     1372/** Wrapper class around DBusError for automatic cleanup */
     1373class autoDBusError
     1374{
     1375    DBusError mError;
     1376public:
     1377    autoDBusError () { dbus_error_init (&mError); }
     1378    ~autoDBusError ()
     1379    {
     1380        if (IsSet())
     1381            dbus_error_free (&mError);
     1382    }
     1383    DBusError &get () { return mError; }
     1384    bool IsSet ()
     1385    {
     1386        Assert((mError.name == NULL) == (mError.message == NULL));
     1387        return (mError.name != NULL);
     1388    }
     1389    bool HasName (const char *pcszName)
     1390    {
     1391        Assert((mError.name == NULL) == (mError.message == NULL));
     1392        return (RTStrCmp (mError.name, pcszName) == 0);
     1393    }
     1394    void FlowLog ()
     1395    {
     1396        if (IsSet ())
     1397            LogFlow(("DBus error %s: %s\n", mError.name, mError.message));
     1398    }
     1399};
     1400
     1401/**
     1402 * Helper function for setting up a connection to the DBus daemon and
     1403 * registering with the hal service.
     1404 *
     1405 * @note If libdbus is being loaded at runtime then be sure to call
     1406 *       VBoxDBusCheckPresence before calling this.
     1407 * @returns iprt status code
     1408 * @param   ppConnection  where to store the connection handle
     1409 */
     1410/* static */
     1411int halInit (RTMemAutoPtr <DBusConnection, VBoxHalShutdown> *pConnection)
     1412{
     1413    AssertReturn(VALID_PTR (pConnection), VERR_INVALID_POINTER);
     1414    LogFlowFunc (("pConnection=%p\n", pConnection));
     1415    int rc = VINF_SUCCESS;
     1416    bool halSuccess = true;
     1417    autoDBusError dbusError;
     1418
     1419    RTMemAutoPtr <DBusConnection, VBoxDBusConnectionUnref> dbusConnection;
     1420    dbusConnection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbusError.get());
     1421    if (!dbusConnection)
     1422        halSuccess = false;
     1423    if (halSuccess)
     1424    {
     1425        dbus_connection_set_exit_on_disconnect (dbusConnection.get(), false);
     1426        halSuccess = dbus_bus_name_has_owner (dbusConnection.get(),
     1427                                              "org.freedesktop.Hal", &dbusError.get());
     1428    }
     1429    if (halSuccess)
     1430    {
     1431        dbus_bus_add_match (dbusConnection.get(),
     1432                            "type='signal',"
     1433                            "interface='org.freedesktop.Hal.Manager',"
     1434                            "sender='org.freedesktop.Hal',"
     1435                            "path='/org/freedesktop/Hal/Manager'",
     1436                            &dbusError.get());
     1437        halSuccess = !dbusError.IsSet();
     1438    }
     1439    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
     1440        rc = VERR_NO_MEMORY;
     1441    if (halSuccess)
     1442        *pConnection = dbusConnection.release();
     1443    LogFlowFunc(("rc=%Rrc, (*pConnection).get()=%p\n", rc, (*pConnection).get()));
     1444    dbusError.FlowLog();
     1445    return rc;
     1446}
     1447
     1448/**
     1449 * Helper function for setting up a private connection to the DBus daemon and
     1450 * registering with the hal service.  Private connections are considered
     1451 * unsociable and should not be used unnecessarily (as per the DBus API docs).
     1452 *
     1453 * @note If libdbus is being loaded at runtime then be sure to call
     1454 *       VBoxDBusCheckPresence before calling this.
     1455 * @returns iprt status code
     1456 * @param   pConnection  where to store the connection handle
     1457 */
     1458/* static */
     1459int halInitPrivate (RTMemAutoPtr <DBusConnection, VBoxHalShutdownPrivate> *pConnection)
     1460{
     1461    AssertReturn(VALID_PTR (pConnection), VERR_INVALID_POINTER);
     1462    LogFlowFunc (("pConnection=%p\n", pConnection));
     1463    int rc = VINF_SUCCESS;
     1464    bool halSuccess = true;
     1465    autoDBusError dbusError;
     1466
     1467    RTMemAutoPtr <DBusConnection, VBoxDBusConnectionCloseAndUnref> dbusConnection;
     1468    dbusConnection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &dbusError.get());
     1469    if (!dbusConnection)
     1470        halSuccess = false;
     1471    if (halSuccess)
     1472    {
     1473        dbus_connection_set_exit_on_disconnect (dbusConnection.get(), false);
     1474        halSuccess = dbus_bus_name_has_owner (dbusConnection.get(),
     1475                                              "org.freedesktop.Hal", &dbusError.get());
     1476    }
     1477    if (halSuccess)
     1478    {
     1479        dbus_bus_add_match (dbusConnection.get(),
     1480                            "type='signal',"
     1481                            "interface='org.freedesktop.Hal.Manager',"
     1482                            "sender='org.freedesktop.Hal',"
     1483                            "path='/org/freedesktop/Hal/Manager'",
     1484                            &dbusError.get());
     1485        halSuccess = !dbusError.IsSet();
     1486    }
     1487    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
     1488        rc = VERR_NO_MEMORY;
     1489    if (halSuccess)
     1490        *pConnection = dbusConnection.release();
     1491    LogFlowFunc(("rc=%Rrc, (*pConnection).get()=%p\n", rc, (*pConnection).get()));
     1492    dbusError.FlowLog();
     1493    return rc;
     1494}
     1495
     1496/**
     1497 * Helper function for shutting down a connection to DBus and hal.
     1498 * @param   pConnection  the connection handle
     1499 */
     1500/* extern */
     1501void VBoxHalShutdown (DBusConnection *pConnection)
     1502{
     1503    AssertReturnVoid(VALID_PTR (pConnection));
     1504    LogFlowFunc (("pConnection=%p\n", pConnection));
     1505    autoDBusError dbusError;
     1506
     1507    dbus_bus_remove_match (pConnection,
     1508                           "type='signal',"
     1509                           "interface='org.freedesktop.Hal.Manager',"
     1510                           "sender='org.freedesktop.Hal',"
     1511                           "path='/org/freedesktop/Hal/Manager'",
     1512                           &dbusError.get());
     1513    dbus_connection_unref (pConnection);
     1514    LogFlowFunc(("returning\n"));
     1515    dbusError.FlowLog();
     1516}
     1517
     1518/**
     1519 * Helper function for shutting down a private connection to DBus and hal.
     1520 * @param   pConnection  the connection handle
     1521 */
     1522/* extern */
     1523void VBoxHalShutdownPrivate (DBusConnection *pConnection)
     1524{
     1525    AssertReturnVoid(VALID_PTR (pConnection));
     1526    LogFlowFunc (("pConnection=%p\n", pConnection));
     1527    autoDBusError dbusError;
     1528
     1529    dbus_bus_remove_match (pConnection,
     1530                           "type='signal',"
     1531                           "interface='org.freedesktop.Hal.Manager',"
     1532                           "sender='org.freedesktop.Hal',"
     1533                           "path='/org/freedesktop/Hal/Manager'",
     1534                           &dbusError.get());
     1535    dbus_connection_close (pConnection);
     1536    dbus_connection_unref (pConnection);
     1537    LogFlowFunc(("returning\n"));
     1538    dbusError.FlowLog();
     1539}
     1540
     1541/** Wrapper around dbus_connection_unref.  We need this to use it as a real
     1542 * function in auto pointers, as a function pointer won't wash here. */
     1543/* extern */
     1544void VBoxDBusConnectionUnref(DBusConnection *pConnection)
     1545{
     1546    dbus_connection_unref(pConnection);
     1547}
     1548
     1549/**
     1550 * This function closes and unrefs a private connection to dbus.  It should
     1551 * only be called once no-one else is referencing the connection.
     1552 */
     1553/* extern */
     1554void VBoxDBusConnectionCloseAndUnref(DBusConnection *pConnection)
     1555{
     1556    dbus_connection_close(pConnection);
     1557    dbus_connection_unref(pConnection);
     1558}
     1559
     1560/** Wrapper around dbus_message_unref.  We need this to use it as a real
     1561 * function in auto pointers, as a function pointer won't wash here. */
     1562/* extern */
     1563void VBoxDBusMessageUnref(DBusMessage *pMessage)
     1564{
     1565    dbus_message_unref(pMessage);
     1566}
     1567
     1568/**
     1569 * Find the UDIs of hal entries that contain Key=Value property.
     1570 * @returns iprt status code.  If a non-fatal error occurs, we return success
     1571 *          but reset pMessage to NULL.
     1572 * @param   pConnection an initialised connection DBus
     1573 * @param   pszKey      the property key
     1574 * @param   pszValue    the property value
     1575 * @param   pMessage    where to store the return DBus message.  This must be
     1576 *                      parsed to get at the UDIs.  NOT optional.
     1577 */
     1578/* static */
     1579int halFindDeviceStringMatch (DBusConnection *pConnection, const char *pszKey,
     1580                              const char *pszValue,
     1581                              RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage)
     1582{
     1583    AssertReturn(   VALID_PTR (pConnection) && VALID_PTR (pszKey)
     1584                 && VALID_PTR (pszValue) && VALID_PTR (pMessage),
     1585                 VERR_INVALID_POINTER);
     1586    LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMessage=%p\n",
     1587                  pConnection, pszKey, pszValue, pMessage));
     1588    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
     1589    bool halSuccess = true;  /* We set this to false to abort the operation. */
     1590    autoDBusError dbusError;
     1591
     1592    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
     1593    if (halSuccess && RT_SUCCESS(rc))
     1594    {
     1595        message = dbus_message_new_method_call ("org.freedesktop.Hal",
     1596                                                "/org/freedesktop/Hal/Manager",
     1597                                                "org.freedesktop.Hal.Manager",
     1598                                                "FindDeviceStringMatch");
     1599        if (!message)
     1600            rc = VERR_NO_MEMORY;
     1601    }
     1602    if (halSuccess && RT_SUCCESS(rc))
     1603    {
     1604        DBusMessageIter iterAppend;
     1605        dbus_message_iter_init_append (message.get(), &iterAppend);
     1606        dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszKey);
     1607        dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszValue);
     1608        reply = dbus_connection_send_with_reply_and_block (pConnection,
     1609                                                            message.get(), -1,
     1610                                                            &dbusError.get());
     1611        if (!reply)
     1612            halSuccess = false;
     1613    }
     1614    *pMessage = reply.release ();
     1615    LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get()));
     1616    dbusError.FlowLog();
     1617    return rc;
     1618}
     1619
     1620/**
     1621 * Find the UDIs of hal entries that contain Key=Value property and return the
     1622 * result on the end of a vector of iprt::MiniString.
     1623 * @returns iprt status code.  If a non-fatal error occurs, we return success
     1624 *          but set *pfSuccess to false.
     1625 * @param   pConnection an initialised connection DBus
     1626 * @param   pszKey      the property key
     1627 * @param   pszValue    the property value
     1628 * @param   pMatches    pointer to an array of iprt::MiniString to append the
     1629 *                      results to.  NOT optional.
     1630 * @param   pfSuccess   will be set to true if the operation succeeds
     1631 */
     1632/* static */
     1633int halFindDeviceStringMatchVector (DBusConnection *pConnection,
     1634                                    const char *pszKey, const char *pszValue,
     1635                                    std::vector<iprt::MiniString> *pMatches,
     1636                                    bool *pfSuccess)
     1637{
     1638    AssertPtrReturn (pConnection, VERR_INVALID_POINTER);
     1639    AssertPtrReturn (pszKey, VERR_INVALID_POINTER);
     1640    AssertPtrReturn (pszValue, VERR_INVALID_POINTER);
     1641    AssertPtrReturn (pMatches, VERR_INVALID_POINTER);
     1642    AssertReturn(pfSuccess == NULL || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
     1643    LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMatches=%p, pfSuccess=%p\n",
     1644                  pConnection, pszKey, pszValue, pMatches, pfSuccess));
     1645    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
     1646    bool halSuccess = true;  /* We set this to false to abort the operation. */
     1647
     1648    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind;
     1649    DBusMessageIter iterFind, iterUdis;
     1650
     1651    if (halSuccess && RT_SUCCESS(rc))
     1652    {
     1653        rc = halFindDeviceStringMatch (pConnection, pszKey, pszValue,
     1654                                       &replyFind);
     1655        if (!replyFind)
     1656            halSuccess = false;
     1657    }
     1658    if (halSuccess && RT_SUCCESS(rc))
     1659    {
     1660        dbus_message_iter_init (replyFind.get(), &iterFind);
     1661        if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
     1662            halSuccess = false;
     1663    }
     1664    if (halSuccess && RT_SUCCESS(rc))
     1665        dbus_message_iter_recurse (&iterFind, &iterUdis);
     1666    for (;    halSuccess && RT_SUCCESS(rc)
     1667           && dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
     1668         dbus_message_iter_next(&iterUdis))
     1669    {
     1670        /* Now get all UDIs from the iterator */
     1671        const char *pszUdi;
     1672        dbus_message_iter_get_basic (&iterUdis, &pszUdi);
     1673        try
     1674        {
     1675            pMatches->push_back(pszUdi);
     1676        }
     1677        catch(std::bad_alloc &e)
     1678        {
     1679            rc = VERR_NO_MEMORY;
     1680        }
     1681    }
     1682    if (pfSuccess != NULL)
     1683        *pfSuccess = halSuccess;
     1684    LogFlow (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
     1685    return rc;
     1686}
     1687
     1688/**
     1689 * Read a set of string properties for a device.  If some of the properties are
     1690 * not of type DBUS_TYPE_STRING or do not exist then a NULL pointer will be
     1691 * returned for them.
     1692 * @returns iprt status code.  If the operation failed for non-fatal reasons
     1693 *          then we return success and leave pMessage untouched - reset it
     1694 *          before the call to detect this.
     1695 * @param   pConnection  an initialised connection DBus
     1696 * @param   pszUdi       the Udi of the device
     1697 * @param   cProps       the number of property values to look up
     1698 * @param   papszKeys    the keys of the properties to be looked up
     1699 * @param   papszValues  where to store the values of the properties.  The
     1700 *                       strings returned will be valid until the message
     1701 *                       returned in @a ppMessage is freed.  Undefined if
     1702 *                       the message is NULL.
     1703 * @param   pMessage     where to store the return DBus message.  The caller
     1704 *                       is responsible for freeing this once they have
     1705 *                       finished with the value strings.  NOT optional.
     1706 */
     1707/* static */
     1708int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi,
     1709                           size_t cProps, const char **papszKeys,
     1710                           char **papszValues,
     1711                           RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage)
     1712{
     1713    AssertReturn(   VALID_PTR (pConnection) && VALID_PTR (pszUdi)
     1714                 && VALID_PTR (papszKeys) && VALID_PTR (papszValues)
     1715                 && VALID_PTR (pMessage),
     1716                 VERR_INVALID_POINTER);
     1717    LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, papszValues=%p, pMessage=%p\n",
     1718                  pConnection, pszUdi, cProps, papszKeys, papszValues, pMessage));
     1719    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
     1720    bool halSuccess = true;  /* We set this to false to abort the operation. */
     1721    autoDBusError dbusError;
     1722
     1723    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
     1724    DBusMessageIter iterGet, iterProps;
     1725
     1726    /* Initialise the return array to NULLs */
     1727    for (size_t i = 0; i < cProps; ++i)
     1728        papszValues[i] = NULL;
     1729
     1730    /* Send a GetAllProperties message to hald */
     1731    message = dbus_message_new_method_call ("org.freedesktop.Hal", pszUdi,
     1732                                            "org.freedesktop.Hal.Device",
     1733                                            "GetAllProperties");
     1734    if (!message)
     1735        rc = VERR_NO_MEMORY;
     1736    if (halSuccess && RT_SUCCESS(rc))
     1737    {
     1738        reply = dbus_connection_send_with_reply_and_block (pConnection,
     1739                                                           message.get(), -1,
     1740                                                           &dbusError.get());
     1741        if (!reply)
     1742            halSuccess = false;
     1743    }
     1744
     1745    /* Parse the reply */
     1746    if (halSuccess && RT_SUCCESS(rc))
     1747    {
     1748        dbus_message_iter_init (reply.get(), &iterGet);
     1749        if (   dbus_message_iter_get_arg_type (&iterGet) != DBUS_TYPE_ARRAY
     1750            && dbus_message_iter_get_element_type (&iterGet) != DBUS_TYPE_DICT_ENTRY)
     1751            halSuccess = false;
     1752    }
     1753    if (halSuccess && RT_SUCCESS(rc))
     1754        dbus_message_iter_recurse (&iterGet, &iterProps);
     1755    /* Go through all entries in the reply and see if any match our keys. */
     1756    while (   halSuccess && RT_SUCCESS(rc)
     1757           &&    dbus_message_iter_get_arg_type (&iterProps)
     1758              == DBUS_TYPE_DICT_ENTRY)
     1759    {
     1760        const char *pszKey;
     1761        DBusMessageIter iterEntry, iterValue;
     1762        dbus_message_iter_recurse (&iterProps, &iterEntry);
     1763        dbus_message_iter_get_basic (&iterEntry, &pszKey);
     1764        dbus_message_iter_next (&iterEntry);
     1765        dbus_message_iter_recurse (&iterEntry, &iterValue);
     1766        /* Fill in any matches. */
     1767        for (size_t i = 0; i < cProps; ++i)
     1768            if (strcmp (pszKey, papszKeys[i]) == 0)
     1769            {
     1770                if (dbus_message_iter_get_arg_type (&iterValue) == DBUS_TYPE_STRING)
     1771                    dbus_message_iter_get_basic (&iterValue, &papszValues[i]);
     1772            }
     1773        dbus_message_iter_next (&iterProps);
     1774    }
     1775    if (RT_SUCCESS(rc) && halSuccess)
     1776        *pMessage = reply.release();
     1777    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
     1778        rc = VERR_NO_MEMORY;
     1779    LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get()));
     1780    dbusError.FlowLog();
     1781    return rc;
     1782}
     1783
     1784/**
     1785 * Read a set of string properties for a device.  If some properties do not
     1786 * exist or are not of type DBUS_TYPE_STRING, we will still fetch the others.
     1787 * @returns iprt status code.  If the operation failed for non-fatal reasons
     1788 *          then we return success and set *pfSuccess to false.
     1789 * @param   pConnection  an initialised connection DBus
     1790 * @param   pszUdi       the Udi of the device
     1791 * @param   cProps       the number of property values to look up
     1792 * @param   papszKeys    the keys of the properties to be looked up
     1793 * @param   pMatches     pointer to an empty array of iprt::MiniString to append the
     1794 *                       results to.  NOT optional.
     1795 * @param   pfMatches    pointer to an array of boolean values indicating
     1796 *                       whether the respective property is a string.  If this
     1797 *                       is not supplied then all properties must be strings
     1798 *                       for the operation to be considered successful
     1799 * @param   pfSuccess    will be set to true if the operation succeeds
     1800 */
     1801/* static */
     1802int halGetPropertyStringsVector (DBusConnection *pConnection,
     1803                                 const char *pszUdi, size_t cProps,
     1804                                 const char **papszKeys,
     1805                                 std::vector<iprt::MiniString> *pMatches,
     1806                                 bool *pfMatches, bool *pfSuccess)
     1807{
     1808    AssertPtrReturn (pConnection, VERR_INVALID_POINTER);
     1809    AssertPtrReturn (pszUdi, VERR_INVALID_POINTER);
     1810    AssertPtrReturn (papszKeys, VERR_INVALID_POINTER);
     1811    AssertPtrReturn (pMatches, VERR_INVALID_POINTER);
     1812    AssertReturn((pfMatches == NULL) || VALID_PTR (pfMatches), VERR_INVALID_POINTER);
     1813    AssertReturn((pfSuccess == NULL) || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
     1814    AssertReturn(pMatches->empty(), VERR_INVALID_PARAMETER);
     1815    LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, pMatches=%p, pfMatches=%p, pfSuccess=%p\n",
     1816                  pConnection, pszUdi, cProps, papszKeys, pMatches, pfMatches, pfSuccess));
     1817    RTMemAutoPtr <char *> values(cProps);
     1818    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message;
     1819    bool halSuccess = true;
     1820    int rc = halGetPropertyStrings (pConnection, pszUdi, cProps, papszKeys,
     1821                                    values.get(), &message);
     1822    if (!message)
     1823        halSuccess = false;
     1824    for (size_t i = 0; RT_SUCCESS(rc) && halSuccess && i < cProps; ++i)
     1825    {
     1826        bool fMatches = values[i] != NULL;
     1827        if (pfMatches != NULL)
     1828            pfMatches[i] = fMatches;
     1829        else
     1830            halSuccess = fMatches;
     1831        try
     1832        {
     1833            pMatches->push_back(fMatches ? values[i] : "");
     1834        }
     1835        catch(std::bad_alloc &e)
     1836        {
     1837            rc = VERR_NO_MEMORY;
     1838        }
     1839    }
     1840    if (pfSuccess != NULL)
     1841        *pfSuccess = halSuccess;
     1842    if (RT_SUCCESS(rc) && halSuccess)
     1843    {
     1844        Assert(pMatches->size() == cProps);
     1845        AssertForEach(j, size_t, 0, cProps,    (pfMatches == NULL)
     1846                                            || (pfMatches[j] == true)
     1847                                            || ((pfMatches[j] == false) && (pMatches[j].size() == 0)));
     1848    }
     1849    LogFlowFunc (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
     1850    return rc;
     1851}
     1852
     1853
     1854/**
     1855 * Helper function to query the hal subsystem for information about USB devices
     1856 * attached to the system.
     1857 * @returns iprt status code
     1858 * @param   pList      where to add information about the devices detected
     1859 * @param   pfSuccess  will be set to true if all interactions with hal
     1860 *                     succeeded and to false otherwise.  Optional.
     1861 *
     1862 * @returns IPRT status code
     1863 */
     1864/* static */
     1865int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
     1866{
     1867    AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
     1868                 VERR_INVALID_POINTER);
     1869    LogFlowFunc (("pList=%p, pfSuccess=%p\n", pList, pfSuccess));
     1870    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
     1871    bool halSuccess = true;  /* We set this to false to abort the operation. */
     1872    autoDBusError dbusError;
     1873
     1874    RTMemAutoPtr<DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
     1875    RTMemAutoPtr<DBusConnection, VBoxHalShutdown> dbusConnection;
     1876    DBusMessageIter iterFind, iterUdis;
     1877
     1878    /* Connect to hal */
     1879    rc = halInit (&dbusConnection);
     1880    if (!dbusConnection)
     1881        halSuccess = false;
     1882    /* Get an array of all devices in the usb_device subsystem */
     1883    if (halSuccess && RT_SUCCESS(rc))
     1884    {
     1885        rc = halFindDeviceStringMatch(dbusConnection.get(), "info.subsystem",
     1886                                      "usb_device", &replyFind);
     1887        if (!replyFind)
     1888            halSuccess = false;
     1889    }
     1890    if (halSuccess && RT_SUCCESS(rc))
     1891    {
     1892        dbus_message_iter_init(replyFind.get(), &iterFind);
     1893        if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
     1894            halSuccess = false;
     1895    }
     1896    /* Recurse down into the array and query interesting information about the
     1897     * entries. */
     1898    if (halSuccess && RT_SUCCESS(rc))
     1899        dbus_message_iter_recurse(&iterFind, &iterUdis);
     1900    for (;    halSuccess && RT_SUCCESS(rc)
     1901           && dbus_message_iter_get_arg_type(&iterUdis) == DBUS_TYPE_STRING;
     1902         dbus_message_iter_next(&iterUdis))
     1903    {
     1904        /* Get the device node and the sysfs path for the current entry. */
     1905        const char *pszUdi;
     1906        dbus_message_iter_get_basic (&iterUdis, &pszUdi);
     1907        static const char *papszKeys[] = { "linux.device_file", "linux.sysfs_path" };
     1908        char *papszValues[RT_ELEMENTS(papszKeys)];
     1909        rc = halGetPropertyStrings(dbusConnection.get(), pszUdi, RT_ELEMENTS(papszKeys),
     1910                                   papszKeys, papszValues, &replyGet);
     1911        const char *pszDevice = papszValues[0], *pszSysfsPath = papszValues[1];
     1912        /* Get the interfaces. */
     1913        if (!!replyGet && pszDevice && pszSysfsPath)
     1914        {
     1915            USBDeviceInfo info(pszDevice, pszSysfsPath);
     1916            bool ifaceSuccess = true;  /* If we can't get the interfaces, just
     1917                                        * skip this one device. */
     1918            rc = getUSBInterfacesFromHal(&info.mInterfaces, pszUdi, &ifaceSuccess);
     1919            if (RT_SUCCESS(rc) && halSuccess && ifaceSuccess)
     1920                try
     1921                {
     1922                    pList->push_back(info);
     1923                }
     1924                catch(std::bad_alloc &e)
     1925                {
     1926                    rc = VERR_NO_MEMORY;
     1927                }
     1928        }
     1929    }
     1930    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
     1931        rc = VERR_NO_MEMORY;
     1932    if (pfSuccess != NULL)
     1933        *pfSuccess = halSuccess;
     1934    LogFlow(("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
     1935    dbusError.FlowLog();
     1936    return rc;
     1937}
     1938
     1939/**
     1940 * Helper function to query the hal subsystem for information about USB devices
     1941 * attached to the system, using the older API.
     1942 * @returns iprt status code
     1943 * @param   pList      where to add information about the devices detected
     1944 * @param   pfSuccess  will be set to true if all interactions with hal
     1945 *                     succeeded and to false otherwise.  Optional.
     1946 *
     1947 * @returns IPRT status code
     1948 */
     1949/* static */
     1950int getOldUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
     1951{
     1952    AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
     1953                 VERR_INVALID_POINTER);
     1954    LogFlowFunc (("pList=%p, pfSuccess=%p\n", pList, pfSuccess));
     1955    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
     1956    bool halSuccess = true;  /* We set this to false to abort the operation. */
     1957    autoDBusError dbusError;
     1958
     1959    RTMemAutoPtr<DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
     1960    RTMemAutoPtr<DBusConnection, VBoxHalShutdown> dbusConnection;
     1961    DBusMessageIter iterFind, iterUdis;
     1962
     1963    /* Connect to hal */
     1964    rc = halInit(&dbusConnection);
     1965    if (!dbusConnection)
     1966        halSuccess = false;
     1967    /* Get an array of all devices in the usb_device subsystem */
     1968    if (halSuccess && RT_SUCCESS(rc))
     1969    {
     1970        rc = halFindDeviceStringMatch(dbusConnection.get(), "info.category",
     1971                                       "usbraw", &replyFind);
     1972        if (!replyFind)
     1973            halSuccess = false;
     1974    }
     1975    if (halSuccess && RT_SUCCESS(rc))
     1976    {
     1977        dbus_message_iter_init(replyFind.get(), &iterFind);
     1978        if (dbus_message_iter_get_arg_type(&iterFind) != DBUS_TYPE_ARRAY)
     1979            halSuccess = false;
     1980    }
     1981    /* Recurse down into the array and query interesting information about the
     1982     * entries. */
     1983    if (halSuccess && RT_SUCCESS(rc))
     1984        dbus_message_iter_recurse(&iterFind, &iterUdis);
     1985    for (;    halSuccess && RT_SUCCESS(rc)
     1986           && dbus_message_iter_get_arg_type(&iterUdis) == DBUS_TYPE_STRING;
     1987         dbus_message_iter_next(&iterUdis))
     1988    {
     1989        /* Get the device node and the sysfs path for the current entry. */
     1990        const char *pszUdi;
     1991        dbus_message_iter_get_basic(&iterUdis, &pszUdi);
     1992        static const char *papszKeys[] = { "linux.device_file", "info.parent" };
     1993        char *papszValues[RT_ELEMENTS(papszKeys)];
     1994        rc = halGetPropertyStrings(dbusConnection.get(), pszUdi, RT_ELEMENTS(papszKeys),
     1995                                   papszKeys, papszValues, &replyGet);
     1996        const char *pszDevice = papszValues[0], *pszSysfsPath = papszValues[1];
     1997        /* Get the interfaces. */
     1998        if (!!replyGet && pszDevice && pszSysfsPath)
     1999        {
     2000            USBDeviceInfo info(pszDevice, pszSysfsPath);
     2001            bool ifaceSuccess = false;  /* If we can't get the interfaces, just
     2002                                         * skip this one device. */
     2003            rc = getUSBInterfacesFromHal(&info.mInterfaces, pszSysfsPath,
     2004                                         &ifaceSuccess);
     2005            if (RT_SUCCESS(rc) && halSuccess && ifaceSuccess)
     2006                try
     2007                {
     2008                    pList->push_back(info);
     2009                }
     2010                catch(std::bad_alloc &e)
     2011                {
     2012                    rc = VERR_NO_MEMORY;
     2013                }
     2014        }
     2015    }
     2016    if (dbusError.HasName(DBUS_ERROR_NO_MEMORY))
     2017        rc = VERR_NO_MEMORY;
     2018    if (pfSuccess != NULL)
     2019        *pfSuccess = halSuccess;
     2020    LogFlow(("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
     2021    dbusError.FlowLog();
     2022    return rc;
     2023}
     2024
    20222025
    20232026/**
Note: See TracChangeset for help on using the changeset viewer.

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