VirtualBox

Changeset 15401 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Dec 12, 2008 10:05:34 PM (16 years ago)
Author:
vboxsync
Message:

Main: added USB to HostHardwareLinux.cpp

Location:
trunk/src/VBox/Main
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/HostHardwareLinux.h

    r14991 r15401  
    77
    88/*
    9  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     9 * Copyright (C) 2008 Sun Microsystems, Inc.
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2121 * additional information or have any questions.
    2222 */
     23
     24#ifndef ____H_HOSTHARDWARELINUX
     25# define ____H_HOSTHARDWARELINUX
    2326
    2427#include <iprt/err.h>
     
    111114typedef VBoxMainDriveInfo::DriveInfo DriveInfo;
    112115
     116/**
     117 * Class for probing and returning information about host USB devices
     118 */
     119class VBoxMainUSBDeviceInfo
     120{
     121public:
     122    /** Structure describing a host USB device */
     123    struct USBDeviceInfo
     124    {
     125        /** The device node of the device. */
     126        std::string mDevice;
     127        /** The sysfs path of the device. */
     128        std::string mSysfsPath;
     129        /** Type for the list of interfaces. */
     130        typedef std::vector <std::string> InterfaceList;
     131        /** The sysfs paths of the device's interfaces. */
     132        InterfaceList mInterfaces;
     133
     134        /** Constructors */
     135        USBDeviceInfo (std::string aDevice, std::string aSysfsPath)
     136            : mDevice (aDevice), mSysfsPath (aSysfsPath) {}
     137        USBDeviceInfo () {}
     138    };
     139   
     140    /** List (resp vector) holding drive information */
     141    typedef std::vector <USBDeviceInfo> DeviceInfoList;
     142
     143    /**
     144     * Search for host USB devices and rebuild the list, which remains empty
     145     * until the first time it is called.
     146     * @returns iprt status code
     147     */
     148    int UpdateDevices ();
     149
     150    /** Get the first element in the list of USB devices. */
     151    DeviceInfoList::const_iterator DevicesBegin()
     152    {
     153        return mDeviceList.begin();
     154    }
     155
     156    /** Get the last element in the list of USB devices. */
     157    DeviceInfoList::const_iterator DevicesEnd()
     158    {
     159        return mDeviceList.end();
     160    }
     161
     162private:
     163    /** The list of currently available USB devices */
     164    DeviceInfoList mDeviceList;
     165};
     166
     167typedef VBoxMainUSBDeviceInfo::DeviceInfoList USBDeviceInfoList;
     168typedef VBoxMainUSBDeviceInfo::USBDeviceInfo USBDeviceInfo;
     169typedef VBoxMainUSBDeviceInfo::USBDeviceInfo::InterfaceList USBInterfaceList;
     170
     171class VBoxMainHotplugWaiter
     172{
     173    /** Opaque context struct. */
     174    struct Context;
     175
     176    /** Opaque waiter context. */
     177    Context *mContext;
     178public:
     179    /** Constructor */
     180    VBoxMainHotplugWaiter (void);
     181    /** Destructor. */
     182    ~VBoxMainHotplugWaiter (void);
     183    /**
     184     * Wait for a hotplug event.
     185     *
     186     * @returns  VINF_SUCCESS if an event occurred or if Interrupt() was called.
     187     * @returns  VERR_TRY_AGAIN if the wait failed but this might (!) be a
     188     *           temporary failure.
     189     * @returns  VERR_NOT_SUPPORTED if the wait failed and will definitely not
     190     *           succeed if retried.
     191     * @returns  Possibly other iprt status codes otherwise.
     192     */
     193    int Wait (void);
     194    /** Interrupts an active wait. */
     195    void Interrupt (void);
     196};
     197
     198#endif /* ____H_HOSTHARDWARELINUX */
     199
  • trunk/src/VBox/Main/include/vbox-dbus.h

    r15058 r15401  
    2929#define LIB_DBUS_1_3 "libdbus-1.so.3"
    3030
    31 /** Types from the dbus header files which we need.  These are taken more or less
    32    verbatim from the DBus public interface header files. */
     31/** Types and defines from the dbus header files which we need.  These are
     32 * taken more or less verbatim from the DBus public interface header files. */
    3333struct DBusError
    3434{
     
    6868typedef struct DBusMessageIter DBusMessageIter;
    6969
    70 /** Defines from the dbus header files which we need.  These are taken more or less
    71     verbatim from the DBus public interface header files. */
    7270#define DBUS_ERROR_NO_MEMORY                  "org.freedesktop.DBus.Error.NoMemory"
    7371#define DBUS_TYPE_STRING        ((int) 's')
    7472#define DBUS_TYPE_ARRAY         ((int) 'a')
    7573#define DBUS_TYPE_DICT_ENTRY    ((int) 'e')
     74
     75typedef enum
     76{
     77  DBUS_HANDLER_RESULT_HANDLED,         /**< Message has had its effect - no need
     78 to run more handlers. */
     79  DBUS_HANDLER_RESULT_NOT_YET_HANDLED, /**< Message has not had any effect - see
     80 if other handlers want it. */
     81  DBUS_HANDLER_RESULT_NEED_MEMORY      /**< Need more memory in order to return
     82#DBUS_HANDLER_RESULT_HANDLED or #DBUS_HANDLER_RESULT_NOT_YET_HANDLED. Please try
     83 again later with more memory. */
     84} DBusHandlerResult;
     85
     86typedef DBusHandlerResult (*DBusHandleMessageFunction) (DBusConnection *,
     87                                                        DBusMessage *, void *);
     88typedef void (*DBusFreeFunction) (void *);
    7689
    7790/** The following are the symbols which we need from libdbus-1. */
     
    100113extern void (*dbus_message_iter_get_basic) (DBusMessageIter *, void *);
    101114extern dbus_bool_t (*dbus_message_iter_next) (DBusMessageIter *);
     115extern dbus_bool_t (*dbus_connection_add_filter) (DBusConnection *, DBusHandleMessageFunction,
     116                                                  void *, DBusFreeFunction);
     117extern void (*dbus_connection_remove_filter) (DBusConnection *, DBusHandleMessageFunction,
     118                                              void *);
     119extern dbus_bool_t (*dbus_connection_read_write_dispatch) (DBusConnection *, int);
     120extern dbus_bool_t (*dbus_message_is_signal) (DBusMessage *, const char *, const char *);
    102121
    103122extern bool VBoxDBusCheckPresence(void);
  • trunk/src/VBox/Main/linux/HostHardwareLinux.cpp

    r15058 r15401  
    77
    88/*
    9  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     9 * Copyright (C) 2008 Sun Microsystems, Inc.
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    6262
    6363/*******************************************************************************
    64 *   Defines and Typedefs                                                       *
     64*   Typedefs and Defines                                                       *
    6565*******************************************************************************/
    6666
    67 typedef VBoxMainDriveInfo::DriveInfoList DriveInfoList;
    68 typedef VBoxMainDriveInfo::DriveInfo DriveInfo;
     67enum { DBUS_POLL_TIMEOUT = 2000 /* ms */ };
     68
    6969
    7070static bool validateDevice(const char *deviceNode, bool isDVD);
     
    7373static int getDVDInfoFromMTab(char *mountTable, DriveInfoList *pList);
    7474#ifdef VBOX_WITH_DBUS
    75 static int halInit(DBusConnection **ppConnection);
    7675/* This must be extern to be used in the RTMemAutoPtr template */
    7776extern void halShutdown (DBusConnection *pConnection);
     77
     78static int halInit(RTMemAutoPtr <DBusConnection, halShutdown> *pConnection);
    7879static int halFindDeviceStringMatch (DBusConnection *pConnection,
    7980                                     const char *pszKey, const char *pszValue,
    80                                      DBusMessage **ppMessage);
     81                                     RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage);
    8182static int halGetPropertyStrings (DBusConnection *pConnection,
    8283                                  const char *pszUdi, size_t cKeys,
    8384                                  const char **papszKeys, char **papszValues,
    84                                   DBusMessage **ppMessage);
     85                                  RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage);
    8586static int getDriveInfoFromHal(DriveInfoList *pList, bool isDVD,
    8687                               bool *pfSuccess);
     88static int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess);
     89static int getUSBInterfacesFromHal(std::vector <std::string> *pList,
     90                                   const char *pcszUdi, bool *pfSuccess);
     91static DBusHandlerResult dbusFilterFunction (DBusConnection *pConnection,
     92                                             DBusMessage *pMessage, void *pvUser);
    8793#endif  /* VBOX_WITH_DBUS */
    8894
     
    182188    LogFlowThisFunc (("rc=%Rrc\n", rc));
    183189    return rc;
     190}
     191
     192/**
     193 * Updates the list of host USB devices.
     194 *
     195 * @returns iprt status code
     196 */
     197int VBoxMainUSBDeviceInfo::UpdateDevices ()
     198{
     199    LogFlowThisFunc (("entered\n"));
     200    int rc = VINF_SUCCESS;
     201    bool success = false;  /* Have we succeeded in finding anything yet? */
     202    try
     203    {
     204        mDeviceList.clear();
     205#if defined(RT_OS_LINUX)
     206#ifdef VBOX_WITH_DBUS
     207        if (RT_SUCCESS (rc) && VBoxDBusCheckPresence() && (!success || testing()))
     208            rc = getUSBDeviceInfoFromHal(&mDeviceList, &success);
     209#endif /* VBOX_WITH_DBUS defined */
     210#endif /* RT_OS_LINUX */
     211    }
     212    catch (std::bad_alloc)
     213    {
     214        rc = VERR_NO_MEMORY;
     215    }
     216    LogFlowThisFunc (("rc=%Rrc\n", rc));
     217    return rc;
     218}
     219
     220struct VBoxMainHotplugWaiter::Context
     221{
     222#if defined RT_OS_LINUX && defined VBOX_WITH_DBUS
     223    /** The connection to DBus */
     224    RTMemAutoPtr <DBusConnection, halShutdown> mConnection;
     225    /** Semaphore which is set when a device is hotplugged and reset when
     226     * it is read. */
     227    bool mTriggered;
     228    /** A flag to say that we wish to interrupt the current wait. */
     229    bool mInterrupt;
     230#endif  /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */
     231};
     232
     233/** Constructor */
     234VBoxMainHotplugWaiter::VBoxMainHotplugWaiter ()
     235{
     236#if defined RT_OS_LINUX && defined VBOX_WITH_DBUS
     237    int rc = VINF_SUCCESS;
     238
     239    mContext = new Context;
     240    for (unsigned i = 0; RT_SUCCESS(rc) && i < 5 && !mContext->mConnection; ++i)
     241    {
     242        rc = halInit (&mContext->mConnection);
     243    }
     244    if (!mContext->mConnection)
     245        rc = VERR_NOT_SUPPORTED;
     246    if (   RT_SUCCESS (rc)
     247        && !dbus_connection_add_filter (mContext->mConnection.get(),
     248                                        dbusFilterFunction,
     249                                        &mContext->mTriggered, NULL))
     250        rc = VERR_NO_MEMORY;
     251    if (RT_FAILURE (rc))
     252        mContext->mConnection.reset();
     253#endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */
     254}
     255
     256/** Destructor */
     257VBoxMainHotplugWaiter::~VBoxMainHotplugWaiter ()
     258{
     259#if defined RT_OS_LINUX && defined VBOX_WITH_DBUS
     260    if (!!mContext->mConnection)
     261        dbus_connection_remove_filter (mContext->mConnection.get(), dbusFilterFunction,
     262                                       &mContext->mTriggered);
     263    delete mContext;
     264#endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */
     265}
     266
     267/**
     268 * Wait for a hotplug event.
     269 *
     270 * @returns  VINF_SUCCESS if an event occurred or if Exit() was called.
     271 * @returns  VERR_TRY_AGAIN if something failed at the DBus level.
     272 * @returns  VERR_NOT_SUPPORTED if the service could not be contacted.
     273 * @returns  Possibly other iprt status codes otherwise.
     274 */
     275int VBoxMainHotplugWaiter::Wait()
     276{
     277    int rc = VINF_SUCCESS;
     278#if defined RT_OS_LINUX && defined VBOX_WITH_DBUS
     279    if (!mContext->mConnection)
     280        rc = VERR_NOT_SUPPORTED;
     281    bool connected = true;
     282    mContext->mTriggered = false;
     283    mContext->mInterrupt = false;
     284    while (   RT_SUCCESS (rc) && connected && !mContext->mTriggered
     285           && !mContext->mInterrupt)
     286        connected = dbus_connection_read_write_dispatch (mContext->mConnection.get(),
     287                                                         DBUS_POLL_TIMEOUT);
     288    if (!connected)
     289        rc = VERR_TRY_AGAIN;
     290#else  /* !(defined RT_OS_LINUX && defined VBOX_WITH_DBUS) */
     291    rc = VERR_NOT_IMPLEMENTED;
     292#endif  /* !(defined RT_OS_LINUX && defined VBOX_WITH_DBUS) */
     293    return rc;
     294}
     295
     296void VBoxMainHotplugWaiter::Interrupt()
     297{
     298#if defined RT_OS_LINUX && defined VBOX_WITH_DBUS
     299    mContext->mInterrupt = true;
     300#endif  /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */
    184301}
    185302
     
    429546 */
    430547/* static */
    431 int halInit (DBusConnection **ppConnection)
    432 {
    433     AssertReturn(VALID_PTR (ppConnection), VERR_INVALID_POINTER);
    434     LogFlowFunc (("ppConnection=%p\n", ppConnection));
     548int halInit (RTMemAutoPtr <DBusConnection, halShutdown> *pConnection)
     549{
     550    AssertReturn(VALID_PTR (pConnection), VERR_INVALID_POINTER);
     551    LogFlowFunc (("pConnection=%p\n", pConnection));
    435552    int rc = VINF_SUCCESS;
    436553    bool halSuccess = true;
     
    459576    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
    460577        rc = VERR_NO_MEMORY;
    461     *ppConnection = halSuccess ? dbusConnection.release() : NULL;
    462     LogFlowFunc(("rc=%Rrc, *ppConnection=%p\n", rc, *ppConnection));
     578    if (halSuccess)
     579        *pConnection = dbusConnection.release();
     580    LogFlowFunc(("rc=%Rrc, (*pConnection).get()=%p\n", rc, (*pConnection).get()));
    463581    dbusError.FlowLog();
    464582    return rc;
     
    489607/**
    490608 * Find the UDIs of hal entries that contain Key=Value property.
    491  * @returns iprt status code
     609 * @returns iprt status code.  If a non-fatal error occurs, we return success
     610 *          but reset pMessage to NULL.
    492611 * @param   pConnection an initialised connection DBus
    493612 * @param   pszKey      the property key
    494613 * @param   pszValue    the property value
    495  * @param   ppMessage   where to store the return DBus message.  This must be
    496  *                      parsed to get at the UDIs.  NOT optional.  The caller
    497  *                      is responsible for freeing this.
     614 * @param   pMessage    where to store the return DBus message.  This must be
     615 *                      parsed to get at the UDIs.  NOT optional.
    498616 */
    499617/* static */
    500618int halFindDeviceStringMatch (DBusConnection *pConnection, const char *pszKey,
    501                               const char *pszValue, DBusMessage **ppMessage)
     619                              const char *pszValue,
     620                              RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage)
    502621{
    503622    AssertReturn(   VALID_PTR (pConnection) && VALID_PTR (pszKey)
    504                  && VALID_PTR (pszValue) && VALID_PTR (ppMessage),
     623                 && VALID_PTR (pszValue) && VALID_PTR (pMessage),
    505624                 VERR_INVALID_POINTER);
    506     LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, ppMessage=%p\n",
    507                   pConnection, pszKey, pszValue, ppMessage));
    508     int rc = VINF_SUCCESS;
    509     bool halSuccess = true;
     625    LogFlowFunc (("pConnection=%p, pszKey=%s, pszValue=%s, pMessage=%p\n",
     626                  pConnection, pszKey, pszValue, pMessage));
     627    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
     628    bool halSuccess = true;  /* We set this to false to abort the operation. */
    510629    autoDBusError dbusError;
    511     RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message;
    512     DBusMessage *pReply = NULL;
     630
     631    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
    513632    if (halSuccess && RT_SUCCESS (rc))
    514633    {
     
    526645        dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszKey);
    527646        dbus_message_iter_append_basic (&iterAppend, DBUS_TYPE_STRING, &pszValue);
    528         pReply = dbus_connection_send_with_reply_and_block (pConnection,
     647        reply = dbus_connection_send_with_reply_and_block (pConnection,
    529648                                                            message.get(), -1,
    530649                                                            &dbusError.get());
    531         if (pReply == NULL)
    532             halSuccess = false;
    533     }
    534     *ppMessage = pReply;
    535     LogFlowFunc (("rc=%Rrc, *ppMessage=%p\n", rc, *ppMessage));
     650        if (!reply)
     651            halSuccess = false;
     652    }
     653    *pMessage = reply.release ();
     654    LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get()));
    536655    dbusError.FlowLog();
    537656    return rc;
     
    541660 * Read a set of string properties for a device.  If some of the properties are
    542661 * not of type DBUS_TYPE_STRING then a NULL pointer will be returned for them.
    543  * @returns iprt status code
     662 * @returns iprt status code.  If the operation failed for non-fatal reasons
     663 *          then we return success and leave pMessage untouched - reset it
     664 *          before the call to detect this.
    544665 * @param   pConnection  an initialised connection DBus
    545666 * @param   pszUdi       the Udi of the device
     
    550671 *                       returned in @a ppMessage is freed.  Undefined if
    551672 *                       the message is NULL.
    552  * @param   ppMessage    where to store the return DBus message.  The caller
     673 * @param   pMessage     where to store the return DBus message.  The caller
    553674 *                       is responsible for freeing this once they have
    554675 *                       finished with the value strings.  NOT optional.
     
    557678int halGetPropertyStrings (DBusConnection *pConnection, const char *pszUdi,
    558679                           size_t cProps, const char **papszKeys,
    559                            char **papszValues, DBusMessage **ppMessage)
     680                           char **papszValues,
     681                           RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> *pMessage)
    560682{
    561683    AssertReturn(   VALID_PTR (pConnection) && VALID_PTR (pszUdi)
    562684                 && VALID_PTR (papszKeys) && VALID_PTR (papszValues)
    563                  && VALID_PTR (ppMessage),
     685                 && VALID_PTR (pMessage),
    564686                 VERR_INVALID_POINTER);
    565     LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, papszValues=%p, ppMessage=%p\n",
    566                   pConnection, pszUdi, cProps, papszKeys, papszValues, ppMessage));
    567     int rc = VINF_SUCCESS;
    568     bool halSuccess = true;
     687    LogFlowFunc (("pConnection=%p, pszUdi=%s, cProps=%llu, papszKeys=%p, papszValues=%p, pMessage=%p\n",
     688                  pConnection, pszUdi, cProps, papszKeys, papszValues, pMessage));
     689    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
     690    bool halSuccess = true;  /* We set this to false to abort the operation. */
    569691    autoDBusError dbusError;
     692
    570693    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, reply;
    571694    DBusMessageIter iterGet, iterProps, iterKey, iterValue;
     
    574697    for (size_t i = 0; i < cProps; ++i)
    575698        papszValues[i] = NULL;
     699
     700    /* Send a GetAllProperties message to hald */
    576701    message = dbus_message_new_method_call ("org.freedesktop.Hal", pszUdi,
    577702                                            "org.freedesktop.Hal.Device",
     
    587712            halSuccess = false;
    588713    }
     714
     715    /* Parse the reply */
    589716    if (halSuccess && RT_SUCCESS (rc))
    590717    {
     
    596723    if (halSuccess && RT_SUCCESS (rc))
    597724        dbus_message_iter_recurse (&iterGet, &iterProps);
     725    /* Go through all entries in the reply and see if any match our keys. */
    598726    while (   halSuccess && RT_SUCCESS (rc)
    599727           &&    dbus_message_iter_get_arg_type (&iterProps)
     
    606734        dbus_message_iter_next (&iterEntry);
    607735        dbus_message_iter_recurse (&iterEntry, &iterValue);
     736        /* Fill in any matches. */
    608737        for (size_t i = 0; i < cProps; ++i)
    609738            if (strcmp (pszKey, papszKeys[i]) == 0)
     
    615744    }
    616745    if (RT_SUCCESS (rc) && halSuccess)
    617         *ppMessage = reply.release();
    618     else
    619         *ppMessage = NULL;
     746        *pMessage = reply.release();
    620747    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
    621             rc = VERR_NO_MEMORY;
    622     LogFlowFunc (("rc=%Rrc, *ppMessage=%p\n", rc, *ppMessage));
     748        rc = VERR_NO_MEMORY;
     749    LogFlowFunc (("rc=%Rrc, *pMessage.value()=%p\n", rc, (*pMessage).get()));
    623750    dbusError.FlowLog();
    624751    return rc;
     
    642769                 VERR_INVALID_POINTER);
    643770    LogFlowFunc (("pList=%p, isDVD=%d, pfSuccess=%p\n", pList, isDVD, pfSuccess));
    644     DBusConnection *pConnection;
     771    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
     772    bool halSuccess = true;  /* We set this to false to abort the operation. */
    645773    autoDBusError dbusError;
    646     DBusMessage *pReply;
     774
    647775    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
     776    RTMemAutoPtr <DBusConnection, halShutdown> dbusConnection;
    648777    DBusMessageIter iterFind, iterUdis;
    649     bool halSuccess = true;  /* Did something go wrong with hal or DBus? */
    650     int rc = VINF_SUCCESS;  /* Did a fatal error occur? */
    651 
    652     rc = halInit (&pConnection);
    653     RTMemAutoPtr <DBusConnection, halShutdown> dbusConnection;
    654     dbusConnection = pConnection;
     778
     779    rc = halInit (&dbusConnection);
    655780    if (!dbusConnection)
    656781        halSuccess = false;
    657782    if (halSuccess && RT_SUCCESS (rc))
    658783    {
    659         rc = halFindDeviceStringMatch (pConnection, "storage.drive_type",
    660                                        isDVD ? "cdrom" : "floppy", &pReply);
    661         replyFind = pReply;
     784        rc = halFindDeviceStringMatch (dbusConnection.get(), "storage.drive_type",
     785                                       isDVD ? "cdrom" : "floppy", &replyFind);
    662786        if (!replyFind)
    663787            halSuccess = false;
     
    681805                { "block.device", "info.product", "info.vendor" };
    682806        char *papszValues[RT_ELEMENTS (papszKeys)];
    683         rc = halGetPropertyStrings (pConnection, pszUdi, RT_ELEMENTS (papszKeys),
    684                                     papszKeys, papszValues, &pReply);
    685         replyGet = pReply;
     807        rc = halGetPropertyStrings (dbusConnection.get(), pszUdi, RT_ELEMENTS (papszKeys),
     808                                    papszKeys, papszValues, &replyGet);
    686809        std::string description;
    687810        const char *pszDevice = papszValues[0], *pszProduct = papszValues[1],
    688811                   *pszVendor = papszValues[2];
    689         if (!!replyGet && pszDevice)
     812        if (!!replyGet && pszDevice == NULL)
     813            halSuccess = false;
     814        if (!!replyGet && pszDevice != NULL)
    690815        {
    691816            if ((pszVendor != NULL) && (pszVendor[0] != '\0'))
     
    697822    }
    698823    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
    699             rc = VERR_NO_MEMORY;
     824        rc = VERR_NO_MEMORY;
    700825    if (pfSuccess != NULL)
    701826        *pfSuccess = halSuccess;
     
    704829    return rc;
    705830}
     831
     832/**
     833 * Helper function to query the hal subsystem for information about USB devices
     834 * attached to the system.
     835 * @returns iprt status code
     836 * @param   pList      where to add information about the devices detected
     837 * @param   pfSuccess  will be set to true if all interactions with hal
     838 *                     succeeded and to false otherwise.  Optional.
     839 *
     840 * @returns IPRT status code
     841 */
     842/* static */
     843int getUSBDeviceInfoFromHal(USBDeviceInfoList *pList, bool *pfSuccess)
     844{
     845    AssertReturn(VALID_PTR (pList) && (pfSuccess == NULL || VALID_PTR (pfSuccess)),
     846                 VERR_INVALID_POINTER);
     847    LogFlowFunc (("pList=%p, pfSuccess=%p\n", pList, pfSuccess));
     848    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
     849    bool halSuccess = true;  /* We set this to false to abort the operation. */
     850    autoDBusError dbusError;
     851
     852    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
     853    RTMemAutoPtr <DBusConnection, halShutdown> dbusConnection;
     854    DBusMessageIter iterFind, iterUdis;
     855
     856    rc = halInit (&dbusConnection);
     857    if (!dbusConnection)
     858        halSuccess = false;
     859    if (halSuccess && RT_SUCCESS (rc))
     860    {
     861        rc = halFindDeviceStringMatch (dbusConnection.get(), "info.subsystem",
     862                                       "usb_device", &replyFind);
     863        if (!replyFind)
     864            halSuccess = false;
     865    }
     866    if (halSuccess && RT_SUCCESS (rc))
     867    {
     868        dbus_message_iter_init (replyFind.get(), &iterFind);
     869        if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
     870            halSuccess = false;
     871    }
     872    if (halSuccess && RT_SUCCESS (rc))
     873        dbus_message_iter_recurse (&iterFind, &iterUdis);
     874    for (;    halSuccess && RT_SUCCESS (rc)
     875           && dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
     876         dbus_message_iter_next(&iterUdis))
     877    {
     878        /* Now get the device node and the sysfs path from the iterator */
     879        const char *pszUdi;
     880        dbus_message_iter_get_basic (&iterUdis, &pszUdi);
     881        static const char *papszKeys[] = { "linux.device_file", "linux.sysfs_path" };
     882        char *papszValues[RT_ELEMENTS (papszKeys)];
     883        rc = halGetPropertyStrings (dbusConnection.get(), pszUdi, RT_ELEMENTS (papszKeys),
     884                                    papszKeys, papszValues, &replyGet);
     885        std::string description;
     886        const char *pszDevice = papszValues[0], *pszSysfsPath = papszValues[1];
     887        /* Get the interfaces for this device. */
     888        if (!!replyGet && pszDevice && pszSysfsPath)
     889        {
     890            USBDeviceInfo info (pszDevice, pszSysfsPath);
     891            bool ifaceSuccess = true;  /* If we can't get the interfaces, just
     892                                        * skip this one device. */           
     893            rc = getUSBInterfacesFromHal (&info.mInterfaces, pszUdi, &ifaceSuccess);
     894            if (RT_SUCCESS(rc) && halSuccess && ifaceSuccess)
     895                pList->push_back (info);
     896        }
     897    }
     898    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
     899        rc = VERR_NO_MEMORY;
     900    if (pfSuccess != NULL)
     901        *pfSuccess = halSuccess;
     902    LogFlow (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
     903    dbusError.FlowLog();
     904    return rc;
     905}
     906
     907/**
     908 * Helper function to query the hal subsystem for information about USB devices
     909 * attached to the system.
     910 * @returns iprt status code
     911 * @param   pList      where to add information about the devices detected.  If
     912 *                     certain interfaces are not found (@a pfFound is false on
     913 *                     return) this may contain invalid information.
     914 * @param   pcszUdi    the hal UDI of the device
     915 * @param   pfSuccess  will be set to true if the operation succeeds and to
     916 *                     false if it fails for non-critical reasons.  Optional.
     917 *
     918 * @returns IPRT status code
     919 */
     920/* static */
     921int getUSBInterfacesFromHal(std::vector <std::string> *pList,
     922                            const char *pcszUdi, bool *pfSuccess)
     923{
     924    AssertReturn(VALID_PTR (pList) && VALID_PTR (pcszUdi) &&
     925                 (pfSuccess == NULL || VALID_PTR (pfSuccess)),
     926                 VERR_INVALID_POINTER);
     927    LogFlowFunc (("pList=%p, pcszUdi=%s, pfSuccess=%p\n", pList, pcszUdi,
     928                  pfSuccess));
     929    int rc = VINF_SUCCESS;  /* We set this to failure on fatal errors. */
     930    bool halSuccess = true;  /* We set this to false to abort the operation. */
     931    autoDBusError dbusError;
     932
     933    RTMemAutoPtr <DBusMessage, VBoxDBusMessageUnref> message, replyFind, replyGet;
     934    RTMemAutoPtr <DBusConnection, halShutdown> dbusConnection;
     935    DBusMessageIter iterFind, iterUdis;
     936
     937    rc = halInit (&dbusConnection);
     938    if (!dbusConnection)
     939        halSuccess = false;
     940    if (halSuccess && RT_SUCCESS (rc))
     941    {
     942        /* Look for children of the current UDI. */
     943        rc = halFindDeviceStringMatch (dbusConnection.get(), "info.parent",
     944                                       pcszUdi, &replyFind);
     945        if (!replyFind)
     946            halSuccess = false;
     947    }
     948    if (halSuccess && RT_SUCCESS (rc))
     949    {
     950        dbus_message_iter_init (replyFind.get(), &iterFind);
     951        if (dbus_message_iter_get_arg_type (&iterFind) != DBUS_TYPE_ARRAY)
     952            halSuccess = false;
     953    }
     954    if (halSuccess && RT_SUCCESS (rc))
     955        dbus_message_iter_recurse (&iterFind, &iterUdis);
     956    for (;    halSuccess && RT_SUCCESS (rc)
     957           && dbus_message_iter_get_arg_type (&iterUdis) == DBUS_TYPE_STRING;
     958         dbus_message_iter_next(&iterUdis))
     959    {
     960        /* Now get the sysfs path and the subsystem from the iterator */
     961        const char *pszUdi;
     962        dbus_message_iter_get_basic (&iterUdis, &pszUdi);
     963        static const char *papszKeys[] = { "linux.sysfs_path", "info.subsystem" };
     964        char *papszValues[RT_ELEMENTS (papszKeys)];
     965        rc = halGetPropertyStrings (dbusConnection.get(), pszUdi, RT_ELEMENTS (papszKeys),
     966                                    papszKeys, papszValues, &replyGet);
     967        std::string description;
     968        const char *pszSysfsPath = papszValues[0], *pszSubsystem = papszValues[1];
     969        if (!replyGet)
     970            halSuccess = false;
     971        if (!!replyGet && pszSysfsPath == NULL)
     972            halSuccess = false;
     973        if (   halSuccess && RT_SUCCESS (rc)
     974            && RTStrCmp (pszSubsystem, "usb_device") != 0)  /* Children of buses can also be devices. */
     975            pList->push_back (pszSysfsPath);
     976    }
     977    if (dbusError.HasName (DBUS_ERROR_NO_MEMORY))
     978        rc = VERR_NO_MEMORY;
     979    if (pfSuccess != NULL)
     980        *pfSuccess = halSuccess;
     981    LogFlow (("rc=%Rrc, halSuccess=%d\n", rc, halSuccess));
     982    dbusError.FlowLog();
     983    return rc;
     984}
     985
     986/**
     987 * When it is registered with DBus, this function will be called by
     988 * dbus_connection_read_write_dispatch each time a message is received over the
     989 * DBus connection.  We check whether that message was caused by a hal device
     990 * hotplug event, and if so we set a flag.  dbus_connection_read_write_dispatch
     991 * will return after calling its filter functions, and its caller should then
     992 * check the status of the flag passed to the filter function.
     993 *
     994 * @param   pConnection The DBus connection we are using.
     995 * @param   pMessage    The DBus message which just arrived.
     996 * @param   pvUser      A pointer to the flag variable we are to set.
     997 */
     998/* static */
     999DBusHandlerResult dbusFilterFunction (DBusConnection *pConnection,
     1000                                      DBusMessage *pMessage, void *pvUser)
     1001{
     1002    bool *pTriggered = reinterpret_cast<bool *> (pvUser);
     1003    if (   dbus_message_is_signal (pMessage, "org.freedesktop.Hal.Manager",
     1004                                   "DeviceAdded")
     1005        || dbus_message_is_signal (pMessage, "org.freedesktop.Hal.Manager",
     1006                                   "DeviceRemoved"))
     1007    {
     1008        *pTriggered = true;
     1009    }
     1010    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     1011}
    7061012#endif  /* RT_OS_LINUX && VBOX_WITH_DBUS */
    7071013
  • trunk/src/VBox/Main/linux/vbox-dbus.cpp

    r15058 r15401  
    6464void (*dbus_message_iter_get_basic) (DBusMessageIter *, void *);
    6565dbus_bool_t (*dbus_message_iter_next) (DBusMessageIter *);
     66dbus_bool_t (*dbus_connection_add_filter) (DBusConnection *, DBusHandleMessageFunction,
     67                                           void *, DBusFreeFunction);
     68void (*dbus_connection_remove_filter) (DBusConnection *, DBusHandleMessageFunction,
     69                                       void *);
     70dbus_bool_t (*dbus_connection_read_write_dispatch) (DBusConnection *, int);
     71dbus_bool_t (*dbus_message_is_signal) (DBusMessage *, const char *, const char *);
    6672
    6773bool VBoxDBusCheckPresence(void)
     
    116122        && RT_SUCCESS(RTLdrGetSymbol(hLibDBus, "dbus_message_iter_next",
    117123                                     (void **) &dbus_message_iter_next))
     124        && RT_SUCCESS(RTLdrGetSymbol(hLibDBus, "dbus_connection_add_filter",
     125                                     (void **) &dbus_connection_add_filter))
     126        && RT_SUCCESS(RTLdrGetSymbol(hLibDBus, "dbus_connection_remove_filter",
     127                                     (void **) &dbus_connection_remove_filter))
     128        && RT_SUCCESS(RTLdrGetSymbol(hLibDBus, "dbus_connection_read_write_dispatch",
     129                                     (void **) &dbus_connection_read_write_dispatch))
     130        && RT_SUCCESS(RTLdrGetSymbol(hLibDBus, "dbus_message_is_signal",
     131                                     (void **) &dbus_message_is_signal))
    118132       )
    119133    {
  • trunk/src/VBox/Main/testcase/Makefile.kmk

    r15057 r15401  
    3333        $(if $(VBOX_WITH_RESOURCE_USAGE_API),tstCollector,)
    3434  PROGRAMS.linux += \
    35         $(if $(VBOX_OSE),,tstHostHardwareLinux)
     35        tstHostHardwareLinux
    3636 endif # !VBOX_WITH_TESTCASES
    3737endif # !VBOX_ONLY_SDK
     
    125125tstHostHardwareLinux_SOURCES   = \
    126126        tstHostHardwareLinux.cpp \
    127         ../linux/USBProxyServiceLinux.cpp \
    128127        ../linux/HostHardwareLinux.cpp \
    129128        ../linux/vbox-dbus.cpp
  • trunk/src/VBox/Main/testcase/tstHostHardwareLinux.cpp

    r14991 r15401  
    11/* $Id$ */
    2 
    32/** @file
    43 *
    5  * Test executable for quickly excercising/debugging the hal-based Linux USB
     4 * Test executable for quickly excercising/debugging the Linux host hardware
    65 * bits.
    76 */
     
    109 * Copyright (C) 2008 Sun Microsystems, Inc.
    1110 *
    12  * Sun Microsystems, Inc. confidential
    13  * All rights reserved
     11 * This file is part of VirtualBox Open Source Edition (OSE), as
     12 * available from http://www.virtualbox.org. This file is free software;
     13 * you can redistribute it and/or modify it under the terms of the GNU
     14 * General Public License (GPL) as published by the Free Software
     15 * Foundation, in version 2 as it comes in the "COPYING" file of the
     16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
     17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
     18 *
     19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
     20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
     21 * additional information or have any questions.
    1422 */
    15 
    16 #ifdef VBOX_USB_WITH_SYSFS
    17 # include "tstUSBLinux.h"
    18 #endif
    1923
    2024#include <HostHardwareLinux.h>
     
    2327
    2428#include <iprt/initterm.h>
     29#include <iprt/param.h>
    2530#include <iprt/stream.h>
     31#include <iprt/linux/sysfs.h>
    2632
    2733#include <iprt/cdefs.h>
    2834#include <iprt/types.h>
    2935
     36#include <errno.h>
     37#include <string.h>
     38
    3039int main()
    3140{
    3241    RTR3Init();
    33 #ifdef VBOX_USB_WITH_SYSFS
    34     USBProxyServiceLinux service;
    35     service.initSysfs();
    36     if (RT_FAILURE(service.getLastError()))
    37     {
    38         RTPrintf("Failed to initialise USBProxyServiceLinux, error %Rrc\n",
    39                  service.getLastError());
    40         return 1;
    41     }
    42     PUSBDEVICE pChain = service.getDevicesFromSysfs();
    43     if (pChain == NULL)
    44         RTPrintf("Failed to get any devices from sysfs\n.");
    45     else
    46     {
    47         PUSBDEVICE pNext = pChain;
    48         while (pNext != NULL)
    49         {
    50             RTPrintf("Device: %s (product string)\n", pNext->pszProduct);
    51             RTPrintf("  Manufacturer: %s\n", pNext->pszManufacturer);
    52             RTPrintf("  Serial number: %s\n", pNext->pszSerialNumber);
    53             RTPrintf("  Address: %s\n", pNext->pszAddress);
    54             RTPrintf("  Vendor ID: %d\n", pNext->idVendor);
    55             RTPrintf("  Product ID: %d\n", pNext->idProduct);
    56             RTPrintf("  Revision: %d.%d\n", pNext->bcdDevice >> 8, pNext->bcdDevice & 255);
    57             RTPrintf("  USB Version: %d.%d\n", pNext->bcdUSB >> 8, pNext->bcdUSB & 255);
    58             RTPrintf("  Device class: %d\n", pNext->bDeviceClass);
    59             RTPrintf("  Device subclass: %d\n", pNext->bDeviceSubClass);
    60             RTPrintf("  Device protocol: %d\n", pNext->bDeviceProtocol);
    61             RTPrintf("  Number of configurations: %d\n", pNext->bNumConfigurations);
    62             RTPrintf("  Device state: %s\n",
    63                      pNext->enmState == USBDEVICESTATE_UNUSED ? "unused"
    64                          : pNext->enmState == USBDEVICESTATE_USED_BY_HOST_CAPTURABLE ? "used by host"
    65                          : "unknown"
    66                     );
    67             RTPrintf("  Device speed: %s\n",
    68                      pNext->enmSpeed == USBDEVICESPEED_LOW ? "low"
    69                          : pNext->enmSpeed == USBDEVICESPEED_FULL ? "full"
    70                          : pNext->enmSpeed == USBDEVICESPEED_HIGH ? "high"
    71                          : "unknown"
    72                     );
    73             RTPrintf("  Serial hash: 0x%llx\n", pNext->u64SerialHash);
    74             RTPrintf("  Bus number: %d\n", pNext->bBus);
    75             RTPrintf("  Port number: %d\n", pNext->bPort);
    76             RTPrintf("  Device number: %d\n", pNext->bDevNum);
    77             RTPrintf("\n");
    78             pNext = pNext->pNext;
    79         }
    80     }
    81 #endif  /* VBOX_USB_WITH_SYSFS */
     42    g_testHostHardwareLinux = true;
     43    int rc = VINF_SUCCESS;
    8244    VBoxMainDriveInfo driveInfo;
    8345    g_testHostHardwareLinux = true;
    84     int rc = driveInfo.updateFloppies();
     46    rc = driveInfo.updateFloppies();
    8547    if (RT_SUCCESS (rc))
    8648        rc = driveInfo.updateDVDs();
     
    9254    }
    9355    RTPrintf ("Listing floppy drives detected:\n");
    94     for (VBoxMainDriveInfo::DriveInfoList::const_iterator it = driveInfo.FloppyBegin();
     56    for (DriveInfoList::const_iterator it = driveInfo.FloppyBegin();
    9557         it != driveInfo.FloppyEnd(); ++it)
    9658    {
     
    10365    }
    10466    RTPrintf ("Listing DVD drives detected:\n");
    105     for (VBoxMainDriveInfo::DriveInfoList::const_iterator it = driveInfo.DVDBegin();
     67    for (DriveInfoList::const_iterator it = driveInfo.DVDBegin();
    10668         it != driveInfo.DVDEnd(); ++it)
    10769    {
     
    11375        RTPrintf ("\n");
    11476    }
     77#ifdef VBOX_USB_WITH_SYSFS
     78    VBoxMainUSBDeviceInfo deviceInfo;
     79    rc = deviceInfo.UpdateDevices();
     80    if (RT_FAILURE (rc))
     81    {
     82        RTPrintf ("Failed to update the host USB device information, error %Rrc\n",
     83                 rc);
     84        return 1;
     85    }
     86    RTPrintf ("Listing USB devices detected:\n");
     87    for (USBDeviceInfoList::const_iterator it = deviceInfo.DevicesBegin();
     88         it != deviceInfo.DevicesEnd(); ++it)
     89    {
     90        char szProduct[1024];
     91        if (RTLinuxSysFsReadStrFile(szProduct, sizeof(szProduct),
     92                                    "%s/product", it->mSysfsPath.c_str()) == -1)
     93        {
     94            if (errno != ENOENT)
     95            {
     96                RTPrintf ("Failed to get the product name for device %s: error %s\n",
     97                          it->mDevice.c_str(), strerror(errno));
     98                return 1;
     99            }
     100            else
     101                szProduct[0] = '\0';
     102        }
     103        RTPrintf ("  device: %s (%s), sysfs path: %s\n", szProduct, it->mDevice.c_str(),
     104                  it->mSysfsPath.c_str());
     105        RTPrintf ("    interfaces:\n");
     106        for (USBInterfaceList::const_iterator it2 = it->mInterfaces.begin();
     107             it2 != it->mInterfaces.end(); ++it2)
     108        {
     109            char szDriver[RTPATH_MAX];
     110            strcpy(szDriver, "none");
     111            ssize_t size = RTLinuxSysFsGetLinkDest(szDriver, sizeof(szDriver),
     112                                                   "%s/driver", it2->c_str());
     113            if (size == -1 && errno != ENOENT)
     114            {
     115                RTPrintf ("Failed to get the driver for interface %s of device %s: error %s\n",
     116                          it2->c_str(), it->mDevice.c_str(), strerror(errno));
     117                return 1;
     118            }
     119            if (RTLinuxSysFsExists("%s/driver", it2->c_str()) != (size != -1))           
     120            {
     121                RTPrintf ("RTLinuxSysFsExists did not return the expected value for the driver link of interface %s of device %s.\n",
     122                          it2->c_str(), it->mDevice.c_str());
     123                return 1;
     124            }
     125            uint64_t u64InterfaceClass;
     126            u64InterfaceClass = RTLinuxSysFsReadIntFile(16, "%s/bInterfaceClass",
     127                                                        it2->c_str());
     128            RTPrintf ("      sysfs path: %s, driver: %s, interface class: 0x%x\n",
     129                      it2->c_str(), szDriver, u64InterfaceClass);
     130        }
     131    }
     132    RTPrintf ("Waiting for a hotplug event, Ctrl-C to abort...\n");
     133    VBoxMainHotplugWaiter waiter;
     134    waiter.Wait();
     135#endif  /* VBOX_USB_WITH_SYSFS */
    115136    return 0;
    116137}
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