VirtualBox

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

Last change on this file since 62890 was 62485, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
Line 
1/* $Id: USBProxyBackendDarwin.cpp 62485 2016-07-22 18:36:43Z vboxsync $ */
2/** @file
3 * VirtualBox USB Proxy Service (in VBoxSVC), Darwin Specialization.
4 */
5
6/*
7 * Copyright (C) 2005-2016 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 "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/**
225 * Returns whether devices reported by this backend go through a de/re-attach
226 * and device re-enumeration cycle when they are captured or released.
227 */
228bool USBProxyBackendDarwin::i_isDevReEnumerationRequired()
229{
230 return true;
231}
232
233
234int USBProxyBackendDarwin::wait(RTMSINTERVAL aMillies)
235{
236 SInt32 rc = CFRunLoopRunInMode(CFSTR(VBOX_IOKIT_MODE_STRING),
237 mWaitABitNextTime && aMillies >= 1000
238 ? 1.0 /* seconds */
239 : aMillies >= 5000 /* Temporary measure to poll for status changes (MSD). */
240 ? 5.0 /* seconds */
241 : aMillies / 1000.0,
242 true);
243 mWaitABitNextTime = rc != kCFRunLoopRunTimedOut;
244
245 return VINF_SUCCESS;
246}
247
248
249int USBProxyBackendDarwin::interruptWait(void)
250{
251 if (mServiceRunLoopRef)
252 CFRunLoopStop(mServiceRunLoopRef);
253 return 0;
254}
255
256
257PUSBDEVICE USBProxyBackendDarwin::getDevices(void)
258{
259 /* call iokit.cpp */
260 return DarwinGetUSBDevices();
261}
262
263
264void USBProxyBackendDarwin::serviceThreadInit(void)
265{
266 mServiceRunLoopRef = CFRunLoopGetCurrent();
267 mNotifyOpaque = DarwinSubscribeUSBNotifications();
268}
269
270
271void USBProxyBackendDarwin::serviceThreadTerm(void)
272{
273 DarwinUnsubscribeUSBNotifications(mNotifyOpaque);
274 mServiceRunLoopRef = NULL;
275}
276
277
278/**
279 * Wrapper called from iokit.cpp.
280 *
281 * @param pCur The USB device to free.
282 */
283void DarwinFreeUSBDeviceFromIOKit(PUSBDEVICE pCur)
284{
285 USBProxyBackend::freeDevice(pCur);
286}
287
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