VirtualBox

Changeset 37618 in vbox for trunk


Ignore:
Timestamp:
Jun 23, 2011 5:16:39 PM (13 years ago)
Author:
vboxsync
Message:

Main/USB/linux: move USBProxyLinuxChooseMethod to USBGetDevices

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

Legend:

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

    r36993 r37618  
    8585
    8686#ifdef UNIT_TEST
     87void TestUSBSetupInit(const char *pcszUsbfsRoot, bool fUsbfsAccessible,
     88                      const char *pcszDevicesRoot, bool fDevicesAccessible,
     89                      int rcMethodInitResult);
     90void TestUSBSetEnv(const char *pcszEnvUsb, const char *pcszEnvUsbRoot);
     91#endif
     92
     93/**
     94 * Selects the access method that will be used to access USB devices based on
     95 * what is available on the host and what if anything the user has specified
     96 * in the environment.
     97 * @returns iprt status value
     98 * @param  pfUsingUsbfsDevices  on success this will be set to true if
     99 *                              the prefered access method is USBFS-like and to
     100 *                              false if it is sysfs/device node-like
     101 * @param  ppcszDevicesRoot     on success the root of the tree of USBFS-like
     102 *                              device nodes will be stored here
     103 */
     104extern int USBProxyLinuxChooseMethod(bool *pfUsingUsbfsDevices,
     105                                     const char **ppcszDevicesRoot);
     106#ifdef UNIT_TEST
    87107/**
    88108 * Specify the list of devices that will appear to be available through
  • trunk/src/VBox/Main/include/USBProxyService.h

    r37617 r37618  
    197197#  endif
    198198
    199 #ifdef UNIT_TEST
    200 void TestUSBSetupInit(const char *pcszUsbfsRoot, bool fUsbfsAccessible,
    201                       const char *pcszDevicesRoot, bool fDevicesAccessible,
    202                       int rcMethodInitResult);
    203 void TestUSBSetEnv(const char *pcszEnvUsb, const char *pcszEnvUsbRoot);
    204 #endif
    205 
    206199/**
    207200 * The Linux hosted USB Proxy Service.
     
    217210    virtual int captureDevice(HostUSBDevice *aDevice);
    218211    virtual int releaseDevice(HostUSBDevice *aDevice);
    219 
    220 #  ifdef UNIT_TEST
    221     /* Test getters for querying internal state.  This will go away. */
    222     bool testGetUsingUsbfs(void) { return mUsingUsbfsDevices; }
    223     const char *testGetDevicesRoot(void) { return mDevicesRoot.c_str(); }
    224 #  endif
    225212
    226213protected:
  • trunk/src/VBox/Main/src-server/linux/USBGetDevices.cpp

    r37390 r37618  
    2323#include "USBGetDevices.h"
    2424
     25#include <VBox/err.h>
    2526#include <VBox/usb.h>
    2627#include <VBox/usblib.h>
     
    2930#include <iprt/cdefs.h>
    3031#include <iprt/ctype.h>
    31 #include <iprt/err.h>
     32#include <iprt/dir.h>
     33#include <iprt/env.h>
     34#include <iprt/file.h>
    3235#include <iprt/fs.h>
    3336#include <iprt/log.h>
     
    15031506#endif
    15041507
     1508#ifdef UNIT_TEST
     1509#  ifdef UNIT_TEST
     1510    /** The path we pretend the usbfs root is located at, or NULL. */
     1511    const char *s_pcszTestUsbfsRoot;
     1512    /** Should usbfs be accessible to the current user? */
     1513    bool s_fTestUsbfsAccessible;
     1514    /** The path we pretend the device node tree root is located at, or NULL. */
     1515    const char *s_pcszTestDevicesRoot;
     1516    /** Should the device node tree be accessible to the current user? */
     1517    bool s_fTestDevicesAccessible;
     1518    /** The result of the usbfs/inotify-specific init */
     1519    int s_rcTestMethodInitResult;
     1520    /** The value of the VBOX_USB environment variable. */
     1521    const char *s_pcszTestEnvUsb;
     1522    /** The value of the VBOX_USB_ROOT environment variable. */
     1523    const char *s_pcszTestEnvUsbRoot;
     1524#  endif
     1525
     1526/** Select which access methods will be available to the @a init method
     1527 * during unit testing, and (hack!) what return code it will see from
     1528 * the access method-specific initialisation. */
     1529void TestUSBSetupInit(const char *pcszUsbfsRoot, bool fUsbfsAccessible,
     1530                      const char *pcszDevicesRoot, bool fDevicesAccessible,
     1531                      int rcMethodInitResult)
     1532{
     1533    s_pcszTestUsbfsRoot = pcszUsbfsRoot;
     1534    s_fTestUsbfsAccessible = fUsbfsAccessible;
     1535    s_pcszTestDevicesRoot = pcszDevicesRoot;
     1536    s_fTestDevicesAccessible = fDevicesAccessible;
     1537    s_rcTestMethodInitResult = rcMethodInitResult;
     1538}
     1539
     1540/** Specify the environment that the @a init method will see during unit
     1541 * testing. */
     1542void TestUSBSetEnv(const char *pcszEnvUsb, const char *pcszEnvUsbRoot)
     1543{
     1544    s_pcszTestEnvUsb = pcszEnvUsb;
     1545    s_pcszTestEnvUsbRoot = pcszEnvUsbRoot;
     1546}
     1547
     1548/* For testing we redefine anything that accesses the outside world to
     1549 * return test values. */
     1550# define RTEnvGet(a) \
     1551    (  !RTStrCmp(a, "VBOX_USB") ? s_pcszTestEnvUsb \
     1552     : !RTStrCmp(a, "VBOX_USB_ROOT") ? s_pcszTestEnvUsbRoot \
     1553     : NULL)
     1554# define USBProxyLinuxCheckDeviceRoot(pcszPath, fUseNodes) \
     1555    (   ((fUseNodes) && s_fTestDevicesAccessible \
     1556                     && !RTStrCmp(pcszPath, s_pcszTestDevicesRoot)) \
     1557     || (!(fUseNodes) && s_fTestUsbfsAccessible \
     1558                      && !RTStrCmp(pcszPath, s_pcszTestUsbfsRoot)))
     1559# define RTDirExists(pcszDir) \
     1560    (   (pcszDir) \
     1561     && (   !RTStrCmp(pcszDir, s_pcszTestDevicesRoot) \
     1562         || !RTStrCmp(pcszDir, s_pcszTestUsbfsRoot)))
     1563# define RTFileExists(pcszFile) \
     1564    (   (pcszFile) \
     1565     && s_pcszTestUsbfsRoot \
     1566     && !RTStrNCmp(pcszFile, s_pcszTestUsbfsRoot, strlen(s_pcszTestUsbfsRoot)) \
     1567     && !RTStrCmp(pcszFile + strlen(s_pcszTestUsbfsRoot), "/devices"))
     1568#endif
     1569
     1570/**
     1571 * Selects the access method that will be used to access USB devices based on
     1572 * what is available on the host and what if anything the user has specified
     1573 * in the environment.
     1574 * @returns iprt status value
     1575 * @param  pfUsingUsbfsDevices  on success this will be set to true if
     1576 *                              the prefered access method is USBFS-like and to
     1577 *                              false if it is sysfs/device node-like
     1578 * @param  ppcszDevicesRoot     on success the root of the tree of USBFS-like
     1579 *                              device nodes will be stored here
     1580 */
     1581int USBProxyLinuxChooseMethod(bool *pfUsingUsbfsDevices,
     1582                              const char **ppcszDevicesRoot)
     1583{
     1584    /*
     1585     * We have two methods available for getting host USB device data - using
     1586     * USBFS and using sysfs.  The default choice is sysfs; if that is not
     1587     * available we fall back to USBFS.
     1588     * In the event of both failing, an appropriate error will be returned.
     1589     * The user may also specify a method and root using the VBOX_USB and
     1590     * VBOX_USB_ROOT environment variables.  In this case we don't check
     1591     * the root they provide for validity.
     1592     */
     1593    bool fUsbfsChosen = false, fSysfsChosen = false;
     1594    const char *pcszUsbFromEnv = RTEnvGet("VBOX_USB");
     1595    const char *pcszUsbRoot = NULL;
     1596    if (pcszUsbFromEnv)
     1597    {
     1598        bool fValidVBoxUSB = true;
     1599
     1600        pcszUsbRoot = RTEnvGet("VBOX_USB_ROOT");
     1601        if (!RTStrICmp(pcszUsbFromEnv, "USBFS"))
     1602        {
     1603            LogRel(("Default USB access method set to \"usbfs\" from environment\n"));
     1604            fUsbfsChosen = true;
     1605        }
     1606        else if (!RTStrICmp(pcszUsbFromEnv, "SYSFS"))
     1607        {
     1608            LogRel(("Default USB method set to \"sysfs\" from environment\n"));
     1609            fSysfsChosen = true;
     1610        }
     1611        else
     1612        {
     1613            LogRel(("Invalid VBOX_USB environment variable setting \"%s\"\n",
     1614                    pcszUsbFromEnv));
     1615            fValidVBoxUSB = false;
     1616            pcszUsbFromEnv = NULL;
     1617        }
     1618        if (!fValidVBoxUSB && pcszUsbRoot)
     1619            pcszUsbRoot = NULL;
     1620    }
     1621    if (!pcszUsbRoot)
     1622    {
     1623        if (   !fUsbfsChosen
     1624            && USBProxyLinuxCheckDeviceRoot("/dev/vboxusb", true))
     1625        {
     1626            fSysfsChosen = true;
     1627            pcszUsbRoot = "/dev/vboxusb";
     1628        }
     1629        else if (   !fSysfsChosen
     1630                 && USBProxyLinuxCheckDeviceRoot("/proc/bus/usb", false))
     1631        {
     1632            fUsbfsChosen = true;
     1633            pcszUsbRoot = "/proc/bus/usb";
     1634        }
     1635    }
     1636    else if (!USBProxyLinuxCheckDeviceRoot(pcszUsbRoot, fSysfsChosen))
     1637        pcszUsbRoot = NULL;
     1638    if (pcszUsbRoot)
     1639    {
     1640        *pfUsingUsbfsDevices = fUsbfsChosen;
     1641        *ppcszDevicesRoot = pcszUsbRoot;
     1642        return VINF_SUCCESS;
     1643    }
     1644    /* else */
     1645    return   pcszUsbFromEnv ? VERR_NOT_FOUND
     1646           : RTDirExists("/dev/vboxusb") ? VERR_VUSB_USB_DEVICE_PERMISSION
     1647           : RTFileExists("/proc/bus/usb/devices") ? VERR_VUSB_USBFS_PERMISSION
     1648           : VERR_NOT_FOUND;
     1649}
     1650
     1651#ifdef UNIT_TEST
     1652# undef RTEnvGet
     1653# undef USBProxyLinuxCheckDeviceRoot
     1654# undef RTDirExists
     1655# undef RTFileExists
     1656#endif
     1657
    15051658bool USBProxyLinuxCheckDeviceRoot(const char *pcszRoot, bool fIsDeviceNodes)
    15061659{
  • trunk/src/VBox/Main/src-server/linux/USBProxyServiceLinux.cpp

    r37617 r37618  
    6868}
    6969
    70 #ifdef UNIT_TEST
    71 #  ifdef UNIT_TEST
    72     /** The path we pretend the usbfs root is located at, or NULL. */
    73     const char *s_pcszTestUsbfsRoot;
    74     /** Should usbfs be accessible to the current user? */
    75     bool s_fTestUsbfsAccessible;
    76     /** The path we pretend the device node tree root is located at, or NULL. */
    77     const char *s_pcszTestDevicesRoot;
    78     /** Should the device node tree be accessible to the current user? */
    79     bool s_fTestDevicesAccessible;
    80     /** The result of the usbfs/inotify-specific init */
    81     int s_rcTestMethodInitResult;
    82     /** The value of the VBOX_USB environment variable. */
    83     const char *s_pcszTestEnvUsb;
    84     /** The value of the VBOX_USB_ROOT environment variable. */
    85     const char *s_pcszTestEnvUsbRoot;
    86 #  endif
    87 
    88 /** Select which access methods will be available to the @a init method
    89  * during unit testing, and (hack!) what return code it will see from
    90  * the access method-specific initialisation. */
    91 void TestUSBSetupInit(const char *pcszUsbfsRoot, bool fUsbfsAccessible,
    92                       const char *pcszDevicesRoot, bool fDevicesAccessible,
    93                       int rcMethodInitResult)
    94 {
    95     s_pcszTestUsbfsRoot = pcszUsbfsRoot;
    96     s_fTestUsbfsAccessible = fUsbfsAccessible;
    97     s_pcszTestDevicesRoot = pcszDevicesRoot;
    98     s_fTestDevicesAccessible = fDevicesAccessible;
    99     s_rcTestMethodInitResult = rcMethodInitResult;
    100 }
    101 
    102 /** Specify the environment that the @a init method will see during unit
    103  * testing. */
    104 void TestUSBSetEnv(const char *pcszEnvUsb, const char *pcszEnvUsbRoot)
    105 {
    106     s_pcszTestEnvUsb = pcszEnvUsb;
    107     s_pcszTestEnvUsbRoot = pcszEnvUsbRoot;
    108 }
    109 
    110 /* For testing we redefine anything that accesses the outside world to
    111  * return test values. */
    112 # define RTEnvGet(a) \
    113     (  !RTStrCmp(a, "VBOX_USB") ? s_pcszTestEnvUsb \
    114      : !RTStrCmp(a, "VBOX_USB_ROOT") ? s_pcszTestEnvUsbRoot \
    115      : NULL)
    116 # define USBProxyLinuxCheckDeviceRoot(pcszPath, fUseNodes) \
    117     (   ((fUseNodes) && s_fTestDevicesAccessible \
    118                      && !RTStrCmp(pcszPath, s_pcszTestDevicesRoot)) \
    119      || (!(fUseNodes) && s_fTestUsbfsAccessible \
    120                       && !RTStrCmp(pcszPath, s_pcszTestUsbfsRoot)))
    121 # define RTDirExists(pcszDir) \
    122     (   (pcszDir) \
    123      && (   !RTStrCmp(pcszDir, s_pcszTestDevicesRoot) \
    124          || !RTStrCmp(pcszDir, s_pcszTestUsbfsRoot)))
    125 # define RTFileExists(pcszFile) \
    126     (   (pcszFile) \
    127      && s_pcszTestUsbfsRoot \
    128      && !RTStrNCmp(pcszFile, s_pcszTestUsbfsRoot, strlen(s_pcszTestUsbfsRoot)) \
    129      && !RTStrCmp(pcszFile + strlen(s_pcszTestUsbfsRoot), "/devices"))
    130 #endif
    131 
    132 /**
    133  * Selects the access method that will be used to access USB devices based on
    134  * what is available on the host and what if anything the user has specified
    135  * in the environment.
    136  * @returns iprt status value
    137  * @param  pfUsingUsbfsDevices  on success this will be set to true if
    138  *                              the prefered access method is USBFS-like and to
    139  *                              false if it is sysfs/device node-like
    140  * @param  ppcszDevicesRoot     on success the root of the tree of USBFS-like
    141  *                              device nodes will be stored here
    142  */
    143 int USBProxyLinuxChooseMethod(bool *pfUsingUsbfsDevices,
    144                               const char **ppcszDevicesRoot)
    145 {
    146     /*
    147      * We have two methods available for getting host USB device data - using
    148      * USBFS and using sysfs.  The default choice is sysfs; if that is not
    149      * available we fall back to USBFS.
    150      * In the event of both failing, an appropriate error will be returned.
    151      * The user may also specify a method and root using the VBOX_USB and
    152      * VBOX_USB_ROOT environment variables.  In this case we don't check
    153      * the root they provide for validity.
    154      */
    155     bool fUsbfsChosen = false, fSysfsChosen = false;
    156     const char *pcszUsbFromEnv = RTEnvGet("VBOX_USB");
    157     const char *pcszUsbRoot = NULL;
    158     if (pcszUsbFromEnv)
    159     {
    160         bool fValidVBoxUSB = true;
    161 
    162         pcszUsbRoot = RTEnvGet("VBOX_USB_ROOT");
    163         if (!RTStrICmp(pcszUsbFromEnv, "USBFS"))
    164         {
    165             LogRel(("Default USB access method set to \"usbfs\" from environment\n"));
    166             fUsbfsChosen = true;
    167         }
    168         else if (!RTStrICmp(pcszUsbFromEnv, "SYSFS"))
    169         {
    170             LogRel(("Default USB method set to \"sysfs\" from environment\n"));
    171             fSysfsChosen = true;
    172         }
    173         else
    174         {
    175             LogRel(("Invalid VBOX_USB environment variable setting \"%s\"\n",
    176                     pcszUsbFromEnv));
    177             fValidVBoxUSB = false;
    178             pcszUsbFromEnv = NULL;
    179         }
    180         if (!fValidVBoxUSB && pcszUsbRoot)
    181             pcszUsbRoot = NULL;
    182     }
    183     if (!pcszUsbRoot)
    184     {
    185         if (   !fUsbfsChosen
    186             && USBProxyLinuxCheckDeviceRoot("/dev/vboxusb", true))
    187         {
    188             fSysfsChosen = true;
    189             pcszUsbRoot = "/dev/vboxusb";
    190         }
    191         else if (   !fSysfsChosen
    192                  && USBProxyLinuxCheckDeviceRoot("/proc/bus/usb", false))
    193         {
    194             fUsbfsChosen = true;
    195             pcszUsbRoot = "/proc/bus/usb";
    196         }
    197     }
    198     else if (!USBProxyLinuxCheckDeviceRoot(pcszUsbRoot, fSysfsChosen))
    199         pcszUsbRoot = NULL;
    200     if (pcszUsbRoot)
    201     {
    202         *pfUsingUsbfsDevices = fUsbfsChosen;
    203         *ppcszDevicesRoot = pcszUsbRoot;
    204         return VINF_SUCCESS;
    205     }
    206     /* else */
    207     return   pcszUsbFromEnv ? VERR_NOT_FOUND
    208            : RTDirExists("/dev/vboxusb") ? VERR_VUSB_USB_DEVICE_PERMISSION
    209            : RTFileExists("/proc/bus/usb/devices") ? VERR_VUSB_USBFS_PERMISSION
    210            : VERR_NOT_FOUND;
    211 }
    212 
    21370/**
    21471 * Initializes the object (called right after construction).
     
    22380    {
    22481        mDevicesRoot = pcszDevicesRoot;
    225 #ifndef UNIT_TEST /* Hack for now */
    22682        rc = mUsingUsbfsDevices ? initUsbfs() : initSysfs();
    227 #else
    228         rc = s_rcTestMethodInitResult;
    229 #endif
    23083        /* For the day when we have VBoxSVC release logging... */
    23184        LogRel((RT_SUCCESS(rc) ? "Successfully initialised host USB using %s\n"
     
    23689    return S_OK;
    23790}
    238 
    239 #ifdef UNIT_TEST
    240 # undef RTEnvGet
    241 # undef USBProxyLinuxCheckDeviceRoot
    242 # undef RTDirExists
    243 # undef RTFileExists
    244 #endif
    24591
    24692/**
  • trunk/src/VBox/Main/testcase/tstUSBProxyLinux.cpp

    r37617 r37618  
    8989    /* "sysfs" and valid root in the environment */
    9090    { "sysfs", "/dev/bus/usb", "/dev/bus/usb", true, NULL, false, VINF_SUCCESS, "/dev/bus/usb", false, VINF_SUCCESS },
    91     /* "sysfs" and valid root in the environment, method-specific init failed */
    92     { "sysfs", "/dev/bus/usb",  "/dev/bus/usb", true, NULL, false, VERR_NO_MEMORY, "/dev/bus/usb", false, VERR_NO_MEMORY },
    9391    /* "sysfs" and bad root in the environment */
    9492    { "sysfs", "/dev/bus/usb", "/dev/vboxusb", false, "/proc/usb/bus", false, VINF_SUCCESS, "", true, VERR_NOT_FOUND },
     
    9795    /* "usbfs" and valid root in the environment */
    9896    { "usbfs", "/dev/bus/usb", NULL, false, "/dev/bus/usb", true, VINF_SUCCESS, "/dev/bus/usb", true, VINF_SUCCESS },
    99     /* "usbfs" and valid root in the environment, method-specific init failed */
    100     { "usbfs", "/dev/bus/usb", NULL, false, "/dev/bus/usb", true, VERR_NO_MEMORY, "/dev/bus/usb", true, VERR_NO_MEMORY },
    10197    /* "usbfs" and bad root in the environment */
    10298    { "usbfs", "/dev/bus/usb", "/dev/vboxusb", false, "/proc/usb/bus", false, VINF_SUCCESS, "", true, VERR_NOT_FOUND },
     
    119115    /* No environment, sysfs available but without access permissions. */
    120116    { NULL, NULL, "/dev/vboxusb", false, NULL, false, VERR_NO_MEMORY, "", true, VERR_VUSB_USB_DEVICE_PERMISSION },
    121     /* No environment, sysfs available with access permissions, method-specific init failed. */
    122     { NULL, NULL, "/dev/vboxusb", true, NULL, false, VERR_NO_MEMORY, "/dev/vboxusb", false, VERR_NO_MEMORY },
    123117    /* No environment, usbfs available but without access permissions. */
    124118    { NULL, NULL, NULL, false, "/proc/bus/usb", false, VERR_NO_MEMORY, "", true, VERR_VUSB_USBFS_PERMISSION },
    125     /* No environment, usbfs available with access permissions, method-specific
    126      * init failed. */
    127     { NULL, NULL, NULL, false, "/proc/bus/usb", true, VERR_NO_MEMORY, "/proc/bus/usb", true, VERR_NO_MEMORY }
    128119};
    129120
    130121static void testInit(RTTEST hTest)
    131122{
    132     RTTestSub(hTest, "Testing USBProxyServiceLinux initialisation");
     123    RTTestSub(hTest, "Testing USBProxyLinuxChooseMethod");
    133124    for (unsigned i = 0; i < RT_ELEMENTS(s_testEnvironment); ++i)
    134125    {
    135         USBProxyServiceLinux test(NULL);
     126        bool fUsingUsbfs = true;
     127        const char *pcszDevicesRoot = "";
     128
    136129        TestUSBSetEnv(s_testEnvironment[i].pcszEnvUsb,
    137                         s_testEnvironment[i].pcszEnvUsbRoot);
     130                      s_testEnvironment[i].pcszEnvUsbRoot);
    138131        TestUSBSetupInit(s_testEnvironment[i].pcszUsbfsRoot,
    139                            s_testEnvironment[i].fUsbfsAccessible,
    140                            s_testEnvironment[i].pcszDevicesRoot,
    141                            s_testEnvironment[i].fDevicesAccessible,
    142                            s_testEnvironment[i].rcMethodInit);
    143         HRESULT hrc = test.init();
    144         RTTESTI_CHECK_MSG(hrc == S_OK,
    145                            ("init() returned 0x%x (test index %i)!\n", hrc, i));
    146         int rc = test.getLastError();
     132                         s_testEnvironment[i].fUsbfsAccessible,
     133                         s_testEnvironment[i].pcszDevicesRoot,
     134                         s_testEnvironment[i].fDevicesAccessible,
     135                         s_testEnvironment[i].rcMethodInit);
     136        int rc = USBProxyLinuxChooseMethod(&fUsingUsbfs, &pcszDevicesRoot);
    147137        RTTESTI_CHECK_MSG(rc == s_testEnvironment[i].rcExpected,
    148                           ("getLastError() returned %Rrc (test index %i) instead of %Rrc!\n",
     138                          ("rc=%Rrc (test index %i) instead of %Rrc!\n",
    149139                           rc, i, s_testEnvironment[i].rcExpected));
    150         const char *pcszDevicesRoot = test.testGetDevicesRoot();
    151140        RTTESTI_CHECK_MSG(!RTStrCmp(pcszDevicesRoot,
    152141                               s_testEnvironment[i].pcszDevicesRootExpected),
     
    154143                           pcszDevicesRoot, i,
    155144                           s_testEnvironment[i].pcszDevicesRootExpected));
    156         bool fUsingUsbfs = test.testGetUsingUsbfs();
    157145        RTTESTI_CHECK_MSG(   fUsingUsbfs
    158146                          == s_testEnvironment[i].fUsingUsbfsExpected,
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