HostHardwareFreeBSD.cpp revision 22197ad5dba8323699e719b622fff028e69b9d54
/* $Id$ */
/** @file
* Classes for handling hardware detection under FreeBSD.
*/
/*
* Copyright (C) 2008 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#define LOG_GROUP LOG_GROUP_MAIN
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <HostHardwareLinux.h>
#ifdef RT_OS_FREEBSD
# include <unistd.h>
# include <fcntl.h>
#endif /* RT_OS_FREEBSD */
#include <vector>
/******************************************************************************
* Typedefs and Defines *
******************************************************************************/
/** Find the length of a string, ignoring trailing non-ascii or control
* characters */
{
cch = i;
return cch + 1;
}
{
while ( (cchStr > 0)
}
/**
* Initialise the device description for a DVD drive based on
* vendor and model name strings.
* @param pcszVendor the vendor ID string
* @param pcszModel the product ID string
* @param pszDesc where to store the description string (optional)
* @param cchDesc the size of the buffer in @pszDesc
*/
/* static */
{
/* Construct the description string as "Vendor Product" */
if (pszDesc)
{
if (cchVendor > 0)
else
}
}
int VBoxMainDriveInfo::updateDVDs ()
{
LogFlowThisFunc(("entered\n"));
int rc = VINF_SUCCESS;
bool fSuccess = false; /* Have we succeeded in finding anything yet? */
try
{
/* Always allow the user to override our auto-detection using an
* environment variable. */
&fSuccess);
}
{
rc = VERR_NO_MEMORY;
}
return rc;
}
int VBoxMainDriveInfo::updateFloppies ()
{
LogFlowThisFunc(("entered\n"));
int rc = VINF_SUCCESS;
bool fSuccess = false; /* Have we succeeded in finding anything yet? */
try
{
mFloppyList.clear ();
/* Always allow the user to override our auto-detection using an
* environment variable. */
&fSuccess);
}
{
rc = VERR_NO_MEMORY;
}
return rc;
}
/**
*
* @returns iprt status code
* @param pList the list to append the drives found to
* @param pfSuccess this will be set to true if we found at least one drive
* and to false otherwise. Optional.
*/
{
int rc = VINF_SUCCESS;
if (RT_SUCCESS(rc))
{
struct dev_match_pattern DeviceMatchPattern;
/* We want to get all devices. */
/* Setup the pattern */
#if __FreeBSD_version >= 900000
#else
#endif
DeviceMatchPattern.pattern.device_pattern.INQ_PAT.media_type = SIP_MEDIA_REMOVABLE | SIP_MEDIA_FIXED;
/*
* Allocate the buffer holding the matches.
* We will allocate for 10 results and call
* CAM multiple times if we have more results.
*/
if (paMatches)
{
do
{
if (RT_FAILURE(rc))
{
break;
}
{
{
/* We have the drive now but need the appropriate device node */
struct dev_match_pattern PeriphMatchPattern;
unsigned iPeriphMatch = 0;
/* This time we only want the specific nodes for the device. */
/* Setup the pattern */
PeriphMatchPattern.pattern.periph_pattern.target_lun = paMatches[i].result.device_result.target_lun;
PeriphMatchPattern.pattern.periph_pattern.flags = PERIPH_MATCH_PATH | PERIPH_MATCH_TARGET | PERIPH_MATCH_LUN;
do
{
if (RT_FAILURE(rc))
{
break;
}
{
{
break; /* We found the periph device */
}
}
break;
if (pPeriphResult)
{
char szPath[RTPATH_MAX];
char szDesc[256];
/* Remove trailing white space. */
if (pfSuccess)
*pfSuccess = true;
}
}
}
}
else
rc = VERR_NO_MEMORY;
}
return rc;
}
/**
* Extract the names of drives from an environment variable and add them to a
* list if they are valid.
* @returns iprt status code
* @param pcszVar the name of the environment variable. The variable
* value should be a list of device node names, separated
* by ':' characters.
* @param pList the list to append the drives found to
* @param isDVD are we looking for DVD drives or for floppies?
* @param pfSuccess this will be set to true if we found at least one drive
* and to false otherwise. Optional.
*/
{
int rc = VINF_SUCCESS;
bool success = false;
try
{
const char *pcszCurrent = pszFreeMe;
{
if (pcszNext)
else
{
* initialized because of that. Need proper fixing. */
success = true;
}
}
}
{
rc = VERR_NO_MEMORY;
}
return rc;
}
#if 0
int VBoxMainUSBDeviceInfo::UpdateDevices ()
{
LogFlowThisFunc(("entered\n"));
int rc = VINF_SUCCESS;
bool success = false; /* Have we succeeded in finding anything yet? */
try
{
bool halSuccess = false;
mDeviceList.clear();
#if defined(RT_OS_LINUX)
#ifdef VBOX_WITH_DBUS
if ( RT_SUCCESS(rc)
&& RT_SUCCESS(RTDBusLoadLib())
/* Try the old API if the new one *succeeded* as only one of them will
* pick up devices anyway. */
if (!success)
#endif /* VBOX_WITH_DBUS defined */
#endif /* RT_OS_LINUX */
}
{
rc = VERR_NO_MEMORY;
}
return rc;
}
struct VBoxMainHotplugWaiter::Context
{
#if defined RT_OS_LINUX && defined VBOX_WITH_DBUS
/** The connection to DBus */
/** Semaphore which is set when a device is hotplugged and reset when
* it is read. */
volatile bool mTriggered;
/** A flag to say that we wish to interrupt the current wait. */
volatile bool mInterrupt;
/** Constructor */
#endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */
};
/* This constructor sets up a private connection to the DBus daemon, connects
* to the hal service and installs a filter which sets the mTriggered flag in
* the Context structure when a device (not necessarily USB) is added or
* removed. */
{
#if defined RT_OS_LINUX && defined VBOX_WITH_DBUS
int rc = VINF_SUCCESS;
if (RT_SUCCESS(RTDBusLoadLib()))
{
{
}
if (!mContext->mConnection)
while ( RT_SUCCESS(rc)
if ( RT_SUCCESS(rc)
rc = VERR_NO_MEMORY;
if (RT_FAILURE(rc))
}
#endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */
}
/* Destructor */
{
#if defined RT_OS_LINUX && defined VBOX_WITH_DBUS
if (!!mContext->mConnection)
(void *) &mContext->mTriggered);
delete mContext;
#endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */
}
/* Currently this is implemented using a timed out wait on our private DBus
* connection. Because the connection is private we don't have to worry about
* blocking other users. */
{
int rc = VINF_SUCCESS;
#if defined RT_OS_LINUX && defined VBOX_WITH_DBUS
if (!mContext->mConnection)
bool connected = true;
mContext->mTriggered = false;
mContext->mInterrupt = false;
unsigned cRealMillies;
if (cMillies != RT_INDEFINITE_WAIT)
else
&& !mContext->mInterrupt)
{
if (mContext->mInterrupt)
LogFlowFunc(("wait loop interrupted\n"));
if (cMillies != RT_INDEFINITE_WAIT)
mContext->mInterrupt = true;
}
if (!connected)
rc = VERR_TRY_AGAIN;
#else /* !(defined RT_OS_LINUX && defined VBOX_WITH_DBUS) */
#endif /* !(defined RT_OS_LINUX && defined VBOX_WITH_DBUS) */
return rc;
}
/* Set a flag to tell the Wait not to resume next time it times out. */
void VBoxMainHotplugWaiter::Interrupt()
{
#if defined RT_OS_LINUX && defined VBOX_WITH_DBUS
LogFlowFunc(("\n"));
mContext->mInterrupt = true;
#endif /* defined RT_OS_LINUX && defined VBOX_WITH_DBUS */
}
#endif