VirtualBox

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

Last change on this file since 68485 was 65854, checked in by vboxsync, 8 years ago

Main/USBProxyBackendUsbIp: Don't prevent VBoxSVC from starting when the server is not reachable, just try to reconnect every 3 seconds. Smaller other fixes for stale USB device lists when the server is not reachable and a fix for saving the same USB source multiple times

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