VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/darwin/USBProxyBackendDarwin.cpp@ 60107

Last change on this file since 60107 was 60107, checked in by vboxsync, 9 years ago

Main/USBProxyService: Save any additional USB device sources in the global configuration and load them during startup

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.9 KB
Line 
1/* $Id: USBProxyBackendDarwin.cpp 60107 2016-03-19 10:22:46Z vboxsync $ */
2/** @file
3 * VirtualBox USB Proxy Service (in VBoxSVC), Darwin 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.215389.xyz. 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 "USBProxyBackend.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 */
41USBProxyBackendDarwin::USBProxyBackendDarwin()
42 : USBProxyBackend(), mServiceRunLoopRef(NULL), mNotifyOpaque(NULL), mWaitABitNextTime(false), mUSBLibInitialized(false)
43{
44}
45
46USBProxyBackendDarwin::~USBProxyBackendDarwin()
47{
48}
49
50/**
51 * Initializes the object (called right after construction).
52 *
53 * @returns VBox status code.
54 */
55int USBProxyBackendDarwin::init(USBProxyService *pUsbProxyService, const com::Utf8Str &strId, const com::Utf8Str &strAddress)
56{
57 USBProxyBackend::init(pUsbProxyService, strId, strAddress);
58
59 unconst(m_strBackend) = Utf8Str("host");
60
61 /*
62 * Initialize the USB library.
63 */
64 int rc = USBLibInit();
65 if (RT_FAILURE(rc))
66 return rc;
67
68 mUSBLibInitialized = true;
69
70 /*
71 * Start the poller thread.
72 */
73 start();
74 return VINF_SUCCESS;
75}
76
77
78/**
79 * Stop all service threads and free the device chain.
80 */
81void USBProxyBackendDarwin::uninit()
82{
83 LogFlowThisFunc(("\n"));
84
85 /*
86 * Stop the service.
87 */
88 if (isActive())
89 stop();
90
91 /*
92 * Terminate the USB library - it'll
93 */
94 if (mUSBLibInitialized)
95 {
96 USBLibTerm();
97 mUSBLibInitialized = false;
98 }
99
100 USBProxyBackend::uninit();
101}
102
103
104void *USBProxyBackendDarwin::insertFilter(PCUSBFILTER aFilter)
105{
106 return USBLibAddFilter(aFilter);
107}
108
109
110void USBProxyBackendDarwin::removeFilter(void *aId)
111{
112 USBLibRemoveFilter(aId);
113}
114
115
116int USBProxyBackendDarwin::captureDevice(HostUSBDevice *aDevice)
117{
118 /*
119 * Check preconditions.
120 */
121 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
122 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
123
124 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
125 LogFlowThisFunc(("aDevice=%s\n", aDevice->i_getName().c_str()));
126
127 Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_Capturing);
128
129 /*
130 * Create a one-shot capture filter for the device (don't
131 * match on port) and trigger a re-enumeration of it.
132 */
133 USBFILTER Filter;
134 USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_CAPTURE);
135 initFilterFromDevice(&Filter, aDevice);
136
137 void *pvId = USBLibAddFilter(&Filter);
138 if (!pvId)
139 return VERR_GENERAL_FAILURE;
140
141 int rc = DarwinReEnumerateUSBDevice(aDevice->i_getUsbData());
142 if (RT_SUCCESS(rc))
143 aDevice->i_setBackendUserData(pvId);
144 else
145 {
146 USBLibRemoveFilter(pvId);
147 pvId = NULL;
148 }
149 LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
150 return rc;
151}
152
153
154void USBProxyBackendDarwin::captureDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
155{
156 AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
157
158 /*
159 * Remove the one-shot filter if necessary.
160 */
161 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice->i_getBackendUserData()));
162 if (!aSuccess && aDevice->i_getBackendUserData())
163 USBLibRemoveFilter(aDevice->i_getBackendUserData());
164 aDevice->i_setBackendUserData(NULL);
165 USBProxyBackend::captureDeviceCompleted(aDevice, aSuccess);
166}
167
168
169int USBProxyBackendDarwin::releaseDevice(HostUSBDevice *aDevice)
170{
171 /*
172 * Check preconditions.
173 */
174 AssertReturn(aDevice, VERR_GENERAL_FAILURE);
175 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), VERR_GENERAL_FAILURE);
176
177 AutoReadLock devLock(aDevice COMMA_LOCKVAL_SRC_POS);
178 LogFlowThisFunc(("aDevice=%s\n", aDevice->i_getName().c_str()));
179
180 Assert(aDevice->i_getUnistate() == kHostUSBDeviceState_ReleasingToHost);
181
182 /*
183 * Create a one-shot ignore filter for the device
184 * and trigger a re-enumeration of it.
185 */
186 USBFILTER Filter;
187 USBFilterInit(&Filter, USBFILTERTYPE_ONESHOT_IGNORE);
188 initFilterFromDevice(&Filter, aDevice);
189 Log(("USBFILTERIDX_PORT=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_PORT)));
190 Log(("USBFILTERIDX_BUS=%#x\n", USBFilterGetNum(&Filter, USBFILTERIDX_BUS)));
191
192 void *pvId = USBLibAddFilter(&Filter);
193 if (!pvId)
194 return VERR_GENERAL_FAILURE;
195
196 int rc = DarwinReEnumerateUSBDevice(aDevice->i_getUsbData());
197 if (RT_SUCCESS(rc))
198 aDevice->i_setBackendUserData(pvId);
199 else
200 {
201 USBLibRemoveFilter(pvId);
202 pvId = NULL;
203 }
204 LogFlowThisFunc(("returns %Rrc pvId=%p\n", rc, pvId));
205 return rc;
206}
207
208
209void USBProxyBackendDarwin::releaseDeviceCompleted(HostUSBDevice *aDevice, bool aSuccess)
210{
211 AssertReturnVoid(aDevice->isWriteLockOnCurrentThread());
212
213 /*
214 * Remove the one-shot filter if necessary.
215 */
216 LogFlowThisFunc(("aDevice=%s aSuccess=%RTbool mOneShotId=%p\n", aDevice->i_getName().c_str(), aSuccess, aDevice->i_getBackendUserData()));
217 if (!aSuccess && aDevice->i_getBackendUserData())
218 USBLibRemoveFilter(aDevice->i_getBackendUserData());
219 aDevice->i_setBackendUserData(NULL);
220 USBProxyBackend::releaseDeviceCompleted(aDevice, aSuccess);
221}
222
223
224/** @todo unused */
225void USBProxyBackendDarwin::detachingDevice(HostUSBDevice *aDevice)
226{
227 NOREF(aDevice);
228}
229
230
231bool USBProxyBackendDarwin::updateDeviceState(HostUSBDevice *aDevice, PUSBDEVICE aUSBDevice, bool *aRunFilters, SessionMachine **aIgnoreMachine)
232{
233 AssertReturn(aDevice, false);
234 AssertReturn(!aDevice->isWriteLockOnCurrentThread(), false);
235 /* Nothing special here so far, so fall back on parent. */
236 return USBProxyBackend::updateDeviceState(aDevice, aUSBDevice, aRunFilters, aIgnoreMachine);
237}
238
239
240int USBProxyBackendDarwin::wait(RTMSINTERVAL aMillies)
241{
242 SInt32 rc = CFRunLoopRunInMode(CFSTR(VBOX_IOKIT_MODE_STRING),
243 mWaitABitNextTime && aMillies >= 1000
244 ? 1.0 /* seconds */
245 : aMillies >= 5000 /* Temporary measure to poll for status changes (MSD). */
246 ? 5.0 /* seconds */
247 : aMillies / 1000.0,
248 true);
249 mWaitABitNextTime = rc != kCFRunLoopRunTimedOut;
250
251 return VINF_SUCCESS;
252}
253
254
255int USBProxyBackendDarwin::interruptWait(void)
256{
257 if (mServiceRunLoopRef)
258 CFRunLoopStop(mServiceRunLoopRef);
259 return 0;
260}
261
262
263PUSBDEVICE USBProxyBackendDarwin::getDevices(void)
264{
265 /* call iokit.cpp */
266 return DarwinGetUSBDevices();
267}
268
269
270void USBProxyBackendDarwin::serviceThreadInit(void)
271{
272 mServiceRunLoopRef = CFRunLoopGetCurrent();
273 mNotifyOpaque = DarwinSubscribeUSBNotifications();
274}
275
276
277void USBProxyBackendDarwin::serviceThreadTerm(void)
278{
279 DarwinUnsubscribeUSBNotifications(mNotifyOpaque);
280 mServiceRunLoopRef = NULL;
281}
282
283
284/**
285 * Wrapper called from iokit.cpp.
286 *
287 * @param pCur The USB device to free.
288 */
289void DarwinFreeUSBDeviceFromIOKit(PUSBDEVICE pCur)
290{
291 USBProxyBackend::freeDevice(pCur);
292}
293
Note: See TracBrowser for help on using the repository browser.

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