USBProxyServiceSolaris.cpp revision b52c24239bed9dc9f284d829b6059073afcb1894
/* $Id$ */
/** @file
* VirtualBox USB Proxy Service, Solaris Specialization.
*/
/*
* Copyright (C) 2006-2007 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.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include "USBProxyService.h"
#include "Logging.h"
#include <iprt/semaphore.h>
#include <syslog.h>
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
typedef struct USBDEVICELIST
{
typedef USBDEVICELIST *PUSBDEVICELIST;
/**
* Initialize data members.
*/
{
}
/**
* Initializes the object (called right after construction).
*
* @returns S_OK on success and non-fatal failures, some COM error otherwise.
*/
{
/*
* Call the superclass method first.
*/
/*
* Create semaphore.
*/
if (RT_FAILURE(rc))
{
mLastError = rc;
return E_FAIL;
}
/*
* Initialize the USB library.
*/
rc = USBLibInit();
if (RT_FAILURE(rc))
{
mLastError = rc;
return S_OK;
}
mUSBLibInitialized = true;
/*
* Start the poller thread.
*/
start();
return S_OK;
}
/**
* Stop all service threads and free the device chain.
*/
{
LogFlowThisFunc(("destruct\n"));
/*
* Stop the service.
*/
if (isActive())
stop();
/*
* Terminate the USB library
*/
if (mUSBLibInitialized)
{
USBLibTerm();
mUSBLibInitialized = false;
}
}
{
return USBLibAddFilter(aFilter);
}
{
}
{
}
int USBProxyServiceSolaris::interruptWait(void)
{
return RTSemEventSignal(mNotifyEventSem);
}
{
if (RootNode != DI_NODE_NIL)
}
#if 0
{
if (!pszDevFsPath || !pszMinorName)
return DI_WALK_CONTINUE;
return DI_WALK_TERMINATE;
}
{
/* Skip "/devices" prefix if any */
char achDevicesDir[] = "/devices/";
pszDevicePath += sizeof(achDevicesDir);
/* Remove dynamic component "::" if any */
*pszTmp = '\0';
/* Remove minor name if any */
*pszTmp = '\0';
/* Walk device tree */
// di_node_t RootNode = di_init("/", DINFOCPYALL);
// if (RootNode != DI_NODE_NIL)
// {
// di_node_t MinorNode = di_lookup_node(RootNode, pszPhysical);
// if (MinorNode != DI_NODE_NIL)
{
return true;
}
// di_fini(RootNode);
// }
return false;
}
#endif
{
/*
* Check if it's a USB device in the first place.
*/
bool fUSBDevice = false;
char *pszCompatNames = NULL;
{
fUSBDevice = true;
break;
}
if (!fUSBDevice)
return DI_WALK_CONTINUE;
/*
* Check if it's a device node or interface.
*/
int rc = DI_WALK_CONTINUE;
{
/* It's a device node. */
if (!pCur)
{
return DI_WALK_TERMINATE;
}
bool fValidDevice = false;
do
{
/*
* Skip hubs
*/
if ( pszDriverName
{
break;
}
/*
* Mandatory.
* snv_85 and above have usb-dev-descriptor node properties, but older one's do not.
* So if we cannot obtain the entire device descriptor, we try falling back to the
* invidividual properties (those must not fail, if it does we drop the device).
*/
if ( cbProp > 0
&& pDevData)
{
pCur->fPartialDescriptor = false;
}
else
{
pCur->fPartialDescriptor = true;
}
if (pszPortAddr)
else
#if 0
/*
* Obtain the dev_t of the device.
*/
int DevInstance = 0;
RTStrPrintf(szAddress, sizeof(szAddress), "/dev/usb/%x.%x|%s", pCur->idVendor, pCur->idProduct, pszDevicePath);
/* @todo after binding ugen we need to append the instance number to the address. Not yet sure how we can update PUSBDEVICE at that time. */
#endif
RTStrPrintf(szBuf, sizeof(szBuf), "%#x:%#x:%d:%s", pCur->idVendor, pCur->idProduct, pCur->bcdDevice, pathBuf);
#else
RTStrPrintf(szBuf, sizeof(szBuf), "/dev/usb/%x.%x/%d|%s", pCur->idVendor, pCur->idProduct, 0, pszDevicePath);
#endif
/*
* Optional (some devices don't have all these)
*/
else
/* Determine state of the USB device. */
// fValidDevice = solarisGetApId(pCur, pszDevicePath, Node);
fValidDevice = true;
/*
* Valid device, add it to the list.
*/
if (fValidDevice)
{
else
}
} while(0);
if (!fValidDevice)
}
return rc;
}
{
/* Not possible unless a user explicitly unbinds the default driver. */
if (!pszDriverName)
return USBDEVICESTATE_UNUSED;
return USBDEVICESTATE_HELD_BY_PROXY;
#else
/* Filter out keyboards, mouse */
if (!pDevice->fPartialDescriptor)
{
/*
* Here we have a fully valid device descriptor, so we fine
* tune what's usable and what's not.
*/
{
return USBDEVICESTATE_USED_BY_HOST;
}
}
else
{
/*
* Old Nevadas don't give full device descriptor in ring-3.
* So those Nevadas we just filter out all HIDs as unusable.
*/
return USBDEVICESTATE_USED_BY_HOST;
}
return enmState;
#endif
}
{
/*
* Check preconditions.
*/
/*
* Create a one-shot capture filter for the device and reset the device.
*/
if (!pvId)
{
LogRel(("USBService: failed to add filter\n"));
return VERR_GENERAL_FAILURE;
}
if (RT_SUCCESS(rc))
else
{
}
return rc;
#else
/*
* Add the driver alias for binding the USB device to our driver.
*/
if (RT_SUCCESS(rc))
{
/*
* Reconnect and configure the device into an 'online' state because hard reset via
* usb_reset_device(9F) leaves the devices in an indeterminent state sometimes.
* In case of errors here, ignore them and prod further...
*/
if (rc)
/*
* Get device driver instance number.
*/
int iInstance;
if (RT_SUCCESS(rc))
{
/*
* Check device node to verify driver binding.
*/
/*
* Wait for the driver to export the device nodes with a timeout of ~5 seconds.
*/
unsigned cTimeout = 0;
bool fExportedNodes = false;
while (cTimeout < 5000)
{
if (RTPathExists(szDevNode))
{
fExportedNodes = true;
break;
}
RTThreadSleep(500);
cTimeout += 500;
}
if (fExportedNodes)
{
#if 0
/*
* This does not work. ProxyDevice somehow still gets the old values.
* Update our device with the node path as well as the device tree path.
*/
RTStrAPrintf(const_cast<char **>(&pDev->pszAddress), "%s|/devices%s", szDevNode, pDev->pszDevicePath);
#endif
/*
* We don't need the system alias for this device anymore now that we've captured it.
* This will also ensure that in case VirtualBox crashes at a later point with
* a captured device it will not affect the user's USB devices.
*/
return VINF_SUCCESS;
}
else
{
}
}
else
LogRel(("USBService: failed to obtain device instance number for %s rc=%Rrc\n", aDevice->getName().c_str(), rc));
}
else
LogRel(("USBService: failed to add alias for device %s devicepath=%s rc=%Rrc\n", aDevice->getName().c_str(), pDev->pszDevicePath, rc));
return VERR_OPEN_FAILED;
#endif
}
{
/*
* Remove the one-shot filter if necessary.
*/
LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->getName().c_str(), aSuccess, aDevice->mOneShotId));
#endif
}
{
/*
* Check preconditions.
*/
/*
* Create a one-shot ignore filter for the device and reset it.
*/
if (!pvId)
{
LogRel(("USBService: Adding ignore filter failed!\n"));
return VERR_GENERAL_FAILURE;
}
if (RT_SUCCESS(rc))
else
{
}
return rc;
#else
/*
* Though may not be strictly remove the driver alias for releasing the USB device
* from our driver, ignore errors here as we usually remove the alias immediately after capturing.
*/
if (RT_SUCCESS(rc))
return VINF_SUCCESS;
/* The Solaris specifics are free'd in USBProxyService::freeDeviceMembers */
LogRel(("USBService: failed to reset device %s devicepath=%s rc=%Rrc\n", aDevice->getName().c_str(), pDev->pszDevicePath, rc));
return rc;
#endif
}
{
/*
* Remove the one-shot filter if necessary.
*/
LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->getName().c_str(), aSuccess, aDevice->mOneShotId));
#endif
}
bool USBProxyServiceSolaris::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
{
#else
#endif
}
/**
* Wrapper called by walkDeviceNode.
*
* @param pDevice The USB device to free.
*/
{
}