VirtualBox

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

Last change on this file since 78273 was 76592, checked in by vboxsync, 6 years ago

Main: Don't use Logging.h.

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