USBProxyService.cpp revision 03b802818ffd2f36e2b9210243cef54f4d4aa5ac
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** @file
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * VirtualBox USB Proxy Service (base) class.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Copyright (C) 2006 InnoTek Systemberatung GmbH
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * available from http://www.virtualbox.org. This file is free software;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * you can redistribute it and/or modify it under the terms of the GNU
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * General Public License as published by the Free Software Foundation,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * If you received this file as part of a commercial VirtualBox
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * distribution, then only the terms of your commercial VirtualBox
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * license agreement apply instead of the previous paragraph.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include "USBProxyService.h"
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include "Logging.h"
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include <VBox/err.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include <iprt/asm.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync#include <iprt/semaphore.h>
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/** @todo add the required locking. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Initialize data members.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncUSBProxyService::USBProxyService (Host *aHost)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync : mHost (aHost), mThread (NIL_RTTHREAD), mTerminate (false), mDevices (), mLastError (VINF_SUCCESS)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync LogFlowMember (("USBProxyService::USBProxyService: aHost=%p\n", aHost));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Empty destructor.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncUSBProxyService::~USBProxyService()
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync LogFlowMember (("USBProxyService::~USBProxyService: \n"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync Assert (mThread == NIL_RTTHREAD);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mDevices.clear();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mTerminate = true;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mHost = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncbool USBProxyService::isActive (void)
dbec828311ed2a5cf6fbc68fe4391d516ba4f92fvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return mThread != NIL_RTTHREAD;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
5eb36887f6970e0033f63fa135f3bb8fbfd6059bvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncint USBProxyService::getLastError (void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return mLastError;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncint USBProxyService::start (void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int rc = VINF_SUCCESS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (mThread == NIL_RTTHREAD)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Force update before starting the poller thread.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync wait (0);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync processChanges ();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Create the poller thread which will look for changes.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mTerminate = false;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync rc = RTThreadCreate (&mThread, USBProxyService::serviceThread, this,
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync 0, RTTHREADTYPE_INFREQUENT_POLLER, RTTHREADFLAGS_WAITABLE, "USBPROXY");
be9960565d2df0031f0e6c8a4610f5f0ae8c1845vboxsync AssertRC (rc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (VBOX_SUCCESS (rc))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync LogFlow (("USBProxyService::start: started mThread=%RTthrd\n", mThread));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mThread = NIL_RTTHREAD;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mLastError = rc;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync LogFlow (("USBProxyService::start: already running, mThread=%RTthrd\n", mThread));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return rc;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncint USBProxyService::stop (void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int rc = VINF_SUCCESS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (mThread != NIL_RTTHREAD)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Mark the thread for termination and kick it.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ASMAtomicXchgSize (&mTerminate, true);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync rc = interruptWait();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync AssertRC (rc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Wait for the thread to finish and then update the state.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync rc = RTThreadWait (mThread, 60000, NULL);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (rc == VERR_INVALID_HANDLE)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync rc = VINF_SUCCESS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (VBOX_SUCCESS (rc))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync LogFlowMember (("USBProxyService::stop: stopped mThread=%RTthrd\n", mThread));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mThread = NIL_RTTHREAD;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mTerminate = false;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync AssertRC (rc);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mLastError = rc;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync LogFlowMember (("USBProxyService::stop: not active\n"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return rc;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Sort a list of USB devices.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync *
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @returns Pointer to the head of the sorted doubly linked list.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * @param aDevices Head pointer (can be both singly and doubly linked list).
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncstatic PUSBDEVICE sortDevices (PUSBDEVICE pDevices)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PUSBDEVICE pHead = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PUSBDEVICE pTail = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync while (pDevices)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* unlink head */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PUSBDEVICE pDev = pDevices;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDevices = pDev->pNext;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pDevices)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDevices->pPrev = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* find location. */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PUSBDEVICE pCur = pTail;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync while ( pCur
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync && HostUSBDevice::compare (pCur, pDev) > 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pCur = pCur->pPrev;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* insert (after pCur) */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDev->pPrev = pCur;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pCur)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDev->pNext = pCur->pNext;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pCur->pNext = pDev;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pDev->pNext)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDev->pNext->pPrev = pDev;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pTail = pDev;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDev->pNext = pHead;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pHead)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pHead->pPrev = pDev;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pTail = pDev;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pHead = pDev;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return pHead;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncvoid USBProxyService::processChanges (void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync LogFlowMember (("USBProxyService::processChanges: \n"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Get the sorted list of USB devices.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PUSBDEVICE pDevices = getDevices();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pDevices)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDevices = sortDevices (pDevices);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Compare previous list with the previous list of devices
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * and merge in any changes while notifying Host.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync HostUSBDeviceList::iterator It = this->mDevices.begin();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync while ( It != mDevices.end()
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync || pDevices)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Compare.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ComObjPtr <HostUSBDevice> DevPtr;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync int iDiff;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (It == mDevices.end())
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync iDiff = 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync DevPtr = *It;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!pDevices)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync iDiff = -1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync iDiff = DevPtr->compare (pDevices);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!iDiff)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Device still there, update the state and move on.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (DevPtr->updateState (pDevices))
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mHost->onUSBDeviceStateChanged (DevPtr);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync It++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PUSBDEVICE pFree = pDevices;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDevices = pDevices->pNext; /* treated as singly linked */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync freeDevice (pFree);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /** @todo detect status changes! */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (iDiff > 0)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * Head of pDevices was attached.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PUSBDEVICE pNew = pDevices;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDevices = pDevices->pNext;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pNew->pPrev = pNew->pNext = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ComObjPtr <HostUSBDevice> NewObj;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync NewObj.createObject();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync NewObj->init (pNew, this);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync Log (("USBProxyService::processChanges: attached %p/%p:{.idVendor=%#06x, .idProduct=%#06x, .pszProduct=\"%s\", .pszManufacturer=\"%s\"}\n",
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync (HostUSBDevice *)NewObj, pNew, pNew->idVendor, pNew->idProduct, pNew->pszProduct, pNew->pszManufacturer));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mDevices.insert (It, NewObj);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mHost->onUSBDeviceAttached (NewObj);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * DevPtr was detached.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync It = mDevices.erase (It);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mHost->onUSBDeviceDetached (DevPtr);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync } /* while */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync else
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* All devices were detached */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync HostUSBDeviceList::iterator It = this->mDevices.begin();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync while (It != mDevices.end())
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync ComObjPtr <HostUSBDevice> DevPtr = *It;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /*
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * DevPtr was detached.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync It = mDevices.erase (It);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync mHost->onUSBDeviceDetached (DevPtr);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
78df65edff21c11c537f38e736707ea434ab5623vboxsync
78df65edff21c11c537f38e736707ea434ab5623vboxsync LogFlowMember (("USBProxyService::processChanges: returns void\n"));
78df65edff21c11c537f38e736707ea434ab5623vboxsync}
78df65edff21c11c537f38e736707ea434ab5623vboxsync
78df65edff21c11c537f38e736707ea434ab5623vboxsync
78df65edff21c11c537f38e736707ea434ab5623vboxsync/*static*/ DECLCALLBACK (int) USBProxyService::serviceThread (RTTHREAD Thread, void *pvUser)
78df65edff21c11c537f38e736707ea434ab5623vboxsync{
78df65edff21c11c537f38e736707ea434ab5623vboxsync USBProxyService *pThis = (USBProxyService *)pvUser;
78df65edff21c11c537f38e736707ea434ab5623vboxsync LogFlow (("USBProxyService::serviceThread: pThis=%p\n", pThis));
78df65edff21c11c537f38e736707ea434ab5623vboxsync pThis->serviceThreadInit();
78df65edff21c11c537f38e736707ea434ab5623vboxsync
78df65edff21c11c537f38e736707ea434ab5623vboxsync /*
78df65edff21c11c537f38e736707ea434ab5623vboxsync * Processing loop.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync for (;;)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pThis->wait (RT_INDEFINITE_WAIT);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (pThis->mTerminate)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pThis->processChanges();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pThis->serviceThreadTerm();
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync LogFlow (("USBProxyService::serviceThread: returns VINF_SUCCESS\n"));
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VINF_SUCCESS;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/*static*/ void USBProxyService::freeDevice (PUSBDEVICE pDevice)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PUSBCONFIG pCfg = pDevice->paConfigurations;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync unsigned cCfgs = pDevice->bNumConfigurations;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync while (cCfgs-- > 0)
78df65edff21c11c537f38e736707ea434ab5623vboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync PUSBINTERFACE pIf = pCfg->paInterfaces;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync unsigned cIfs = pCfg->bNumInterfaces;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync while (cIfs-- > 0)
78df65edff21c11c537f38e736707ea434ab5623vboxsync {
78df65edff21c11c537f38e736707ea434ab5623vboxsync RTMemFree (pIf->paEndpoints);
78df65edff21c11c537f38e736707ea434ab5623vboxsync pIf->paEndpoints = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTStrFree ((char *)pIf->pszDriver);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pIf->pszDriver = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTStrFree ((char *)pIf->pszInterface);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pIf->pszInterface = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* next */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pIf++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTMemFree (pCfg->paInterfaces);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pCfg->paInterfaces = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTStrFree ((char *)pCfg->pszConfiguration);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pCfg->pszConfiguration = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync /* next */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pCfg++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTMemFree (pDevice->paConfigurations);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDevice->paConfigurations = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTStrFree ((char *)pDevice->pszManufacturer);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDevice->pszManufacturer = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTStrFree ((char *)pDevice->pszProduct);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDevice->pszProduct = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTStrFree ((char *)pDevice->pszSerialNumber);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDevice->pszSerialNumber = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTStrFree ((char *)pDevice->pszAddress);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pDevice->pszAddress = NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync RTMemFree (pDevice);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/* static */ uint64_t USBProxyService::calcSerialHash (const char *aSerial)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!aSerial)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync aSerial = "";
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync register const uint8_t *pu8 = (const uint8_t *)aSerial;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync register uint64_t u64 = 14695981039346656037ULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync for (;;)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync {
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync register uint8_t u8 = *pu8;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync if (!u8)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync break;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync u64 = (u64 * 1099511628211ULL) ^ u8;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync pu8++;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync }
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return u64;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/* Stubs which the host specific classes overrides: */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncint USBProxyService::wait (unsigned aMillies)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return RTThreadSleep (250);
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncint USBProxyService::interruptWait (void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VERR_NOT_IMPLEMENTED;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncPUSBDEVICE USBProxyService::getDevices (void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return NULL;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncvoid USBProxyService::serviceThreadInit (void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncvoid USBProxyService::serviceThreadTerm (void)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync/**
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * The default implementation returns non-NULL to emulate successful insertions
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync * for those subclasses that don't reimplement this method.
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync */
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncvoid *USBProxyService::insertFilter (IUSBDeviceFilter * /* aFilter */)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync // return non-NULL to prevent failed assertions in Main
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return (void *) 1;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncvoid USBProxyService::removeFilter (void * /* aID */)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncint USBProxyService::captureDevice (HostUSBDevice *pDevice)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VERR_NOT_IMPLEMENTED;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncint USBProxyService::holdDevice (HostUSBDevice *pDevice)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VERR_NOT_IMPLEMENTED;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncint USBProxyService::releaseDevice (HostUSBDevice *pDevice)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VERR_NOT_IMPLEMENTED;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsyncint USBProxyService::resetDevice (HostUSBDevice *pDevice)
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync{
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync return VERR_NOT_IMPLEMENTED;
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync}
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync
30a23dfc653298a09d77d3045cf873b1bd6ddecfvboxsync