Index: trunk/src/VBox/Main/linux/HostHardwareLinux.cpp
===================================================================
--- trunk/src/VBox/Main/linux/HostHardwareLinux.cpp	(revision 28314)
+++ trunk/src/VBox/Main/linux/HostHardwareLinux.cpp	(revision 28315)
@@ -853,44 +853,4 @@
 }
 
-/**
- * Helper function to query the sysfs subsystem for information about USB
- * devices attached to the system.
- * @returns iprt status code
- * @param   pList      where to add information about the drives detected
- * @param   pfSuccess  Did we find anything?
- *
- * @returns IPRT status code
- */
-static int getUSBDeviceInfoFromSysfs(USBDeviceInfoList *pList,
-                                     bool *pfSuccess)
-{
-    AssertPtrReturn(pList, VERR_INVALID_POINTER);
-    AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */
-    LogFlowFunc (("pList=%p, pfSuccess=%p\n",
-                  pList, pfSuccess));
-    size_t cDevices = pList->size();
-    matchUSBDevice devHandler(pList);
-    int rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &devHandler);
-    do {
-        if (RT_FAILURE(rc))
-            break;
-        for (USBDeviceInfoList::iterator pInfo = pList->begin();
-             pInfo != pList->end(); ++pInfo)
-        {
-            matchUSBInterface ifaceHandler(&*pInfo);
-            rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &ifaceHandler);
-            if (RT_FAILURE(rc))
-                break;
-        }
-    } while(0);
-    if (RT_FAILURE(rc))
-        /* Clean up again */
-        while (pList->size() > cDevices)
-            pList->pop_back();
-    if (pfSuccess)
-        *pfSuccess = RT_SUCCESS(rc);
-    LogFlow (("rc=%Rrc\n", rc));
-    return rc;
-}
 
 /** Structure for holding information about a drive we have found */
@@ -1197,658 +1157,4 @@
 
 
-#if defined(RT_OS_LINUX) && defined(VBOX_WITH_DBUS)
-/** Wrapper class around DBusError for automatic cleanup */
-class autoDBusError
-{
-    DBusError mError;
-public:
-    autoDBusError () { dbus_error_init (&mError); }
-    ~autoDBusError ()
-    {
-        if (IsSet())
-            dbus_error_free (&mError);
-    }
-    DBusError &get () { return mError; }
-    bool IsSet ()
-    {
-        Assert((mError.name == NULL) == (mError.message == NULL));
-        return (mError.name != NULL);
-    }
-    bool HasName (const char *pcszName)
-    {
-        Assert((mError.name == NULL) == (mError.message == NULL));
-        return (RTStrCmp (mError.name, pcszName) == 0);
-    }
-    void FlowLog ()
-    {
-        if (IsSet ())
-            LogFlow(("DBus error %s: %s\n", mError.name, mError.message));
-    }
-};
-
-/**
- * Helper function for setting up a connection to the DBus daemon and
- * registering with the hal service.
- *
- * @note If libdbus is being loaded at runtime then be sure to call
- *       VBoxDBusCheckPresence before calling this.
- * @returns iprt status code
- * @param   ppConnection  where to store the connection handle
- */
-/* static */
-int halInit (RTMemAutoPtr <DBusConnection, VBoxHalShutdown> *pConnection)
-{
-    AssertReturn(VALID_PTR (pConnection), VERR_INVALID_POINTER);
-    LogFlowFunc (("pConnection=%p\n", pConnection));
-    int rc = VINF_SUCCESS;
-    bool halSuccess = true;
-    autoDBusError dbusError;
-
-    RTMemAutoPtr <DBusConnection, VBoxDBusConnectionUnref> dbusConnection;
-    dbusConnection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbusError.get());
-    if (!dbusConnection)
-        halSuccess = false;
-    if (halSuccess)
-    {
-        dbus_connection_set_exit_on_disconnect (dbusConnection.get(), false);
-        halSuccess = dbus_bus_name_has_owner (dbusConnection.get(),
-                                              "org.freedesktop.Hal", &dbusError.get());
-    }
-    if (halSuccess)
-    {
-        dbus_bus_add_match (dbusConnection.get(),
-                            "type='signal',"
-                            "interface='org.freedesktop.Hal.Manager',"
-                            "sender='org.freedesktop.Hal',"
-                            "path='/org/freedesktop/Hal/Manager'",
-                            &dbusError.get());
-        halSuccess = !dbusError.IsSet();
-    }
-    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
-        rc = VERR_NO_MEMORY;
-    if (halSuccess)
-        *pConnection = dbusConnection.release();
-    LogFlowFunc(("rc=%Rrc, (*pConnection).get()=%p\n", rc, (*pConnection).get()));
-    dbusError.FlowLog();
-    return rc;
-}
-
-/**
- * Helper function for setting up a private connection to the DBus daemon and
- * registering with the hal service.  Private connections are considered
- * unsociable and should not be used unnecessarily (as per the DBus API docs).
- *
- * @note If libdbus is being loaded at runtime then be sure to call
- *       VBoxDBusCheckPresence before calling this.
- * @returns iprt status code
- * @param   pConnection  where to store the connection handle
- */
-/* static */
-int halInitPrivate (RTMemAutoPtr <DBusConnection, VBoxHalShutdownPrivate> *pConnection)
-{
-    AssertReturn(VALID_PTR (pConnection), VERR_INVALID_POINTER);
-    LogFlowFunc (("pConnection=%p\n", pConnection));
-    int rc = VINF_SUCCESS;
-    bool halSuccess = true;
-    autoDBusError dbusError;
-
-    RTMemAutoPtr <DBusConnection, VBoxDBusConnectionCloseAndUnref> dbusConnection;
-    dbusConnection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &dbusError.get());
-    if (!dbusConnection)
-        halSuccess = false;
-    if (halSuccess)
-    {
-        dbus_connection_set_exit_on_disconnect (dbusConnection.get(), false);
-        halSuccess = dbus_bus_name_has_owner (dbusConnection.get(),
-                                              "org.freedesktop.Hal", &dbusError.get());
-    }
-    if (halSuccess)
-    {
-        dbus_bus_add_match (dbusConnection.get(),
-                            "type='signal',"
-                            "interface='org.freedesktop.Hal.Manager',"
-                            "sender='org.freedesktop.Hal',"
-                            "path='/org/freedesktop/Hal/Manager'",
-                            &dbusError.get());
-        halSuccess = !dbusError.IsSet();
-    }
-    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
-        rc = VERR_NO_MEMORY;
-    if (halSuccess)
-        *pConnection = dbusConnection.release();
-    LogFlowFunc(("rc=%Rrc, (*pConnection).get()=%p\n", rc, (*pConnection).get()));
-    dbusError.FlowLog();
-    return rc;
-}
-
-/**
- * Helper function for shutting down a connection to DBus and hal.
- * @param   pConnection  the connection handle
- */
-/* extern */
-void VBoxHalShutdown (DBusConnection *pConnection)
-{
-    AssertReturnVoid(VALID_PTR (pConnection));
-    LogFlowFunc (("pConnection=%p\n", pConnection));
-    autoDBusError dbusError;
-
-    dbus_bus_remove_match (pConnection,
-                           "type='signal',"
-                           "interface='org.freedesktop.Hal.Manager',"
-                           "sender='org.freedesktop.Hal',"
-                           "path='/org/freedesktop/Hal/Manager'",
-                           &dbusError.get());
-    dbus_connection_unref (pConnection);
-    LogFlowFunc(("returning\n"));
-    dbusError.FlowLog();
-}
-
-/**
- * Helper function for shutting down a private connection to DBus and hal.
- * @param   pConnection  the connection handle
- */
-/* extern */
-void VBoxHalShutdownPrivate (DBusConnection *pConnection)
-{
-    AssertReturnVoid(VALID_PTR (pConnection));
-    LogFlowFunc (("pConnection=%p\n", pConnection));
-    autoDBusError dbusError;
-
-    dbus_bus_remove_match (pConnection,
-                           "type='signal',"
-                           "interface='org.freedesktop.Hal.Manager',"
-                           "sender='org.freedesktop.Hal',"
-                           "path='/org/freedesktop/Hal/Manager'",
-                           &dbusError.get());
-    dbus_connection_close (pConnection);
-    dbus_connection_unref (pConnection);
-    LogFlowFunc(("returning\n"));
-    dbusError.FlowLog();
-}
-
-/** Wrapper around dbus_connection_unref.  We need this to use it as a real
- * function in auto pointers, as a function pointer won't wash here. */
-/* extern */
-void VBoxDBusConnectionUnref(DBusConnection *pConnection)
-{
-    dbus_connection_unref(pConnection);
-}
-
-/**
- * This function closes and unrefs a private connection to dbus.  It should
- * only be called once no-one else is referencing the connection.
- */
-/* extern */
-void VBoxDBusConnectionCloseAndUnref(DBusConnection *pConnection)
-{
-    dbus_connection_close(pConnection);
-    dbus_connection_unref(pConnection);
-}
-
-/** Wrapper around dbus_message_unref.  We need this to use it as a real
- * function in auto pointers, as a function pointer won't wash here. */
-/* extern */
-void VBoxDBusMessageUnref(DBusMessage *pMessage)
-{
-    dbus_message_unref(pMessage);
-}
-
-/**
- * Find the UDIs of hal entries that contain Key=Value property.
- * @returns iprt status code.  If a non-fatal error occurs, we return success
- *          but reset pMessage to NULL.
- * @param   pConnection an initialised connection DBus
- * @param   pszKey      the property key
- * @param   pszValue    the property value
- * @param   pMessage    where to store the return DBus message.  This must be
- *                      parsed to get at the UDIs.  NOT optional.
- */
-/* static */
-int halFindDeviceStringMatch (DBusConnection *pConnection, const char *pszKey,
-                              const char *pszValue,
-                              RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage)
-{
-    AssertReturn(   VALID_PTR (pConnection) && VALID_PTR (pszKey)
-                 && VALID_PTR (pszValue) && VALID_PTR (pMessage),
-                 VERR_INVALID_POINTER);
-    LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMessage=%p\n",
-                  pConnection, pszKey, pszValue, pMessage));
-    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
-    bool halSuccess = true;  /* We set this to false to abort the operation. */
-    autoDBusError dbusError;
-
-    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
-    if (halSuccess && RT_SUCCESS(rc))
-    {
-        message = dbus_message_new_method_call ("org.freedesktop.Hal",
-                                                "/org/freedesktop/Hal/Manager",
-                                                "org.freedesktop.Hal.Manager",
-                                                "FindDeviceStringMatch");
-        if (!message)
-            rc = VERR_NO_MEMORY;
-    }
-    if (halSuccess && RT_SUCCESS(rc))
-    {
-        DBusMessageIter iterAppend;
-        dbus_message_iter_init_append (message.get(), &iterAppend);
-        dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszKey);
-        dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszValue);
-        reply = dbus_connection_send_with_reply_and_block (pConnection,
-                                                            message.get(), -1,
-                                                            &dbusError.get());
-        if (!reply)
-            halSuccess = false;
-    }
-    *pMessage = reply.release ();
-    LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get()));
-    dbusError.FlowLog();
-    return rc;
-}
-
-/**
- * Find the UDIs of hal entries that contain Key=Value property and return the
- * result on the end of a vector of iprt::MiniString.
- * @returns iprt status code.  If a non-fatal error occurs, we return success
- *          but set *pfSuccess to false.
- * @param   pConnection an initialised connection DBus
- * @param   pszKey      the property key
- * @param   pszValue    the property value
- * @param   pMatches    pointer to an array of iprt::MiniString to append the
- *                      results to.  NOT optional.
- * @param   pfSuccess   will be set to true if the operation succeeds
- */
-/* static */
-int halFindDeviceStringMatchVector (DBusConnection *pConnection,
-                                    const char *pszKey, const char *pszValue,
-                                    std::vector<iprt::MiniString> *pMatches,
-                                    bool *pfSuccess)
-{
-    AssertPtrReturn (pConnection, VERR_INVALID_POINTER);
-    AssertPtrReturn (pszKey, VERR_INVALID_POINTER);
-    AssertPtrReturn (pszValue, VERR_INVALID_POINTER);
-    AssertPtrReturn (pMatches, VERR_INVALID_POINTER);
-    AssertReturn(pfSuccess == NULL || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
-    LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMatches=%p, pfSuccess=%p\n",
-                  pConnection, pszKey, pszValue, pMatches, pfSuccess));
-    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
-    bool halSuccess = true;  /* We set this to false to abort the operation. */
-
-    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind;
-    DBusMessageIter iterFind, iterUdis;
-
-    if (halSuccess && RT_SUCCESS(rc))
-    {
-        rc = halFindDeviceStringMatch (pConnection, pszKey, pszValue,
-                                       &replyFind);
-        if (!replyFind)
-            halSuccess = false;
-    }
-    if (halSuccess && RT_SUCCESS(rc))
-    {
-        dbus_message_iter_init (replyFind.get(), &iterFind);
-        if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
-            halSuccess = false;
-    }
-    if (halSuccess && RT_SUCCESS(rc))
-        dbus_message_iter_recurse (&iterFind, &iterUdis);
-    for (;    halSuccess && RT_SUCCESS(rc)
-           && dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
-         dbus_message_iter_next(&iterUdis))
-    {
-        /* Now get all UDIs from the iterator */
-        const char *pszUdi;
-        dbus_message_iter_get_basic (&iterUdis, &pszUdi);
-        try
-        {
-            pMatches->push_back(pszUdi);
-        }
-        catch(std::bad_alloc &e)
-        {
-            rc = VERR_NO_MEMORY;
-        }
-    }
-    if (pfSuccess != NULL)
-        *pfSuccess = halSuccess;
-    LogFlow (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
-    return rc;
-}
-
-/**
- * Read a set of string properties for a device.  If some of the properties are
- * not of type DBUS_TYPE_STRING or do not exist then a NULL pointer will be
- * returned for them.
- * @returns iprt status code.  If the operation failed for non-fatal reasons
- *          then we return success and leave pMessage untouched - reset it
- *          before the call to detect this.
- * @param   pConnection  an initialised connection DBus
- * @param   pszUdi       the Udi of the device
- * @param   cProps       the number of property values to look up
- * @param   papszKeys    the keys of the properties to be looked up
- * @param   papszValues  where to store the values of the properties.  The
- *                       strings returned will be valid until the message
- *                       returned in @a ppMessage is freed.  Undefined if
- *                       the message is NULL.
- * @param   pMessage     where to store the return DBus message.  The caller
- *                       is responsible for freeing this once they have
- *                       finished with the value strings.  NOT optional.
- */
-/* static */
-int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi,
-                           size_t cProps, const char **papszKeys,
-                           char **papszValues,
-                           RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage)
-{
-    AssertReturn(   VALID_PTR (pConnection) && VALID_PTR (pszUdi)
-                 && VALID_PTR (papszKeys) && VALID_PTR (papszValues)
-                 && VALID_PTR (pMessage),
-                 VERR_INVALID_POINTER);
-    LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, papszValues=%p, pMessage=%p\n",
-                  pConnection, pszUdi, cProps, papszKeys, papszValues, pMessage));
-    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
-    bool halSuccess = true;  /* We set this to false to abort the operation. */
-    autoDBusError dbusError;
-
-    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
-    DBusMessageIter iterGet, iterProps;
-
-    /* Initialise the return array to NULLs */
-    for (size_t i = 0; i < cProps; ++i)
-        papszValues[i] = NULL;
-
-    /* Send a GetAllProperties message to hald */
-    message = dbus_message_new_method_call ("org.freedesktop.Hal", pszUdi,
-                                            "org.freedesktop.Hal.Device",
-                                            "GetAllProperties");
-    if (!message)
-        rc = VERR_NO_MEMORY;
-    if (halSuccess && RT_SUCCESS(rc))
-    {
-        reply = dbus_connection_send_with_reply_and_block (pConnection,
-                                                           message.get(), -1,
-                                                           &dbusError.get());
-        if (!reply)
-            halSuccess = false;
-    }
-
-    /* Parse the reply */
-    if (halSuccess && RT_SUCCESS(rc))
-    {
-        dbus_message_iter_init (reply.get(), &iterGet);
-        if (   dbus_message_iter_get_arg_type (&iterGet) != DBUS_TYPE_ARRAY
-            && dbus_message_iter_get_element_type (&iterGet) != DBUS_TYPE_DICT_ENTRY)
-            halSuccess = false;
-    }
-    if (halSuccess && RT_SUCCESS(rc))
-        dbus_message_iter_recurse (&iterGet, &iterProps);
-    /* Go through all entries in the reply and see if any match our keys. */
-    while (   halSuccess && RT_SUCCESS(rc)
-           &&    dbus_message_iter_get_arg_type (&iterProps)
-              == DBUS_TYPE_DICT_ENTRY)
-    {
-        const char *pszKey;
-        DBusMessageIter iterEntry, iterValue;
-        dbus_message_iter_recurse (&iterProps, &iterEntry);
-        dbus_message_iter_get_basic (&iterEntry, &pszKey);
-        dbus_message_iter_next (&iterEntry);
-        dbus_message_iter_recurse (&iterEntry, &iterValue);
-        /* Fill in any matches. */
-        for (size_t i = 0; i < cProps; ++i)
-            if (strcmp (pszKey, papszKeys[i]) == 0)
-            {
-                if (dbus_message_iter_get_arg_type (&iterValue) == DBUS_TYPE_STRING)
-                    dbus_message_iter_get_basic (&iterValue, &papszValues[i]);
-            }
-        dbus_message_iter_next (&iterProps);
-    }
-    if (RT_SUCCESS(rc) && halSuccess)
-        *pMessage = reply.release();
-    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
-        rc = VERR_NO_MEMORY;
-    LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get()));
-    dbusError.FlowLog();
-    return rc;
-}
-
-/**
- * Read a set of string properties for a device.  If some properties do not
- * exist or are not of type DBUS_TYPE_STRING, we will still fetch the others.
- * @returns iprt status code.  If the operation failed for non-fatal reasons
- *          then we return success and set *pfSuccess to false.
- * @param   pConnection  an initialised connection DBus
- * @param   pszUdi       the Udi of the device
- * @param   cProps       the number of property values to look up
- * @param   papszKeys    the keys of the properties to be looked up
- * @param   pMatches     pointer to an empty array of iprt::MiniString to append the
- *                       results to.  NOT optional.
- * @param   pfMatches    pointer to an array of boolean values indicating
- *                       whether the respective property is a string.  If this
- *                       is not supplied then all properties must be strings
- *                       for the operation to be considered successful
- * @param   pfSuccess    will be set to true if the operation succeeds
- */
-/* static */
-int halGetPropertyStringsVector (DBusConnection *pConnection,
-                                 const char *pszUdi, size_t cProps,
-                                 const char **papszKeys,
-                                 std::vector<iprt::MiniString> *pMatches,
-                                 bool *pfMatches, bool *pfSuccess)
-{
-    AssertPtrReturn (pConnection, VERR_INVALID_POINTER);
-    AssertPtrReturn (pszUdi, VERR_INVALID_POINTER);
-    AssertPtrReturn (papszKeys, VERR_INVALID_POINTER);
-    AssertPtrReturn (pMatches, VERR_INVALID_POINTER);
-    AssertReturn((pfMatches == NULL) || VALID_PTR (pfMatches), VERR_INVALID_POINTER);
-    AssertReturn((pfSuccess == NULL) || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
-    AssertReturn(pMatches->empty(), VERR_INVALID_PARAMETER);
-    LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, pMatches=%p, pfMatches=%p, pfSuccess=%p\n",
-                  pConnection, pszUdi, cProps, papszKeys, pMatches, pfMatches, pfSuccess));
-    RTMemAutoPtr <char *> values(cProps);
-    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message;
-    bool halSuccess = true;
-    int rc = halGetPropertyStrings (pConnection, pszUdi, cProps, papszKeys,
-                                    values.get(), &message);
-    if (!message)
-        halSuccess = false;
-    for (size_t i = 0; RT_SUCCESS(rc) && halSuccess && i < cProps; ++i)
-    {
-        bool fMatches = values[i] != NULL;
-        if (pfMatches != NULL)
-            pfMatches[i] = fMatches;
-        else
-            halSuccess = fMatches;
-        try
-        {
-            pMatches->push_back(fMatches ? values[i] : "");
-        }
-        catch(std::bad_alloc &e)
-        {
-            rc = VERR_NO_MEMORY;
-        }
-    }
-    if (pfSuccess != NULL)
-        *pfSuccess = halSuccess;
-    if (RT_SUCCESS(rc) && halSuccess)
-    {
-        Assert(pMatches->size() == cProps);
-        AssertForEach(j, size_t, 0, cProps,    (pfMatches == NULL)
-                                            || (pfMatches[j] == true)
-                                            || ((pfMatches[j] == false) && (pMatches[j].size() == 0)));
-    }
-    LogFlowFunc (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
-    return rc;
-}
-
-
-/**
- * Helper function to query the hal subsystem for information about USB devices
- * attached to the system.
- * @returns iprt status code
- * @param   pList      where to add information about the devices detected
- * @param   pfSuccess  will be set to true if all interactions with hal
- *                     succeeded and to false otherwise.  Optional.
- *
- * @returns IPRT status code
- */
-/* static */
-int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
-{
-    AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
-                 VERR_INVALID_POINTER);
-    LogFlowFunc (("pList=%p, pfSuccess=%p\n", pList, pfSuccess));
-    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
-    bool halSuccess = true;  /* We set this to false to abort the operation. */
-    autoDBusError dbusError;
-
-    RTMemAutoPtr<DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
-    RTMemAutoPtr<DBusConnection, VBoxHalShutdown> dbusConnection;
-    DBusMessageIter iterFind, iterUdis;
-
-    /* Connect to hal */
-    rc = halInit (&dbusConnection);
-    if (!dbusConnection)
-        halSuccess = false;
-    /* Get an array of all devices in the usb_device subsystem */
-    if (halSuccess && RT_SUCCESS(rc))
-    {
-        rc = halFindDeviceStringMatch(dbusConnection.get(), "info.subsystem",
-                                      "usb_device", &replyFind);
-        if (!replyFind)
-            halSuccess = false;
-    }
-    if (halSuccess && RT_SUCCESS(rc))
-    {
-        dbus_message_iter_init(replyFind.get(), &iterFind);
-        if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
-            halSuccess = false;
-    }
-    /* Recurse down into the array and query interesting information about the
-     * entries. */
-    if (halSuccess && RT_SUCCESS(rc))
-        dbus_message_iter_recurse(&iterFind, &iterUdis);
-    for (;    halSuccess && RT_SUCCESS(rc)
-           && dbus_message_iter_get_arg_type(&iterUdis) == DBUS_TYPE_STRING;
-         dbus_message_iter_next(&iterUdis))
-    {
-        /* Get the device node and the sysfs path for the current entry. */
-        const char *pszUdi;
-        dbus_message_iter_get_basic (&iterUdis, &pszUdi);
-        static const char *papszKeys[] = { "linux.device_file", "linux.sysfs_path" };
-        char *papszValues[RT_ELEMENTS(papszKeys)];
-        rc = halGetPropertyStrings(dbusConnection.get(), pszUdi, RT_ELEMENTS(papszKeys),
-                                   papszKeys, papszValues, &replyGet);
-        const char *pszDevice = papszValues[0], *pszSysfsPath = papszValues[1];
-        /* Get the interfaces. */
-        if (!!replyGet && pszDevice && pszSysfsPath)
-        {
-            USBDeviceInfo info(pszDevice, pszSysfsPath);
-            bool ifaceSuccess = true;  /* If we can't get the interfaces, just
-                                        * skip this one device. */
-            rc = getUSBInterfacesFromHal(&info.mInterfaces, pszUdi, &ifaceSuccess);
-            if (RT_SUCCESS(rc) && halSuccess && ifaceSuccess)
-                try
-                {
-                    pList->push_back(info);
-                }
-                catch(std::bad_alloc &e)
-                {
-                    rc = VERR_NO_MEMORY;
-                }
-        }
-    }
-    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
-        rc = VERR_NO_MEMORY;
-    if (pfSuccess != NULL)
-        *pfSuccess = halSuccess;
-    LogFlow(("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
-    dbusError.FlowLog();
-    return rc;
-}
-
-/**
- * Helper function to query the hal subsystem for information about USB devices
- * attached to the system, using the older API.
- * @returns iprt status code
- * @param   pList      where to add information about the devices detected
- * @param   pfSuccess  will be set to true if all interactions with hal
- *                     succeeded and to false otherwise.  Optional.
- *
- * @returns IPRT status code
- */
-/* static */
-int getOldUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
-{
-    AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
-                 VERR_INVALID_POINTER);
-    LogFlowFunc (("pList=%p, pfSuccess=%p\n", pList, pfSuccess));
-    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
-    bool halSuccess = true;  /* We set this to false to abort the operation. */
-    autoDBusError dbusError;
-
-    RTMemAutoPtr<DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
-    RTMemAutoPtr<DBusConnection, VBoxHalShutdown> dbusConnection;
-    DBusMessageIter iterFind, iterUdis;
-
-    /* Connect to hal */
-    rc = halInit(&dbusConnection);
-    if (!dbusConnection)
-        halSuccess = false;
-    /* Get an array of all devices in the usb_device subsystem */
-    if (halSuccess && RT_SUCCESS(rc))
-    {
-        rc = halFindDeviceStringMatch(dbusConnection.get(), "info.category",
-                                       "usbraw", &replyFind);
-        if (!replyFind)
-            halSuccess = false;
-    }
-    if (halSuccess && RT_SUCCESS(rc))
-    {
-        dbus_message_iter_init(replyFind.get(), &iterFind);
-        if (dbus_message_iter_get_arg_type(&iterFind) != DBUS_TYPE_ARRAY)
-            halSuccess = false;
-    }
-    /* Recurse down into the array and query interesting information about the
-     * entries. */
-    if (halSuccess && RT_SUCCESS(rc))
-        dbus_message_iter_recurse(&iterFind, &iterUdis);
-    for (;    halSuccess && RT_SUCCESS(rc)
-           && dbus_message_iter_get_arg_type(&iterUdis) == DBUS_TYPE_STRING;
-         dbus_message_iter_next(&iterUdis))
-    {
-        /* Get the device node and the sysfs path for the current entry. */
-        const char *pszUdi;
-        dbus_message_iter_get_basic(&iterUdis, &pszUdi);
-        static const char *papszKeys[] = { "linux.device_file", "info.parent" };
-        char *papszValues[RT_ELEMENTS(papszKeys)];
-        rc = halGetPropertyStrings(dbusConnection.get(), pszUdi, RT_ELEMENTS(papszKeys),
-                                   papszKeys, papszValues, &replyGet);
-        const char *pszDevice = papszValues[0], *pszSysfsPath = papszValues[1];
-        /* Get the interfaces. */
-        if (!!replyGet && pszDevice && pszSysfsPath)
-        {
-            USBDeviceInfo info(pszDevice, pszSysfsPath);
-            bool ifaceSuccess = false;  /* If we can't get the interfaces, just
-                                         * skip this one device. */
-            rc = getUSBInterfacesFromHal(&info.mInterfaces, pszSysfsPath,
-                                         &ifaceSuccess);
-            if (RT_SUCCESS(rc) && halSuccess && ifaceSuccess)
-                try
-                {
-                    pList->push_back(info);
-                }
-                catch(std::bad_alloc &e)
-                {
-                    rc = VERR_NO_MEMORY;
-                }
-        }
-    }
-    if (dbusError.HasName(DBUS_ERROR_NO_MEMORY))
-        rc = VERR_NO_MEMORY;
-    if (pfSuccess != NULL)
-        *pfSuccess = halSuccess;
-    LogFlow(("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
-    dbusError.FlowLog();
-    return rc;
-}
-
 class sysfsPathHandler
 {
@@ -2020,4 +1326,701 @@
     }
 };
+
+/**
+ * Helper function to query the sysfs subsystem for information about USB
+ * devices attached to the system.
+ * @returns iprt status code
+ * @param   pList      where to add information about the drives detected
+ * @param   pfSuccess  Did we find anything?
+ *
+ * @returns IPRT status code
+ */
+static int getUSBDeviceInfoFromSysfs(USBDeviceInfoList *pList,
+                                     bool *pfSuccess)
+{
+    AssertPtrReturn(pList, VERR_INVALID_POINTER);
+    AssertPtrNullReturn(pfSuccess, VERR_INVALID_POINTER); /* Valid or Null */
+    LogFlowFunc (("pList=%p, pfSuccess=%p\n",
+                  pList, pfSuccess));
+    size_t cDevices = pList->size();
+    matchUSBDevice devHandler(pList);
+    int rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &devHandler);
+    do {
+        if (RT_FAILURE(rc))
+            break;
+        for (USBDeviceInfoList::iterator pInfo = pList->begin();
+             pInfo != pList->end(); ++pInfo)
+        {
+            matchUSBInterface ifaceHandler(&*pInfo);
+            rc = getDeviceInfoFromSysfs("/sys/bus/usb/devices", &ifaceHandler);
+            if (RT_FAILURE(rc))
+                break;
+        }
+    } while(0);
+    if (RT_FAILURE(rc))
+        /* Clean up again */
+        while (pList->size() > cDevices)
+            pList->pop_back();
+    if (pfSuccess)
+        *pfSuccess = RT_SUCCESS(rc);
+    LogFlow (("rc=%Rrc\n", rc));
+    return rc;
+}
+
+
+#if defined(RT_OS_LINUX) && defined(VBOX_WITH_DBUS)
+/** Wrapper class around DBusError for automatic cleanup */
+class autoDBusError
+{
+    DBusError mError;
+public:
+    autoDBusError () { dbus_error_init (&mError); }
+    ~autoDBusError ()
+    {
+        if (IsSet())
+            dbus_error_free (&mError);
+    }
+    DBusError &get () { return mError; }
+    bool IsSet ()
+    {
+        Assert((mError.name == NULL) == (mError.message == NULL));
+        return (mError.name != NULL);
+    }
+    bool HasName (const char *pcszName)
+    {
+        Assert((mError.name == NULL) == (mError.message == NULL));
+        return (RTStrCmp (mError.name, pcszName) == 0);
+    }
+    void FlowLog ()
+    {
+        if (IsSet ())
+            LogFlow(("DBus error %s: %s\n", mError.name, mError.message));
+    }
+};
+
+/**
+ * Helper function for setting up a connection to the DBus daemon and
+ * registering with the hal service.
+ *
+ * @note If libdbus is being loaded at runtime then be sure to call
+ *       VBoxDBusCheckPresence before calling this.
+ * @returns iprt status code
+ * @param   ppConnection  where to store the connection handle
+ */
+/* static */
+int halInit (RTMemAutoPtr <DBusConnection, VBoxHalShutdown> *pConnection)
+{
+    AssertReturn(VALID_PTR (pConnection), VERR_INVALID_POINTER);
+    LogFlowFunc (("pConnection=%p\n", pConnection));
+    int rc = VINF_SUCCESS;
+    bool halSuccess = true;
+    autoDBusError dbusError;
+
+    RTMemAutoPtr <DBusConnection, VBoxDBusConnectionUnref> dbusConnection;
+    dbusConnection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbusError.get());
+    if (!dbusConnection)
+        halSuccess = false;
+    if (halSuccess)
+    {
+        dbus_connection_set_exit_on_disconnect (dbusConnection.get(), false);
+        halSuccess = dbus_bus_name_has_owner (dbusConnection.get(),
+                                              "org.freedesktop.Hal", &dbusError.get());
+    }
+    if (halSuccess)
+    {
+        dbus_bus_add_match (dbusConnection.get(),
+                            "type='signal',"
+                            "interface='org.freedesktop.Hal.Manager',"
+                            "sender='org.freedesktop.Hal',"
+                            "path='/org/freedesktop/Hal/Manager'",
+                            &dbusError.get());
+        halSuccess = !dbusError.IsSet();
+    }
+    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
+        rc = VERR_NO_MEMORY;
+    if (halSuccess)
+        *pConnection = dbusConnection.release();
+    LogFlowFunc(("rc=%Rrc, (*pConnection).get()=%p\n", rc, (*pConnection).get()));
+    dbusError.FlowLog();
+    return rc;
+}
+
+/**
+ * Helper function for setting up a private connection to the DBus daemon and
+ * registering with the hal service.  Private connections are considered
+ * unsociable and should not be used unnecessarily (as per the DBus API docs).
+ *
+ * @note If libdbus is being loaded at runtime then be sure to call
+ *       VBoxDBusCheckPresence before calling this.
+ * @returns iprt status code
+ * @param   pConnection  where to store the connection handle
+ */
+/* static */
+int halInitPrivate (RTMemAutoPtr <DBusConnection, VBoxHalShutdownPrivate> *pConnection)
+{
+    AssertReturn(VALID_PTR (pConnection), VERR_INVALID_POINTER);
+    LogFlowFunc (("pConnection=%p\n", pConnection));
+    int rc = VINF_SUCCESS;
+    bool halSuccess = true;
+    autoDBusError dbusError;
+
+    RTMemAutoPtr <DBusConnection, VBoxDBusConnectionCloseAndUnref> dbusConnection;
+    dbusConnection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &dbusError.get());
+    if (!dbusConnection)
+        halSuccess = false;
+    if (halSuccess)
+    {
+        dbus_connection_set_exit_on_disconnect (dbusConnection.get(), false);
+        halSuccess = dbus_bus_name_has_owner (dbusConnection.get(),
+                                              "org.freedesktop.Hal", &dbusError.get());
+    }
+    if (halSuccess)
+    {
+        dbus_bus_add_match (dbusConnection.get(),
+                            "type='signal',"
+                            "interface='org.freedesktop.Hal.Manager',"
+                            "sender='org.freedesktop.Hal',"
+                            "path='/org/freedesktop/Hal/Manager'",
+                            &dbusError.get());
+        halSuccess = !dbusError.IsSet();
+    }
+    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
+        rc = VERR_NO_MEMORY;
+    if (halSuccess)
+        *pConnection = dbusConnection.release();
+    LogFlowFunc(("rc=%Rrc, (*pConnection).get()=%p\n", rc, (*pConnection).get()));
+    dbusError.FlowLog();
+    return rc;
+}
+
+/**
+ * Helper function for shutting down a connection to DBus and hal.
+ * @param   pConnection  the connection handle
+ */
+/* extern */
+void VBoxHalShutdown (DBusConnection *pConnection)
+{
+    AssertReturnVoid(VALID_PTR (pConnection));
+    LogFlowFunc (("pConnection=%p\n", pConnection));
+    autoDBusError dbusError;
+
+    dbus_bus_remove_match (pConnection,
+                           "type='signal',"
+                           "interface='org.freedesktop.Hal.Manager',"
+                           "sender='org.freedesktop.Hal',"
+                           "path='/org/freedesktop/Hal/Manager'",
+                           &dbusError.get());
+    dbus_connection_unref (pConnection);
+    LogFlowFunc(("returning\n"));
+    dbusError.FlowLog();
+}
+
+/**
+ * Helper function for shutting down a private connection to DBus and hal.
+ * @param   pConnection  the connection handle
+ */
+/* extern */
+void VBoxHalShutdownPrivate (DBusConnection *pConnection)
+{
+    AssertReturnVoid(VALID_PTR (pConnection));
+    LogFlowFunc (("pConnection=%p\n", pConnection));
+    autoDBusError dbusError;
+
+    dbus_bus_remove_match (pConnection,
+                           "type='signal',"
+                           "interface='org.freedesktop.Hal.Manager',"
+                           "sender='org.freedesktop.Hal',"
+                           "path='/org/freedesktop/Hal/Manager'",
+                           &dbusError.get());
+    dbus_connection_close (pConnection);
+    dbus_connection_unref (pConnection);
+    LogFlowFunc(("returning\n"));
+    dbusError.FlowLog();
+}
+
+/** Wrapper around dbus_connection_unref.  We need this to use it as a real
+ * function in auto pointers, as a function pointer won't wash here. */
+/* extern */
+void VBoxDBusConnectionUnref(DBusConnection *pConnection)
+{
+    dbus_connection_unref(pConnection);
+}
+
+/**
+ * This function closes and unrefs a private connection to dbus.  It should
+ * only be called once no-one else is referencing the connection.
+ */
+/* extern */
+void VBoxDBusConnectionCloseAndUnref(DBusConnection *pConnection)
+{
+    dbus_connection_close(pConnection);
+    dbus_connection_unref(pConnection);
+}
+
+/** Wrapper around dbus_message_unref.  We need this to use it as a real
+ * function in auto pointers, as a function pointer won't wash here. */
+/* extern */
+void VBoxDBusMessageUnref(DBusMessage *pMessage)
+{
+    dbus_message_unref(pMessage);
+}
+
+/**
+ * Find the UDIs of hal entries that contain Key=Value property.
+ * @returns iprt status code.  If a non-fatal error occurs, we return success
+ *          but reset pMessage to NULL.
+ * @param   pConnection an initialised connection DBus
+ * @param   pszKey      the property key
+ * @param   pszValue    the property value
+ * @param   pMessage    where to store the return DBus message.  This must be
+ *                      parsed to get at the UDIs.  NOT optional.
+ */
+/* static */
+int halFindDeviceStringMatch (DBusConnection *pConnection, const char *pszKey,
+                              const char *pszValue,
+                              RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage)
+{
+    AssertReturn(   VALID_PTR (pConnection) && VALID_PTR (pszKey)
+                 && VALID_PTR (pszValue) && VALID_PTR (pMessage),
+                 VERR_INVALID_POINTER);
+    LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMessage=%p\n",
+                  pConnection, pszKey, pszValue, pMessage));
+    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
+    bool halSuccess = true;  /* We set this to false to abort the operation. */
+    autoDBusError dbusError;
+
+    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
+    if (halSuccess && RT_SUCCESS(rc))
+    {
+        message = dbus_message_new_method_call ("org.freedesktop.Hal",
+                                                "/org/freedesktop/Hal/Manager",
+                                                "org.freedesktop.Hal.Manager",
+                                                "FindDeviceStringMatch");
+        if (!message)
+            rc = VERR_NO_MEMORY;
+    }
+    if (halSuccess && RT_SUCCESS(rc))
+    {
+        DBusMessageIter iterAppend;
+        dbus_message_iter_init_append (message.get(), &iterAppend);
+        dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszKey);
+        dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszValue);
+        reply = dbus_connection_send_with_reply_and_block (pConnection,
+                                                            message.get(), -1,
+                                                            &dbusError.get());
+        if (!reply)
+            halSuccess = false;
+    }
+    *pMessage = reply.release ();
+    LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get()));
+    dbusError.FlowLog();
+    return rc;
+}
+
+/**
+ * Find the UDIs of hal entries that contain Key=Value property and return the
+ * result on the end of a vector of iprt::MiniString.
+ * @returns iprt status code.  If a non-fatal error occurs, we return success
+ *          but set *pfSuccess to false.
+ * @param   pConnection an initialised connection DBus
+ * @param   pszKey      the property key
+ * @param   pszValue    the property value
+ * @param   pMatches    pointer to an array of iprt::MiniString to append the
+ *                      results to.  NOT optional.
+ * @param   pfSuccess   will be set to true if the operation succeeds
+ */
+/* static */
+int halFindDeviceStringMatchVector (DBusConnection *pConnection,
+                                    const char *pszKey, const char *pszValue,
+                                    std::vector<iprt::MiniString> *pMatches,
+                                    bool *pfSuccess)
+{
+    AssertPtrReturn (pConnection, VERR_INVALID_POINTER);
+    AssertPtrReturn (pszKey, VERR_INVALID_POINTER);
+    AssertPtrReturn (pszValue, VERR_INVALID_POINTER);
+    AssertPtrReturn (pMatches, VERR_INVALID_POINTER);
+    AssertReturn(pfSuccess == NULL || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
+    LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMatches=%p, pfSuccess=%p\n",
+                  pConnection, pszKey, pszValue, pMatches, pfSuccess));
+    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
+    bool halSuccess = true;  /* We set this to false to abort the operation. */
+
+    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind;
+    DBusMessageIter iterFind, iterUdis;
+
+    if (halSuccess && RT_SUCCESS(rc))
+    {
+        rc = halFindDeviceStringMatch (pConnection, pszKey, pszValue,
+                                       &replyFind);
+        if (!replyFind)
+            halSuccess = false;
+    }
+    if (halSuccess && RT_SUCCESS(rc))
+    {
+        dbus_message_iter_init (replyFind.get(), &iterFind);
+        if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
+            halSuccess = false;
+    }
+    if (halSuccess && RT_SUCCESS(rc))
+        dbus_message_iter_recurse (&iterFind, &iterUdis);
+    for (;    halSuccess && RT_SUCCESS(rc)
+           && dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
+         dbus_message_iter_next(&iterUdis))
+    {
+        /* Now get all UDIs from the iterator */
+        const char *pszUdi;
+        dbus_message_iter_get_basic (&iterUdis, &pszUdi);
+        try
+        {
+            pMatches->push_back(pszUdi);
+        }
+        catch(std::bad_alloc &e)
+        {
+            rc = VERR_NO_MEMORY;
+        }
+    }
+    if (pfSuccess != NULL)
+        *pfSuccess = halSuccess;
+    LogFlow (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
+    return rc;
+}
+
+/**
+ * Read a set of string properties for a device.  If some of the properties are
+ * not of type DBUS_TYPE_STRING or do not exist then a NULL pointer will be
+ * returned for them.
+ * @returns iprt status code.  If the operation failed for non-fatal reasons
+ *          then we return success and leave pMessage untouched - reset it
+ *          before the call to detect this.
+ * @param   pConnection  an initialised connection DBus
+ * @param   pszUdi       the Udi of the device
+ * @param   cProps       the number of property values to look up
+ * @param   papszKeys    the keys of the properties to be looked up
+ * @param   papszValues  where to store the values of the properties.  The
+ *                       strings returned will be valid until the message
+ *                       returned in @a ppMessage is freed.  Undefined if
+ *                       the message is NULL.
+ * @param   pMessage     where to store the return DBus message.  The caller
+ *                       is responsible for freeing this once they have
+ *                       finished with the value strings.  NOT optional.
+ */
+/* static */
+int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi,
+                           size_t cProps, const char **papszKeys,
+                           char **papszValues,
+                           RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage)
+{
+    AssertReturn(   VALID_PTR (pConnection) && VALID_PTR (pszUdi)
+                 && VALID_PTR (papszKeys) && VALID_PTR (papszValues)
+                 && VALID_PTR (pMessage),
+                 VERR_INVALID_POINTER);
+    LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, papszValues=%p, pMessage=%p\n",
+                  pConnection, pszUdi, cProps, papszKeys, papszValues, pMessage));
+    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
+    bool halSuccess = true;  /* We set this to false to abort the operation. */
+    autoDBusError dbusError;
+
+    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
+    DBusMessageIter iterGet, iterProps;
+
+    /* Initialise the return array to NULLs */
+    for (size_t i = 0; i < cProps; ++i)
+        papszValues[i] = NULL;
+
+    /* Send a GetAllProperties message to hald */
+    message = dbus_message_new_method_call ("org.freedesktop.Hal", pszUdi,
+                                            "org.freedesktop.Hal.Device",
+                                            "GetAllProperties");
+    if (!message)
+        rc = VERR_NO_MEMORY;
+    if (halSuccess && RT_SUCCESS(rc))
+    {
+        reply = dbus_connection_send_with_reply_and_block (pConnection,
+                                                           message.get(), -1,
+                                                           &dbusError.get());
+        if (!reply)
+            halSuccess = false;
+    }
+
+    /* Parse the reply */
+    if (halSuccess && RT_SUCCESS(rc))
+    {
+        dbus_message_iter_init (reply.get(), &iterGet);
+        if (   dbus_message_iter_get_arg_type (&iterGet) != DBUS_TYPE_ARRAY
+            && dbus_message_iter_get_element_type (&iterGet) != DBUS_TYPE_DICT_ENTRY)
+            halSuccess = false;
+    }
+    if (halSuccess && RT_SUCCESS(rc))
+        dbus_message_iter_recurse (&iterGet, &iterProps);
+    /* Go through all entries in the reply and see if any match our keys. */
+    while (   halSuccess && RT_SUCCESS(rc)
+           &&    dbus_message_iter_get_arg_type (&iterProps)
+              == DBUS_TYPE_DICT_ENTRY)
+    {
+        const char *pszKey;
+        DBusMessageIter iterEntry, iterValue;
+        dbus_message_iter_recurse (&iterProps, &iterEntry);
+        dbus_message_iter_get_basic (&iterEntry, &pszKey);
+        dbus_message_iter_next (&iterEntry);
+        dbus_message_iter_recurse (&iterEntry, &iterValue);
+        /* Fill in any matches. */
+        for (size_t i = 0; i < cProps; ++i)
+            if (strcmp (pszKey, papszKeys[i]) == 0)
+            {
+                if (dbus_message_iter_get_arg_type (&iterValue) == DBUS_TYPE_STRING)
+                    dbus_message_iter_get_basic (&iterValue, &papszValues[i]);
+            }
+        dbus_message_iter_next (&iterProps);
+    }
+    if (RT_SUCCESS(rc) && halSuccess)
+        *pMessage = reply.release();
+    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
+        rc = VERR_NO_MEMORY;
+    LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get()));
+    dbusError.FlowLog();
+    return rc;
+}
+
+/**
+ * Read a set of string properties for a device.  If some properties do not
+ * exist or are not of type DBUS_TYPE_STRING, we will still fetch the others.
+ * @returns iprt status code.  If the operation failed for non-fatal reasons
+ *          then we return success and set *pfSuccess to false.
+ * @param   pConnection  an initialised connection DBus
+ * @param   pszUdi       the Udi of the device
+ * @param   cProps       the number of property values to look up
+ * @param   papszKeys    the keys of the properties to be looked up
+ * @param   pMatches     pointer to an empty array of iprt::MiniString to append the
+ *                       results to.  NOT optional.
+ * @param   pfMatches    pointer to an array of boolean values indicating
+ *                       whether the respective property is a string.  If this
+ *                       is not supplied then all properties must be strings
+ *                       for the operation to be considered successful
+ * @param   pfSuccess    will be set to true if the operation succeeds
+ */
+/* static */
+int halGetPropertyStringsVector (DBusConnection *pConnection,
+                                 const char *pszUdi, size_t cProps,
+                                 const char **papszKeys,
+                                 std::vector<iprt::MiniString> *pMatches,
+                                 bool *pfMatches, bool *pfSuccess)
+{
+    AssertPtrReturn (pConnection, VERR_INVALID_POINTER);
+    AssertPtrReturn (pszUdi, VERR_INVALID_POINTER);
+    AssertPtrReturn (papszKeys, VERR_INVALID_POINTER);
+    AssertPtrReturn (pMatches, VERR_INVALID_POINTER);
+    AssertReturn((pfMatches == NULL) || VALID_PTR (pfMatches), VERR_INVALID_POINTER);
+    AssertReturn((pfSuccess == NULL) || VALID_PTR (pfSuccess), VERR_INVALID_POINTER);
+    AssertReturn(pMatches->empty(), VERR_INVALID_PARAMETER);
+    LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, pMatches=%p, pfMatches=%p, pfSuccess=%p\n",
+                  pConnection, pszUdi, cProps, papszKeys, pMatches, pfMatches, pfSuccess));
+    RTMemAutoPtr <char *> values(cProps);
+    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message;
+    bool halSuccess = true;
+    int rc = halGetPropertyStrings (pConnection, pszUdi, cProps, papszKeys,
+                                    values.get(), &message);
+    if (!message)
+        halSuccess = false;
+    for (size_t i = 0; RT_SUCCESS(rc) && halSuccess && i < cProps; ++i)
+    {
+        bool fMatches = values[i] != NULL;
+        if (pfMatches != NULL)
+            pfMatches[i] = fMatches;
+        else
+            halSuccess = fMatches;
+        try
+        {
+            pMatches->push_back(fMatches ? values[i] : "");
+        }
+        catch(std::bad_alloc &e)
+        {
+            rc = VERR_NO_MEMORY;
+        }
+    }
+    if (pfSuccess != NULL)
+        *pfSuccess = halSuccess;
+    if (RT_SUCCESS(rc) && halSuccess)
+    {
+        Assert(pMatches->size() == cProps);
+        AssertForEach(j, size_t, 0, cProps,    (pfMatches == NULL)
+                                            || (pfMatches[j] == true)
+                                            || ((pfMatches[j] == false) && (pMatches[j].size() == 0)));
+    }
+    LogFlowFunc (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
+    return rc;
+}
+
+
+/**
+ * Helper function to query the hal subsystem for information about USB devices
+ * attached to the system.
+ * @returns iprt status code
+ * @param   pList      where to add information about the devices detected
+ * @param   pfSuccess  will be set to true if all interactions with hal
+ *                     succeeded and to false otherwise.  Optional.
+ *
+ * @returns IPRT status code
+ */
+/* static */
+int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
+{
+    AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
+                 VERR_INVALID_POINTER);
+    LogFlowFunc (("pList=%p, pfSuccess=%p\n", pList, pfSuccess));
+    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
+    bool halSuccess = true;  /* We set this to false to abort the operation. */
+    autoDBusError dbusError;
+
+    RTMemAutoPtr<DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
+    RTMemAutoPtr<DBusConnection, VBoxHalShutdown> dbusConnection;
+    DBusMessageIter iterFind, iterUdis;
+
+    /* Connect to hal */
+    rc = halInit (&dbusConnection);
+    if (!dbusConnection)
+        halSuccess = false;
+    /* Get an array of all devices in the usb_device subsystem */
+    if (halSuccess && RT_SUCCESS(rc))
+    {
+        rc = halFindDeviceStringMatch(dbusConnection.get(), "info.subsystem",
+                                      "usb_device", &replyFind);
+        if (!replyFind)
+            halSuccess = false;
+    }
+    if (halSuccess && RT_SUCCESS(rc))
+    {
+        dbus_message_iter_init(replyFind.get(), &iterFind);
+        if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
+            halSuccess = false;
+    }
+    /* Recurse down into the array and query interesting information about the
+     * entries. */
+    if (halSuccess && RT_SUCCESS(rc))
+        dbus_message_iter_recurse(&iterFind, &iterUdis);
+    for (;    halSuccess && RT_SUCCESS(rc)
+           && dbus_message_iter_get_arg_type(&iterUdis) == DBUS_TYPE_STRING;
+         dbus_message_iter_next(&iterUdis))
+    {
+        /* Get the device node and the sysfs path for the current entry. */
+        const char *pszUdi;
+        dbus_message_iter_get_basic (&iterUdis, &pszUdi);
+        static const char *papszKeys[] = { "linux.device_file", "linux.sysfs_path" };
+        char *papszValues[RT_ELEMENTS(papszKeys)];
+        rc = halGetPropertyStrings(dbusConnection.get(), pszUdi, RT_ELEMENTS(papszKeys),
+                                   papszKeys, papszValues, &replyGet);
+        const char *pszDevice = papszValues[0], *pszSysfsPath = papszValues[1];
+        /* Get the interfaces. */
+        if (!!replyGet && pszDevice && pszSysfsPath)
+        {
+            USBDeviceInfo info(pszDevice, pszSysfsPath);
+            bool ifaceSuccess = true;  /* If we can't get the interfaces, just
+                                        * skip this one device. */
+            rc = getUSBInterfacesFromHal(&info.mInterfaces, pszUdi, &ifaceSuccess);
+            if (RT_SUCCESS(rc) && halSuccess && ifaceSuccess)
+                try
+                {
+                    pList->push_back(info);
+                }
+                catch(std::bad_alloc &e)
+                {
+                    rc = VERR_NO_MEMORY;
+                }
+        }
+    }
+    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
+        rc = VERR_NO_MEMORY;
+    if (pfSuccess != NULL)
+        *pfSuccess = halSuccess;
+    LogFlow(("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
+    dbusError.FlowLog();
+    return rc;
+}
+
+/**
+ * Helper function to query the hal subsystem for information about USB devices
+ * attached to the system, using the older API.
+ * @returns iprt status code
+ * @param   pList      where to add information about the devices detected
+ * @param   pfSuccess  will be set to true if all interactions with hal
+ *                     succeeded and to false otherwise.  Optional.
+ *
+ * @returns IPRT status code
+ */
+/* static */
+int getOldUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
+{
+    AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
+                 VERR_INVALID_POINTER);
+    LogFlowFunc (("pList=%p, pfSuccess=%p\n", pList, pfSuccess));
+    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
+    bool halSuccess = true;  /* We set this to false to abort the operation. */
+    autoDBusError dbusError;
+
+    RTMemAutoPtr<DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
+    RTMemAutoPtr<DBusConnection, VBoxHalShutdown> dbusConnection;
+    DBusMessageIter iterFind, iterUdis;
+
+    /* Connect to hal */
+    rc = halInit(&dbusConnection);
+    if (!dbusConnection)
+        halSuccess = false;
+    /* Get an array of all devices in the usb_device subsystem */
+    if (halSuccess && RT_SUCCESS(rc))
+    {
+        rc = halFindDeviceStringMatch(dbusConnection.get(), "info.category",
+                                       "usbraw", &replyFind);
+        if (!replyFind)
+            halSuccess = false;
+    }
+    if (halSuccess && RT_SUCCESS(rc))
+    {
+        dbus_message_iter_init(replyFind.get(), &iterFind);
+        if (dbus_message_iter_get_arg_type(&iterFind) != DBUS_TYPE_ARRAY)
+            halSuccess = false;
+    }
+    /* Recurse down into the array and query interesting information about the
+     * entries. */
+    if (halSuccess && RT_SUCCESS(rc))
+        dbus_message_iter_recurse(&iterFind, &iterUdis);
+    for (;    halSuccess && RT_SUCCESS(rc)
+           && dbus_message_iter_get_arg_type(&iterUdis) == DBUS_TYPE_STRING;
+         dbus_message_iter_next(&iterUdis))
+    {
+        /* Get the device node and the sysfs path for the current entry. */
+        const char *pszUdi;
+        dbus_message_iter_get_basic(&iterUdis, &pszUdi);
+        static const char *papszKeys[] = { "linux.device_file", "info.parent" };
+        char *papszValues[RT_ELEMENTS(papszKeys)];
+        rc = halGetPropertyStrings(dbusConnection.get(), pszUdi, RT_ELEMENTS(papszKeys),
+                                   papszKeys, papszValues, &replyGet);
+        const char *pszDevice = papszValues[0], *pszSysfsPath = papszValues[1];
+        /* Get the interfaces. */
+        if (!!replyGet && pszDevice && pszSysfsPath)
+        {
+            USBDeviceInfo info(pszDevice, pszSysfsPath);
+            bool ifaceSuccess = false;  /* If we can't get the interfaces, just
+                                         * skip this one device. */
+            rc = getUSBInterfacesFromHal(&info.mInterfaces, pszSysfsPath,
+                                         &ifaceSuccess);
+            if (RT_SUCCESS(rc) && halSuccess && ifaceSuccess)
+                try
+                {
+                    pList->push_back(info);
+                }
+                catch(std::bad_alloc &e)
+                {
+                    rc = VERR_NO_MEMORY;
+                }
+        }
+    }
+    if (dbusError.HasName(DBUS_ERROR_NO_MEMORY))
+        rc = VERR_NO_MEMORY;
+    if (pfSuccess != NULL)
+        *pfSuccess = halSuccess;
+    LogFlow(("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
+    dbusError.FlowLog();
+    return rc;
+}
+
 
 /**
