1
/* $Id: USBProxyServiceWindows.cpp 35368 2010-12-30 13:38:23Z vboxsync $ */
3
* VirtualBox USB Proxy Service, Windows Specialization.
7
* Copyright (C) 2006-2010 Oracle Corporation
9
* This file is part of VirtualBox Open Source Edition (OSE), as
10
* available from http://www.virtualbox.org. This file is free software;
11
* you can redistribute it and/or modify it under the terms of the GNU
12
* General Public License (GPL) as published by the Free Software
13
* Foundation, in version 2 as it comes in the "COPYING" file of the
14
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
/*******************************************************************************
21
*******************************************************************************/
22
#include "USBProxyService.h"
28
#include <iprt/string.h>
29
#include <iprt/alloc.h>
30
#include <iprt/assert.h>
31
#include <iprt/file.h>
34
#include <VBox/usblib.h>
38
* Initialize data members.
40
USBProxyServiceWindows::USBProxyServiceWindows(Host *aHost)
41
: USBProxyService(aHost), mhEventInterrupt(INVALID_HANDLE_VALUE)
43
LogFlowThisFunc(("aHost=%p\n", aHost));
48
* Initializes the object (called right after construction).
50
* @returns S_OK on success and non-fatal failures, some COM error otherwise.
52
HRESULT USBProxyServiceWindows::init(void)
55
* Call the superclass method first.
57
HRESULT hrc = USBProxyService::init();
58
AssertComRCReturn(hrc, hrc);
61
* Create the semaphore (considered fatal).
63
mhEventInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
64
AssertReturn(mhEventInterrupt != INVALID_HANDLE_VALUE, E_FAIL);
67
* Initialize the USB lib and stuff.
69
int rc = USBLibInit();
73
* Start the poller thread.
78
LogFlowThisFunc(("returns successfully\n"));
85
CloseHandle(mhEventInterrupt);
86
mhEventInterrupt = INVALID_HANDLE_VALUE;
88
LogFlowThisFunc(("returns failure!!! (rc=%Rrc)\n", rc));
95
* Stop all service threads and free the device chain.
97
USBProxyServiceWindows::~USBProxyServiceWindows()
99
LogFlowThisFunc(("\n"));
107
if (mhEventInterrupt != INVALID_HANDLE_VALUE)
108
CloseHandle(mhEventInterrupt);
109
mhEventInterrupt = INVALID_HANDLE_VALUE;
112
* Terminate the library...
114
int rc = USBLibTerm();
119
void *USBProxyServiceWindows::insertFilter(PCUSBFILTER aFilter)
121
AssertReturn(aFilter, NULL);
123
LogFlow(("USBProxyServiceWindows::insertFilter()\n"));
125
void *pvId = USBLibAddFilter(aFilter);
127
LogFlow(("USBProxyServiceWindows::insertFilter(): returning pvId=%p\n", pvId));
133
void USBProxyServiceWindows::removeFilter(void *aID)
135
LogFlow(("USBProxyServiceWindows::removeFilter(): id=%p\n", aID));
137
AssertReturnVoid(aID);
139
USBLibRemoveFilter(aID);
143
int USBProxyServiceWindows::captureDevice(HostUSBDevice *aDevice)
145
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
146
AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
147
Assert(aDevice->getUnistate() == kHostUSBDeviceState_Capturing);
149
/** @todo pass up a one-shot filter like on darwin? */
150
USHORT vendorId, productId, revision;
154
rc = aDevice->COMGETTER(VendorId)(&vendorId);
155
AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
157
rc = aDevice->COMGETTER(ProductId)(&productId);
158
AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
160
rc = aDevice->COMGETTER(Revision)(&revision);
161
AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
163
return USBLibCaptureDevice(vendorId, productId, revision);
167
int USBProxyServiceWindows::releaseDevice(HostUSBDevice *aDevice)
169
AssertReturn(aDevice, VERR_GENERAL_FAILURE);
170
AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
171
Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);
173
/** @todo pass up a one-shot filter like on darwin? */
174
USHORT vendorId, productId, revision;
177
rc = aDevice->COMGETTER(VendorId)(&vendorId);
178
AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
180
rc = aDevice->COMGETTER(ProductId)(&productId);
181
AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
183
rc = aDevice->COMGETTER(Revision)(&revision);
184
AssertComRCReturn(rc, VERR_INTERNAL_ERROR);
186
Log(("USBProxyServiceWindows::releaseDevice\n"));
187
return USBLibReleaseDevice(vendorId, productId, revision);
191
bool USBProxyServiceWindows::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
193
/* Nothing special here so far, so fall back on parent */
194
return USBProxyService::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
198
AssertReturn(aDevice, false);
199
AssertReturn(aDevice->isWriteLockOnCurrentThread(), false);
202
* We're only called in the 'existing device' state, so if there is a pending async
203
* operation we can check if it completed here and suppress state changes if it hasn't.
206
if (aDevice->isStatePending())
208
bool fRc = aDevice->updateState(aUSBDevice);
211
if (aDevice->state() != aDevice->pendingState())
217
/* fall back on parent. */
218
return USBProxyService::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
223
int USBProxyServiceWindows::wait(unsigned aMillies)
227
/* Not going to do something fancy where we block in the filter
228
* driver and are woken up when the state has changed.
229
* Would be better, but this is good enough.
233
rc = WaitForSingleObject(mhEventInterrupt, RT_MIN(aMillies, 100));
234
if (rc == WAIT_OBJECT_0)
236
/** @todo handle WAIT_FAILED here */
238
if (USBLibHasPendingDeviceChanges() == true)
240
Log(("wait thread detected usb change\n"));
247
while (aMillies > 100);
253
int USBProxyServiceWindows::interruptWait(void)
255
SetEvent(mhEventInterrupt);
261
* Gets a list of all devices the VM can grab
263
PUSBDEVICE USBProxyServiceWindows::getDevices(void)
265
PUSBDEVICE pDevices = NULL;
266
uint32_t cDevices = 0;
268
Log(("USBProxyServiceWindows::getDevices\n"));
269
USBLibGetDevices(&pDevices, &cDevices);