VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/darwin/USBProxyServiceDarwin.cpp@ 37608

Last change on this file since 37608 was 37599, checked in by vboxsync, 14 years ago

Main/USBProxyService: implementation inheritance is not so great that we have to pretend to do it when we are not

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.1 KB
Line 
1/* $Id: USBProxyServiceDarwin.cpp 37599 2011-06-22 21:06:38Z vboxsync $ */
2/** @file
3 * VirtualBox USB Proxy Service (in VBoxSVC), Darwin Specialization.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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#include "iokit.h"
25
26#include <VBox/usb.h>
27#include <VBox/usblib.h>
28#include <VBox/err.h>
29
30#include <iprt/string.h>
31#include <iprt/alloc.h>
32#include <iprt/assert.h>
33#include <iprt/file.h>
34#include <iprt/err.h>
35#include <iprt/asm.h>
36
37
38/**
39 * Initialize data members.
40 */
41USBProxyServiceDarwin::USBProxyServiceDarwin (Host *aHost)
42 : USBProxyService (aHost), mServiceRunLoopRef (NULL), mNotifyOpaque (NULL), mWaitABitNextTime (false), mUSBLibInitialized (false)
43{
44 LogFlowThisFunc(("aHost=%p\n", aHost));
45}
46
47
48/**
49 * Initializes the object (called right after construction).
50 *
51 * @returns S_OK on success and non-fatal failures, some COM error otherwise.
52 */
53HRESULT USBProxyServiceDarwin::init(void)
54{
55#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
56 /*
57 * Initialize the USB library.
58 */
59 int rc = USBLibInit();
60 if (RT_FAILURE(rc))
61 {
62 mLastError = rc;
63 return S_OK;
64 }
65 mUSBLibInitialized = true;
66#endif
67
68 /*
69 * Start the poller thread.
70 */
71 start();
72 return S_OK;
73}
74
75
76/**
77 * Stop all service threads and free the device chain.
78 */
79USBProxyServiceDarwin::~USBProxyServiceDarwin()
80{
81 LogFlowThisFunc(("\n"));
82
83 /*
84 * Stop the service.
85 */
86 if (isActive())
87 stop();
88
89#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
90 /*
91 * Terminate the USB library - it'll
92 */
93 if (mUSBLibInitialized)
94 {
95 USBLibTerm();
96 mUSBLibInitialized = false;
97 }
98#endif
99}
100
101
102#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
103void *USBProxyServiceDarwin::insertFilter (PCUSBFILTER aFilter)
104{
105 return USBLibAddFilter (aFilter);
106}
107
108
109void USBProxyServiceDarwin::removeFilter (void *aId)
110{
111 USBLibRemoveFilter (aId);
112}
113#endif /* VBOX_WITH_NEW_USB_CODE_ON_DARWIN */
114
115
116int USBProxyServiceDarwin::captureDevice(HostUSBDevice *aDevice)
117{
118 /*
119 * Check preconditions.
120 */
121 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
122 LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
123 AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
124 Assert(aDevice->getUnistate() == kHostUSBDeviceState_Capturing);
125
126#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
127 /*
128 * Fake it.
129 */
130 ASMAtomicWriteBool(&mFakeAsync, true);
131 interruptWait();
132 return VINF_SUCCESS;
133
134#else
135 /*
136 * Create a one-shot capture filter for the device (don't
137 * match on port) and trigger a re-enumeration of it.
138 */
139 USBFILTER Filter;
140 USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_CAPTURE);
141 initFilterFromDevice(&Filter, aDevice);
142
143 void *pvId = USBLibAddFilter(&Filter);
144 if (!pvId)
145 return VERR_GENERAL_FAILURE;
146
147 int rc = DarwinReEnumerateUSBDevice(aDevice->mUsb);
148 if (RT_SUCCESS(rc))
149 aDevice->mOneShotId = pvId;
150 else
151 {
152 USBLibRemoveFilter(pvId);
153 pvId = NULL;
154 }
155 LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
156 return rc;
157#endif
158}
159
160
161void USBProxyServiceDarwin::captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
162{
163#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
164 /*
165 * Remove the one-shot filter if necessary.
166 */
167 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->getName().c_str(), aSuccess, aDevice->mOneShotId));
168 if (!aSuccess && aDevice->mOneShotId)
169 USBLibRemoveFilter(aDevice->mOneShotId);
170 aDevice->mOneShotId = NULL;
171#endif
172}
173
174
175int USBProxyServiceDarwin::releaseDevice(HostUSBDevice *aDevice)
176{
177 /*
178 * Check preconditions.
179 */
180 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
181 LogFlowThisFunc(("aDevice=%s\n", aDevice->getName().c_str()));
182 AssertReturn(aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
183 Assert(aDevice->getUnistate() == kHostUSBDeviceState_ReleasingToHost);
184
185#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
186 /*
187 * Fake it.
188 */
189 ASMAtomicWriteBool(&mFakeAsync, true);
190 interruptWait();
191 return VINF_SUCCESS;
192
193#else
194 /*
195 * Create a one-shot ignore filter for the device
196 * and trigger a re-enumeration of it.
197 */
198 USBFILTER Filter;
199 USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_IGNORE);
200 initFilterFromDevice(&Filter, aDevice);
201 Log(("USBFILTERIDX_PORT=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_PORT)));
202 Log(("USBFILTERIDX_BUS=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_BUS)));
203
204 void *pvId = USBLibAddFilter(&Filter);
205 if (!pvId)
206 return VERR_GENERAL_FAILURE;
207
208 int rc = DarwinReEnumerateUSBDevice(aDevice->mUsb);
209 if (RT_SUCCESS(rc))
210 aDevice->mOneShotId = pvId;
211 else
212 {
213 USBLibRemoveFilter(pvId);
214 pvId = NULL;
215 }
216 LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
217 return rc;
218#endif
219}
220
221
222void USBProxyServiceDarwin::releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
223{
224#ifdef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
225 /*
226 * Remove the one-shot filter if necessary.
227 */
228 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->getName().c_str(), aSuccess, aDevice->mOneShotId));
229 if (!aSuccess && aDevice->mOneShotId)
230 USBLibRemoveFilter(aDevice->mOneShotId);
231 aDevice->mOneShotId = NULL;
232#endif
233}
234
235
236void USBProxyServiceDarwin::detachingDevice(HostUSBDevice *aDevice)
237{
238#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
239 aDevice->setLogicalReconnect (HostUSBDevice::kDetachingPendingDetach);
240#else
241 NOREF(aDevice);
242#endif
243}
244
245
246bool USBProxyServiceDarwin::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
247{
248#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
249 /* We're faking async state stuff. */
250 return updateDeviceStateFake(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
251#else
252 /* Nothing special here so far, so fall back on parent */
253 return USBProxyService::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
254#endif
255}
256
257
258int USBProxyServiceDarwin::wait(RTMSINTERVAL aMillies)
259{
260#ifndef VBOX_WITH_NEW_USB_CODE_ON_DARWIN
261 if ( mFakeAsync
262 && ASMAtomicXchgBool(&mFakeAsync, false))
263 return VINF_SUCCESS;
264#endif
265
266 SInt32 rc = CFRunLoopRunInMode(CFSTR (VBOX_IOKIT_MODE_STRING),
267 mWaitABitNextTime && aMillies >= 1000
268 ? 1.0 /* seconds */
269 : aMillies >= 5000 /* Temporary measure to poll for status changes (MSD). */
270 ? 5.0 /* seconds */
271 : aMillies / 1000.0,
272 true);
273 mWaitABitNextTime = rc != kCFRunLoopRunTimedOut;
274
275 return VINF_SUCCESS;
276}
277
278
279int USBProxyServiceDarwin::interruptWait (void)
280{
281 if (mServiceRunLoopRef)
282 CFRunLoopStop (mServiceRunLoopRef);
283 return 0;
284}
285
286
287PUSBDEVICE USBProxyServiceDarwin::getDevices (void)
288{
289 /* call iokit.cpp */
290 return DarwinGetUSBDevices();
291}
292
293
294void USBProxyServiceDarwin::serviceThreadInit (void)
295{
296 mServiceRunLoopRef = CFRunLoopGetCurrent();
297 mNotifyOpaque = DarwinSubscribeUSBNotifications();
298}
299
300
301void USBProxyServiceDarwin::serviceThreadTerm (void)
302{
303 DarwinUnsubscribeUSBNotifications (mNotifyOpaque);
304 mServiceRunLoopRef = NULL;
305}
306
307
308/**
309 * Wrapper called from iokit.cpp.
310 *
311 * @param pCur The USB device to free.
312 */
313void DarwinFreeUSBDeviceFromIOKit (PUSBDEVICE pCur)
314{
315 USBProxyService::freeDevice (pCur);
316}
317
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