VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/win/USBProxyServiceWindows.cpp@ 43978

Last change on this file since 43978 was 41814, checked in by vboxsync, 13 years ago

USBProxyServiceWindows: Fixed debug assertion when releasing devices.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.0 KB
Line 
1/* $Id: USBProxyServiceWindows.cpp 41814 2012-06-18 13:15:30Z vboxsync $ */
2/** @file
3 * VirtualBox USB Proxy Service, Windows Specialization.
4 */
5
6/*
7 * Copyright (C) 2005-2012 Oracle Corporation
8 *
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.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include "USBProxyService.h"
23#include "Logging.h"
24
25#include <VBox/usb.h>
26#include <VBox/err.h>
27
28#include <iprt/string.h>
29#include <iprt/alloc.h>
30#include <iprt/assert.h>
31#include <iprt/file.h>
32#include <iprt/err.h>
33
34#include <VBox/usblib.h>
35
36
37/**
38 * Initialize data members.
39 */
40USBProxyServiceWindows::USBProxyServiceWindows(Host *aHost)
41 : USBProxyService(aHost), mhEventInterrupt(INVALID_HANDLE_VALUE)
42{
43 LogFlowThisFunc(("aHost=%p\n", aHost));
44}
45
46
47/**
48 * Initializes the object (called right after construction).
49 *
50 * @returns S_OK on success and non-fatal failures, some COM error otherwise.
51 */
52HRESULT USBProxyServiceWindows::init(void)
53{
54 /*
55 * Create the semaphore (considered fatal).
56 */
57 mhEventInterrupt = CreateEvent(NULL, FALSE, FALSE, NULL);
58 AssertReturn(mhEventInterrupt != INVALID_HANDLE_VALUE, E_FAIL);
59
60 /*
61 * Initialize the USB lib and stuff.
62 */
63 int rc = USBLibInit();
64 if (RT_SUCCESS(rc))
65 {
66 /*
67 * Start the poller thread.
68 */
69 rc = start();
70 if (RT_SUCCESS(rc))
71 {
72 LogFlowThisFunc(("returns successfully\n"));
73 return S_OK;
74 }
75
76 USBLibTerm();
77 }
78
79 CloseHandle(mhEventInterrupt);
80 mhEventInterrupt = INVALID_HANDLE_VALUE;
81
82 LogFlowThisFunc(("returns failure!!! (rc=%Rrc)\n", rc));
83 mLastError = rc;
84 return S_OK;
85}
86
87
88/**
89 * Stop all service threads and free the device chain.
90 */
91USBProxyServiceWindows::~USBProxyServiceWindows()
92{
93 LogFlowThisFunc(("\n"));
94
95 /*
96 * Stop the service.
97 */
98 if (isActive())
99 stop();
100
101 if (mhEventInterrupt != INVALID_HANDLE_VALUE)
102 CloseHandle(mhEventInterrupt);
103 mhEventInterrupt = INVALID_HANDLE_VALUE;
104
105 /*
106 * Terminate the library...
107 */
108 int rc = USBLibTerm();
109 AssertRC(rc);
110}
111
112
113void *USBProxyServiceWindows::insertFilter(PCUSBFILTER aFilter)
114{
115 AssertReturn(aFilter, NULL);
116
117 LogFlow(("USBProxyServiceWindows::insertFilter()\n"));
118
119 void *pvId = USBLibAddFilter(aFilter);
120
121 LogFlow(("USBProxyServiceWindows::insertFilter(): returning pvId=%p\n", pvId));
122
123 return pvId;
124}
125
126
127void USBProxyServiceWindows::removeFilter(void *aID)
128{
129 LogFlow(("USBProxyServiceWindows::removeFilter(): id=%p\n", aID));
130
131 AssertReturnVoid(aID);
132
133 USBLibRemoveFilter(aID);
134}
135
136
137int USBProxyServiceWindows::captureDevice(HostUSBDevice *aDevice)
138{
139 /*
140 * Check preconditions.
141 */
142 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
143 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
144
145 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
146 LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
147
148 Assert(aDevice->getUnistate() == kHostUSBDeviceState_Capturing);
149
150 /*
151 * Create a one-shot ignore filter for the device
152 * and trigger a re-enumeration of it.
153 */
154 USBFILTER Filter;
155 USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_CAPTURE);
156 initFilterFromDevice(&Filter, aDevice);
157 Log(("USBFILTERIDX_PORT=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_PORT)));
158 Log(("USBFILTERIDX_BUS=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_BUS)));
159
160 void *pvId = USBLibAddFilter(&Filter);
161 if (!pvId)
162 {
163 AssertMsgFailed(("Add one-shot Filter failed\n"));
164 return VERR_GENERAL_FAILURE;
165 }
166
167 int rc = USBLibRunFilters();
168 if (!RT_SUCCESS(rc))
169 {
170 AssertMsgFailed(("Run Filters failed\n"));
171 USBLibRemoveFilter(pvId);
172 return rc;
173 }
174
175 return VINF_SUCCESS;
176}
177
178
179int USBProxyServiceWindows::releaseDevice(HostUSBDevice *aDevice)
180{
181 /*
182 * Check preconditions.
183 */
184 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
185 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
186
187 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
188 LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
189
190 Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);
191
192 /*
193 * Create a one-shot ignore filter for the device
194 * and trigger a re-enumeration of it.
195 */
196 USBFILTER Filter;
197 USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_IGNORE);
198 initFilterFromDevice(&Filter, aDevice);
199 Log(("USBFILTERIDX_PORT=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_PORT)));
200 Log(("USBFILTERIDX_BUS=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_BUS)));
201
202 void *pvId = USBLibAddFilter(&Filter);
203 if (!pvId)
204 {
205 AssertMsgFailed(("Add one-shot Filter failed\n"));
206 return VERR_GENERAL_FAILURE;
207 }
208
209 int rc = USBLibRunFilters();
210 if (!RT_SUCCESS(rc))
211 {
212 AssertMsgFailed(("Run Filters failed\n"));
213 USBLibRemoveFilter(pvId);
214 return rc;
215 }
216
217
218 return VINF_SUCCESS;
219}
220
221
222bool USBProxyServiceWindows::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
223{
224 AssertReturn(aDevice, false);
225 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
226 /* Nothing special here so far, so fall back on parent */
227 return USBProxyService::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
228
229/// @todo remove?
230#if 0
231
232 /*
233 * We're only called in the 'existing device' state, so if there is a pending async
234 * operation we can check if it completed here and suppress state changes if it hasn't.
235 */
236 /* TESTME */
237 if (aDevice->isStatePending())
238 {
239 bool fRc = aDevice->updateState(aUSBDevice);
240 if (fRc)
241 {
242 if (aDevice->state() != aDevice->pendingState())
243 fRc = false;
244 }
245 return fRc;
246 }
247
248 /* fall back on parent. */
249 return USBProxyService::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
250#endif
251}
252
253
254int USBProxyServiceWindows::wait(unsigned aMillies)
255{
256 return USBLibWaitChange(aMillies);
257}
258
259
260int USBProxyServiceWindows::interruptWait(void)
261{
262 return USBLibInterruptWaitChange();
263}
264
265/**
266 * Gets a list of all devices the VM can grab
267 */
268PUSBDEVICE USBProxyServiceWindows::getDevices(void)
269{
270 PUSBDEVICE pDevices = NULL;
271 uint32_t cDevices = 0;
272
273 Log(("USBProxyServiceWindows::getDevices\n"));
274 USBLibGetDevices(&pDevices, &cDevices);
275 return pDevices;
276}
277
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette