USBProxyService.cpp revision a275c09e02fec4e58e2579339b9e12bb02666bd3
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * VBox frontends: Basic Frontend (BFE):
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Implemenation of USBProxyService class
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Copyright (C) 2006-2007 innotek GmbH
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * This file is part of VirtualBox Open Source Edition (OSE), as
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * available from http://www.virtualbox.org. This file is free software;
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * you can redistribute it and/or modify it under the terms of the GNU
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * General Public License as published by the Free Software Foundation,
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * distribution. VirtualBox OSE is distributed in the hope that it will
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * be useful, but WITHOUT ANY WARRANTY of any kind.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan/** @todo add the required locking. */
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Initialize data members.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki RajagopalanUSBProxyService::USBProxyService (HostUSB *aHost)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan : mHost (aHost), mThread (NIL_RTTHREAD), mTerminate (false), mDevices (), mLastError (VINF_SUCCESS)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan LogFlowMember (("USBProxyService::USBProxyService: aHost=%p\n", aHost));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Empty destructor.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan LogFlowMember (("USBProxyService::~USBProxyService: \n"));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Force update before starting the poller thread.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Create the poller thread which will look for changes.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan rc = RTThreadCreate (&mThread, USBProxyService::serviceThread, this,
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan 0, RTTHREADTYPE_INFREQUENT_POLLER, RTTHREADFLAGS_WAITABLE, "USBPROXY");
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan LogFlow (("USBProxyService::start: started mThread=%RTthrd\n", mThread));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan LogFlow (("USBProxyService::start: already running, mThread=%RTthrd\n", mThread));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Mark the thread for termination and kick it.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Wait for the thread to finish and then update the state.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan LogFlowMember (("USBProxyService::stop: stopped mThread=%RTthrd\n", mThread));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan LogFlowMember (("USBProxyService::stop: not active\n"));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Sort a list of USB devices.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * @returns Pointer to the head of the sorted doubly linked list.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * @param aDevices Head pointer (can be both singly and doubly linked list).
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalanstatic PUSBDEVICE sortDevices (PUSBDEVICE pDevices)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan /* unlink head */
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan /* find location. */
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan && HostUSBDevice::compare (pCur, pDev) > 0)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan /* insert (after pCur) */
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalanvoid USBProxyService::processChanges (void)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan LogFlowMember (("USBProxyService::processChanges: \n"));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Get the sorted list of USB devices.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Compare previous list with the previous list of devices
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * and merge in any changes while notifying Host.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan HostUSBDeviceList::iterator It = this->mDevices.begin();
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan HostUSBDevice *DevPtr = 0; /* shut up gcc */
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Device still there, update the state and move on.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan pDevices = pDevices->pNext; /* treated as singly linked */
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan /** @todo detect status changes! */
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Head of pDevices was attached.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan HostUSBDevice *NewObj = new HostUSBDevice;
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan Log (("USBProxyService::processChanges: attached %p/%p:{.idVendor=%#06x, .idProduct=%#06x, .pszProduct=\"%s\", .pszManufacturer=\"%s\"}\n",
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan NewObj, pNew, pNew->idVendor, pNew->idProduct,
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan pNew->pszProduct, pNew->pszManufacturer));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * DevPtr was detached.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan /* All devices were detached */
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan HostUSBDeviceList::iterator It = this->mDevices.begin();
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * DevPtr was detached.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan Log (("USBProxyService::processChanges: detached %p\n", (HostUSBDevice *)DevPtr)); /** @todo add details .*/
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan LogFlowMember (("USBProxyService::processChanges: returns void\n"));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan/*static*/ DECLCALLBACK (int) USBProxyService::serviceThread (RTTHREAD Thread, void *pvUser)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan USBProxyService *pThis = (USBProxyService *)pvUser;
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan LogFlow (("USBProxyService::serviceThread: pThis=%p\n", pThis));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan * Processing loop.
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan LogFlow (("USBProxyService::serviceThread: returns VINF_SUCCESS\n"));
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan/*static*/ void USBProxyService::freeInterfaceMembers (PUSBINTERFACE pIf, unsigned cIfs)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan freeInterfaceMembers(pIf->paAlts, pIf->cAlts);
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan/*static*/ void USBProxyService::freeDevice (PUSBDEVICE pDevice)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan PUSBCONFIG pCfg = pDevice->paConfigurations;
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan unsigned cCfgs = pDevice->bNumConfigurations;
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan freeInterfaceMembers (pCfg->paInterfaces, pCfg->bNumInterfaces);
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan RTStrFree ((char *)pCfg->pszConfiguration);
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan RTStrFree ((char *)pDevice->pszManufacturer);
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan RTStrFree ((char *)pDevice->pszSerialNumber);
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan/* static */ uint64_t USBProxyService::calcSerialHash (const char *aSerial)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan register const uint8_t *pu8 = (const uint8_t *)aSerial;
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan register uint64_t u64 = 14695981039346656037ULL;
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalan/* Stubs which the host specific classes overrides: */
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalanint USBProxyService::wait (unsigned aMillies)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki RajagopalanPUSBDEVICE USBProxyService::getDevices (void)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalanint USBProxyService::captureDevice (HostUSBDevice *pDevice)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalanint USBProxyService::holdDevice (HostUSBDevice *pDevice)
b494511a9cf72b1fc4eb13a0e593f55c624ab829Venki Rajagopalanint USBProxyService::releaseDevice (HostUSBDevice *pDevice)