HostUSBImpl.cpp revision 1ffafb5d3a2749ff247ba03d1d124c5409910c43
/** @file
*
* VBox frontends: Basic Frontend (BFE):
* Implementation of HostUSB
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* 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.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/* r=michael: I have removed almost all functionality from the Main
* version of this file, but left the structure as similar
* as I could in case we do need some of it some day. */
#include <string>
#ifdef RT_OS_LINUX
#include <unistd.h>
#include <fcntl.h>
#include <mntent.h>
/* bird: This is a hack to work around conflicts between these linux kernel headers
* and the GLIBC tcpip headers. They have different declarations of the 4
* standard byte order functions. */
#define _LINUX_BYTEORDER_GENERIC_H
#include <errno.h>
#endif /* RT_OS_LINUX */
#include "HostUSBImpl.h"
#include "HostUSBDeviceImpl.h"
#include "USBProxyService.h"
#include "Logging.h"
#include <stdio.h>
#include <algorithm>
// destructor
/////////////////////////////////////////////////////////////////////////////
{
if (isReady())
uninit();
}
// public initializer/uninitializer for internal purposes only
/////////////////////////////////////////////////////////////////////////////
/**
* Initializes the host USB object.
*
* @returns COM result indicator
* @param parent handle of our parent object
*/
{
/* Save pointer to the VM */
/*
#ifdef RT_OS_LINUX
mUSBProxyService = new USBProxyServiceLinux (this);
#elif defined RT_OS_WINDOWS
mUSBProxyService = new USBProxyServiceWin32 (this);
*/
#ifdef RT_OS_L4
mUSBProxyService = new USBProxyServiceLinux (this);
#else
mUSBProxyService = new USBProxyService (this);
#endif
/** @todo handle !mUSBProxySerivce->isActive() and mUSBProxyService->getLastError()
* and somehow report or whatever that the proxy failed to startup.
* Also, there might be init order issues... */
setReady(true);
return S_OK;
}
/**
* Uninitializes the host object and sets the ready flag to FALSE.
* Called either from FinalRelease() or by the parent when it gets destroyed.
*/
{
AssertReturn (isReady(), (void) 0);
delete mUSBProxyService;
mUSBDevices.clear();
}
// private methods
////////////////////////////////////////////////////////////////////////////////
/**
* Called by USB proxy service when a new device is physically attached
* to the host.
*
* @param aDevice Pointer to the device which has been attached.
*/
{
LogFlowMember (("HostUSB::onUSBDeviceAttached: aDevice=%p\n",
aDevice));
// add to the collecion
// apply all filters (no need to lock the device, nobody can access it yet)
AssertComRC (rc);
}
/**
* Called by USB proxy service (?) when the device is physically detached
* from the host.
*
* @param aDevice Pointer to the device which has been detached.
*/
{
LogFlowMember (("HostUSB::onUSBDeviceDetached: aDevice=%p\n",
&aDevice));
HostUSBDevice *device = 0;
{
{
break;
}
++ it;
}
AssertReturn (!!device, (void) 0);
// remove from the collecion
if (device->isCaptured())
{
// the device is captured, release it
AssertComRC (rc);
}
}
/**
* Called by USB proxy service when the state of the host-driven device
* has changed because of non proxy interaction.
*
* @param aDevice The device in question.
*/
{
LogFlowMember (("HostUSB::onUSBDeviceStateChanged: \n"));
/** @todo dmik, is there anything we should do here? For instance if the device now is available? */
}
{
/* This originally checked that the console object was ready.
* Unfortunately, this method now belongs to HostUSB, and can get
* called during construction - so before we are "ready". */
// CHECK_READY();
/*
* Don't proceed unless we've found the usb controller.
*/
if (!mpVM)
if (RT_FAILURE (vrc))
/*
* Make sure that the device is in a captureable state
*/
if (eState != USBDeviceState_Busy &&
tr ("Device is not in a capturable state"));
PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG)pBase->pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG);
/*
* Get the address and the Uuid, and call the pfnCreateProxyDevice roothub method in EMT.
*/
AssertComRC (hrc);
AssertComRC (hrc);
/* No remote devices for now */
LogFlowMember (("Console::AttachUSBDevice: Proxying USB device '%s' %RTuuid...\n", Address.c_str(), &Uuid));
if (RT_SUCCESS (vrc))
VMR3ReqFree (pReq);
if (RT_SUCCESS (vrc))
else
{
Log (("Console::AttachUSBDevice: Failed to create proxy device for '%s' %RTuuid, vrc=%Rrc\n", Address.c_str(),
/* michael: I presume this is not needed. */
/* hrc = mControl->ReleaseUSBDevice (Uuid);
AssertComRC (hrc); */
switch (vrc)
{
case VERR_VUSB_NO_PORTS:
break;
break;
default:
break;
}
return hrc;
}
return S_OK;
}
{
/* This originally checked that the console object was ready.
* Unfortunately, this method now belongs to HostUSB, and can get
* called during construction - so before we are "ready". */
// CHECK_READY();
/*
* Detach the device from the VM
*/
int vrc = VERR_PDM_DEVICE_NOT_FOUND;
if (mpVM)
{
if (RT_SUCCESS (vrc))
{
PVUSBIRHCONFIG pRhConfig = (PVUSBIRHCONFIG)pBase->pfnQueryInterface (pBase, PDMINTERFACE_VUSB_RH_CONFIG);
vrc = VMR3ReqCall (mpVM, VMCPUID_ANY, &pReq, RT_INDEFINITE_WAIT, (PFNRT)pRhConfig->pfnDestroyProxyDevice,
if (RT_SUCCESS (vrc))
VMR3ReqFree (pReq);
}
}
if ( vrc == VERR_PDM_DEVICE_NOT_FOUND
{
Log (("Console::DetachUSBDevice: USB isn't enabled.\n"));
vrc = VINF_SUCCESS;
}
if (RT_SUCCESS (vrc))
return S_OK;
Log (("Console::AttachUSBDevice: Failed to detach the device from the USB controller, vrc=%Rrc.\n", vrc));
}