USBProxyService.cpp revision 06642a40c2b51f038e46bb1ded79cbb35b89b4b0
/** @file
*
* VBox frontends: Basic Frontend (BFE):
* Implemenation of USBProxyService class
*/
/*
* 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.
*/
#include "USBProxyService.h"
#include "Logging.h"
#include <iprt/semaphore.h>
/** @todo add the required locking. */
/**
* Initialize data members.
*/
{
}
/**
* Empty destructor.
*/
{
LogFlowMember (("USBProxyService::~USBProxyService: \n"));
mTerminate = true;
}
bool USBProxyService::isActive (void)
{
return mThread != NIL_RTTHREAD;
}
int USBProxyService::getLastError (void)
{
return mLastError;
}
int USBProxyService::start (void)
{
int rc = VINF_SUCCESS;
if (mThread == NIL_RTTHREAD)
{
/*
* Force update before starting the poller thread.
*/
wait (0);
processChanges ();
/*
* Create the poller thread which will look for changes.
*/
mTerminate = false;
if (VBOX_SUCCESS (rc))
else
{
mLastError = rc;
}
}
else
return rc;
}
int USBProxyService::stop (void)
{
int rc = VINF_SUCCESS;
if (mThread != NIL_RTTHREAD)
{
/*
* Mark the thread for termination and kick it.
*/
ASMAtomicXchgSize (&mTerminate, true);
rc = interruptWait();
/*
* Wait for the thread to finish and then update the state.
*/
if (rc == VERR_INVALID_HANDLE)
rc = VINF_SUCCESS;
if (VBOX_SUCCESS (rc))
{
mTerminate = false;
}
else
{
mLastError = rc;
}
}
else
LogFlowMember (("USBProxyService::stop: not active\n"));
return rc;
}
/**
* Sort a list of USB devices.
*
* @returns Pointer to the head of the sorted doubly linked list.
* @param aDevices Head pointer (can be both singly and doubly linked list).
*/
{
while (pDevices)
{
/* unlink head */
if (pDevices)
/* find location. */
while ( pCur
/* insert (after pCur) */
if (pCur)
{
else
}
else
{
if (pHead)
else
}
}
return pHead;
}
void USBProxyService::processChanges (void)
{
LogFlowMember (("USBProxyService::processChanges: \n"));
/*
* Get the sorted list of USB devices.
*/
if (pDevices)
{
/*
* Compare previous list with the previous list of devices
* and merge in any changes while notifying Host.
*/
|| pDevices)
{
/*
* Compare.
*/
int iDiff;
iDiff = 1;
else
{
if (!pDevices)
iDiff = -1;
else
}
if (!iDiff)
{
/*
* Device still there, update the state and move on.
*/
It++;
freeDevice (pFree);
/** @todo detect status changes! */
}
else
{
if (iDiff > 0)
{
/*
* Head of pDevices was attached.
*/
Log (("USBProxyService::processChanges: attached %p/%p:{.idVendor=%#06x, .idProduct=%#06x, .pszProduct=\"%s\", .pszManufacturer=\"%s\"}\n",
}
else
{
/*
* DevPtr was detached.
*/
Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/
}
}
} /* while */
}
else
{
/* All devices were detached */
{
/*
* DevPtr was detached.
*/
Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/
}
}
LogFlowMember (("USBProxyService::processChanges: returns void\n"));
}
{
/*
* Processing loop.
*/
for (;;)
{
if (pThis->mTerminate)
break;
pThis->processChanges();
}
LogFlow (("USBProxyService::serviceThread: returns VINF_SUCCESS\n"));
return VINF_SUCCESS;
}
#ifdef USBDEVICE_WITH_EVERYTHING
{
while (cIfs-- > 0)
{
/* next */
pIf++;
}
}
#endif
{
#ifdef USBDEVICE_WITH_EVERYTHING
while (cCfgs-- > 0)
{
pCfg->bNumInterfaces = 0;
/* next */
pCfg++;
}
#endif
}
{
if (!aSerial)
aSerial = "";
for (;;)
{
if (!u8)
break;
pu8++;
}
return u64;
}
/* Stubs which the host specific classes overrides: */
{
return RTThreadSleep (250);
}
int USBProxyService::interruptWait (void)
{
return VERR_NOT_IMPLEMENTED;
}
{
return NULL;
}
{
return VERR_NOT_IMPLEMENTED;
}
{
return VERR_NOT_IMPLEMENTED;
}
{
return VERR_NOT_IMPLEMENTED;
}
{
return VERR_NOT_IMPLEMENTED;
}