VirtualBox

source: vbox/trunk/src/VBox/Main/USBControllerImpl.cpp@ 13538

Last change on this file since 13538 was 10535, checked in by vboxsync, 16 years ago

The OSE case (no USB) didn't compile

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 38.9 KB
RevLine 
[7964]1/* $Id: USBControllerImpl.cpp 10535 2008-07-11 15:28:06Z vboxsync $ */
[1]2/** @file
3 * Implementation of IUSBController.
4 */
5
6/*
[8155]7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
[1]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
[5999]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.
[8155]16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
[1]20 */
21
22
23
24#include "USBControllerImpl.h"
25#include "MachineImpl.h"
26#include "VirtualBoxImpl.h"
27#include "HostImpl.h"
[7964]28#ifdef VBOX_WITH_USB
29# include "USBDeviceImpl.h"
30# include "HostUSBDeviceImpl.h"
31# include "USBProxyService.h"
32#endif
[1]33#include "Logging.h"
34
35
36#include <iprt/string.h>
[3007]37#include <iprt/cpputils.h>
[1]38#include <VBox/err.h>
39
40#include <algorithm>
41
42// defines
43/////////////////////////////////////////////////////////////////////////////
44
45// constructor / destructor
46/////////////////////////////////////////////////////////////////////////////
47
[2845]48DEFINE_EMPTY_CTOR_DTOR (USBController)
49
[1]50HRESULT USBController::FinalConstruct()
51{
52 return S_OK;
53}
54
55void USBController::FinalRelease()
56{
[2845]57 uninit();
[1]58}
59
60// public initializer/uninitializer for internal purposes only
61/////////////////////////////////////////////////////////////////////////////
62
63/**
64 * Initializes the USB controller object.
65 *
66 * @returns COM result indicator.
[2845]67 * @param aParent Pointer to our parent object.
[1]68 */
[2845]69HRESULT USBController::init (Machine *aParent)
[1]70{
[2845]71 LogFlowThisFunc (("aParent=%p\n", aParent));
[1]72
[2845]73 ComAssertRet (aParent, E_INVALIDARG);
[1]74
[2845]75 /* Enclose the state transition NotReady->InInit->Ready */
76 AutoInitSpan autoInitSpan (this);
77 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
[1]78
[2845]79 unconst (mParent) = aParent;
80 /* mPeer is left null */
[1]81
[2845]82 mData.allocate();
[7964]83#ifdef VBOX_WITH_USB
[2845]84 mDeviceFilters.allocate();
[7964]85#endif
[1]86
[2845]87 /* Confirm a successful initialization */
88 autoInitSpan.setSucceeded();
89
[1]90 return S_OK;
91}
92
93
94/**
95 * Initializes the USB controller object given another USB controller object
96 * (a kind of copy constructor). This object shares data with
97 * the object passed as an argument.
98 *
99 * @returns COM result indicator.
[2845]100 * @param aParent Pointer to our parent object.
101 * @param aPeer The object to share.
[1]102 *
[2845]103 * @note This object must be destroyed before the original object
[1]104 * it shares data with is destroyed.
105 */
[2845]106HRESULT USBController::init (Machine *aParent, USBController *aPeer)
[1]107{
[2845]108 LogFlowThisFunc (("aParent=%p, aPeer=%p\n", aParent, aPeer));
[1]109
[2845]110 ComAssertRet (aParent && aPeer, E_INVALIDARG);
[1]111
[2845]112 /* Enclose the state transition NotReady->InInit->Ready */
113 AutoInitSpan autoInitSpan (this);
114 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
[1]115
[2845]116 unconst (mParent) = aParent;
117 unconst (mPeer) = aPeer;
[1]118
[8083]119 AutoWriteLock thatlock (aPeer);
[2845]120 mData.share (aPeer->mData);
[1]121
[7964]122#ifdef VBOX_WITH_USB
[2845]123 /* create copies of all filters */
124 mDeviceFilters.allocate();
125 DeviceFilterList::const_iterator it = aPeer->mDeviceFilters->begin();
126 while (it != aPeer->mDeviceFilters->end())
[1]127 {
128 ComObjPtr <USBDeviceFilter> filter;
129 filter.createObject();
130 filter->init (this, *it);
[2845]131 mDeviceFilters->push_back (filter);
[1]132 ++ it;
133 }
[7964]134#endif /* VBOX_WITH_USB */
[1]135
[2845]136 /* Confirm a successful initialization */
137 autoInitSpan.setSucceeded();
138
[1]139 return S_OK;
140}
141
142
143/**
144 * Initializes the USB controller object given another guest object
145 * (a kind of copy constructor). This object makes a private copy of data
146 * of the original object passed as an argument.
147 */
[2845]148HRESULT USBController::initCopy (Machine *aParent, USBController *aPeer)
[1]149{
[2845]150 LogFlowThisFunc (("aParent=%p, aPeer=%p\n", aParent, aPeer));
[1]151
[2845]152 ComAssertRet (aParent && aPeer, E_INVALIDARG);
[1]153
[2845]154 /* Enclose the state transition NotReady->InInit->Ready */
155 AutoInitSpan autoInitSpan (this);
156 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
[1]157
[2845]158 unconst (mParent) = aParent;
159 /* mPeer is left null */
[1]160
[8083]161 AutoWriteLock thatlock (aPeer);
[2845]162 mData.attachCopy (aPeer->mData);
[1]163
[7964]164#ifdef VBOX_WITH_USB
[2845]165 /* create private copies of all filters */
166 mDeviceFilters.allocate();
167 DeviceFilterList::const_iterator it = aPeer->mDeviceFilters->begin();
168 while (it != aPeer->mDeviceFilters->end())
[1]169 {
170 ComObjPtr <USBDeviceFilter> filter;
171 filter.createObject();
172 filter->initCopy (this, *it);
[2845]173 mDeviceFilters->push_back (filter);
[1]174 ++ it;
175 }
[7964]176#endif /* VBOX_WITH_USB */
[1]177
[2845]178 /* Confirm a successful initialization */
179 autoInitSpan.setSucceeded();
180
[1]181 return S_OK;
182}
183
184
185/**
186 * Uninitializes the instance and sets the ready flag to FALSE.
187 * Called either from FinalRelease() or by the parent when it gets destroyed.
188 */
189void USBController::uninit()
190{
[2845]191 LogFlowThisFunc (("\n"));
[1]192
[2845]193 /* Enclose the state transition Ready->InUninit->NotReady */
194 AutoUninitSpan autoUninitSpan (this);
195 if (autoUninitSpan.uninitDone())
196 return;
[1]197
[2845]198 /* uninit all filters (including those still referenced by clients) */
[1]199 uninitDependentChildren();
200
[7964]201#ifdef VBOX_WITH_USB
[2845]202 mDeviceFilters.free();
[7964]203#endif
[2845]204 mData.free();
[1]205
[2845]206 unconst (mPeer).setNull();
207 unconst (mParent).setNull();
[1]208}
209
210
211// IUSBController properties
212/////////////////////////////////////////////////////////////////////////////
213
[2845]214STDMETHODIMP USBController::COMGETTER(Enabled) (BOOL *aEnabled)
[1]215{
[2845]216 if (!aEnabled)
[1]217 return E_POINTER;
218
[2845]219 AutoCaller autoCaller (this);
220 CheckComRCReturnRC (autoCaller.rc());
[1]221
[8083]222 AutoReadLock alock (this);
[2845]223
224 *aEnabled = mData->mEnabled;
225
[1]226 return S_OK;
227}
228
229
[2845]230STDMETHODIMP USBController::COMSETTER(Enabled) (BOOL aEnabled)
[1]231{
[2845]232 LogFlowThisFunc (("aEnabled=%RTbool\n", aEnabled));
[1]233
[2845]234 AutoCaller autoCaller (this);
235 CheckComRCReturnRC (autoCaller.rc());
[1]236
[3302]237 /* the machine needs to be mutable */
238 Machine::AutoMutableStateDependency adep (mParent);
239 CheckComRCReturnRC (adep.rc());
240
[8083]241 AutoWriteLock alock (this);
[1]242
[2845]243 if (mData->mEnabled != aEnabled)
[1]244 {
[2845]245 mData.backup();
246 mData->mEnabled = aEnabled;
[1]247
[2845]248 /* leave the lock for safety */
249 alock.leave();
250
251 mParent->onUSBControllerChange();
[1]252 }
253
254 return S_OK;
255}
256
[5613]257STDMETHODIMP USBController::COMGETTER(EnabledEhci) (BOOL *aEnabled)
258{
259 if (!aEnabled)
260 return E_POINTER;
261
262 AutoCaller autoCaller (this);
263 CheckComRCReturnRC (autoCaller.rc());
264
[8083]265 AutoReadLock alock (this);
[5613]266
267 *aEnabled = mData->mEnabledEhci;
268
269 return S_OK;
270}
271
272STDMETHODIMP USBController::COMSETTER(EnabledEhci) (BOOL aEnabled)
273{
274 LogFlowThisFunc (("aEnabled=%RTbool\n", aEnabled));
275
276 AutoCaller autoCaller (this);
277 CheckComRCReturnRC (autoCaller.rc());
278
279 /* the machine needs to be mutable */
280 Machine::AutoMutableStateDependency adep (mParent);
281 CheckComRCReturnRC (adep.rc());
282
[8083]283 AutoWriteLock alock (this);
[5613]284
285 if (mData->mEnabledEhci != aEnabled)
286 {
287 mData.backup();
288 mData->mEnabledEhci = aEnabled;
289
290 /* leave the lock for safety */
291 alock.leave();
292
293 mParent->onUSBControllerChange();
294 }
295
296 return S_OK;
297}
298
[2845]299STDMETHODIMP USBController::COMGETTER(USBStandard) (USHORT *aUSBStandard)
[1]300{
[2845]301 if (!aUSBStandard)
[1]302 return E_POINTER;
303
[2845]304 AutoCaller autoCaller (this);
305 CheckComRCReturnRC (autoCaller.rc());
[1]306
[2845]307 /* not accessing data -- no need to lock */
308
[7964]309 /** @todo This is no longer correct */
[2845]310 *aUSBStandard = 0x0101;
311
[1]312 return S_OK;
313}
314
[7964]315#ifndef VBOX_WITH_USB
316/**
317 * Fake class for build without USB.
318 * We need an empty collection & enum for deviceFilters, that's all.
319 */
[10535]320class ATL_NO_VTABLE USBDeviceFilter :
321 public VirtualBoxBaseNEXT,
322 public VirtualBoxSupportErrorInfoImpl <USBDeviceFilter, IUSBDeviceFilter>,
323 public VirtualBoxSupportTranslation <USBDeviceFilter>,
324 public IUSBDeviceFilter
[7964]325{
326public:
327 DECLARE_NOT_AGGREGATABLE(USBDeviceFilter)
328 DECLARE_PROTECT_FINAL_CONSTRUCT()
329 BEGIN_COM_MAP(USBDeviceFilter)
330 COM_INTERFACE_ENTRY(ISupportErrorInfo)
331 COM_INTERFACE_ENTRY(IUSBDeviceFilter)
332 END_COM_MAP()
333
334 NS_DECL_ISUPPORTS
335
336 DECLARE_EMPTY_CTOR_DTOR (USBDeviceFilter)
337
338 // IUSBDeviceFilter properties
339 STDMETHOD(COMGETTER(Name)) (BSTR *aName);
340 STDMETHOD(COMSETTER(Name)) (INPTR BSTR aName);
341 STDMETHOD(COMGETTER(Active)) (BOOL *aActive);
342 STDMETHOD(COMSETTER(Active)) (BOOL aActive);
343 STDMETHOD(COMGETTER(VendorId)) (BSTR *aVendorId);
344 STDMETHOD(COMSETTER(VendorId)) (INPTR BSTR aVendorId);
345 STDMETHOD(COMGETTER(ProductId)) (BSTR *aProductId);
346 STDMETHOD(COMSETTER(ProductId)) (INPTR BSTR aProductId);
347 STDMETHOD(COMGETTER(Revision)) (BSTR *aRevision);
348 STDMETHOD(COMSETTER(Revision)) (INPTR BSTR aRevision);
349 STDMETHOD(COMGETTER(Manufacturer)) (BSTR *aManufacturer);
350 STDMETHOD(COMSETTER(Manufacturer)) (INPTR BSTR aManufacturer);
351 STDMETHOD(COMGETTER(Product)) (BSTR *aProduct);
352 STDMETHOD(COMSETTER(Product)) (INPTR BSTR aProduct);
353 STDMETHOD(COMGETTER(SerialNumber)) (BSTR *aSerialNumber);
354 STDMETHOD(COMSETTER(SerialNumber)) (INPTR BSTR aSerialNumber);
355 STDMETHOD(COMGETTER(Port)) (BSTR *aPort);
356 STDMETHOD(COMSETTER(Port)) (INPTR BSTR aPort);
357 STDMETHOD(COMGETTER(Remote)) (BSTR *aRemote);
358 STDMETHOD(COMSETTER(Remote)) (INPTR BSTR aRemote);
359 STDMETHOD(COMGETTER(MaskedInterfaces)) (ULONG *aMaskedIfs);
360 STDMETHOD(COMSETTER(MaskedInterfaces)) (ULONG aMaskedIfs);
361};
362COM_DECL_READONLY_ENUM_AND_COLLECTION (USBDeviceFilter);
363COM_IMPL_READONLY_ENUM_AND_COLLECTION (USBDeviceFilter);
364#endif /* !VBOX_WITH_USB */
365
366
[1]367STDMETHODIMP USBController::COMGETTER(DeviceFilters) (IUSBDeviceFilterCollection **aDevicesFilters)
368{
369 if (!aDevicesFilters)
370 return E_POINTER;
371
[2845]372 AutoCaller autoCaller (this);
373 CheckComRCReturnRC (autoCaller.rc());
[1]374
[8083]375 AutoReadLock alock (this);
[2845]376
[1]377 ComObjPtr <USBDeviceFilterCollection> collection;
378 collection.createObject();
[7964]379#ifdef VBOX_WITH_USB
[2845]380 collection->init (*mDeviceFilters.data());
[7964]381#endif
[1]382 collection.queryInterfaceTo (aDevicesFilters);
[2845]383
[1]384 return S_OK;
385}
386
387// IUSBController methods
388/////////////////////////////////////////////////////////////////////////////
389
390STDMETHODIMP USBController::CreateDeviceFilter (INPTR BSTR aName,
391 IUSBDeviceFilter **aFilter)
392{
[7964]393#ifdef VBOX_WITH_USB
[1]394 if (!aFilter)
395 return E_POINTER;
396
397 if (!aName || *aName == 0)
398 return E_INVALIDARG;
399
[2845]400 AutoCaller autoCaller (this);
401 CheckComRCReturnRC (autoCaller.rc());
[1]402
[3302]403 /* the machine needs to be mutable */
404 Machine::AutoMutableStateDependency adep (mParent);
405 CheckComRCReturnRC (adep.rc());
406
[8083]407 AutoWriteLock alock (this);
[1]408
409 ComObjPtr <USBDeviceFilter> filter;
410 filter.createObject();
411 HRESULT rc = filter->init (this, aName);
[2845]412 ComAssertComRCRetRC (rc);
[1]413 rc = filter.queryInterfaceTo (aFilter);
[2845]414 AssertComRCReturnRC (rc);
415
[1]416 return S_OK;
[7964]417#else
418 return E_NOTIMPL;
419#endif
[1]420}
421
422STDMETHODIMP USBController::InsertDeviceFilter (ULONG aPosition,
423 IUSBDeviceFilter *aFilter)
424{
[7964]425#ifdef VBOX_WITH_USB
[1]426 if (!aFilter)
427 return E_INVALIDARG;
428
[2845]429 AutoCaller autoCaller (this);
430 CheckComRCReturnRC (autoCaller.rc());
[1]431
[2805]432 /* the machine needs to be mutable */
[3302]433 Machine::AutoMutableStateDependency adep (mParent);
[2805]434 CheckComRCReturnRC (adep.rc());
[1]435
[8083]436 AutoWriteLock alock (this);
[2845]437
[1]438 ComObjPtr <USBDeviceFilter> filter = getDependentChild (aFilter);
439 if (!filter)
440 return setError (E_INVALIDARG,
441 tr ("The given USB device filter is not created within "
442 "this VirtualBox instance"));
443
444 if (filter->mInList)
445 return setError (E_INVALIDARG,
446 tr ("The given USB device filter is already in the list"));
447
[2805]448 /* backup the list before modification */
[2845]449 mDeviceFilters.backup();
[1]450
[2805]451 /* iterate to the position... */
[1]452 DeviceFilterList::iterator it;
[2845]453 if (aPosition < mDeviceFilters->size())
[1]454 {
[2845]455 it = mDeviceFilters->begin();
[1]456 std::advance (it, aPosition);
457 }
458 else
[2845]459 it = mDeviceFilters->end();
[2805]460 /* ...and insert */
[2845]461 mDeviceFilters->insert (it, filter);
[1]462 filter->mInList = true;
463
[2805]464 /// @todo After rewriting Win32 USB support, no more necessary;
465 // a candidate for removal.
466#if 0
467 /* notify the proxy (only when the filter is active) */
[1]468 if (filter->data().mActive)
[2805]469#else
470 /* notify the proxy (only when it makes sense) */
471 if (filter->data().mActive && adep.machineState() >= MachineState_Running)
472#endif
[1]473 {
[2845]474 USBProxyService *service = mParent->virtualBox()->host()->usbProxyService();
[1]475 ComAssertRet (service, E_FAIL);
476
477 ComAssertRet (filter->id() == NULL, E_FAIL);
[3758]478 filter->id() = service->insertFilter (&filter->data().mUSBFilter);
[1]479 }
480
481 return S_OK;
[7964]482#else
483 return E_NOTIMPL;
484#endif
[1]485}
486
487STDMETHODIMP USBController::RemoveDeviceFilter (ULONG aPosition,
488 IUSBDeviceFilter **aFilter)
489{
[7964]490#ifdef VBOX_WITH_USB
[1]491 if (!aFilter)
492 return E_POINTER;
493
[2845]494 AutoCaller autoCaller (this);
495 CheckComRCReturnRC (autoCaller.rc());
[1]496
[2805]497 /* the machine needs to be mutable */
[3302]498 Machine::AutoMutableStateDependency adep (mParent);
[2805]499 CheckComRCReturnRC (adep.rc());
[1]500
[8083]501 AutoWriteLock alock (this);
[2845]502
503 if (!mDeviceFilters->size())
[1]504 return setError (E_INVALIDARG,
505 tr ("The USB device filter list is empty"));
506
[2845]507 if (aPosition >= mDeviceFilters->size())
[1]508 return setError (E_INVALIDARG,
509 tr ("Invalid position: %lu (must be in range [0, %lu])"),
[2845]510 aPosition, mDeviceFilters->size() - 1);
[1]511
[2805]512 /* backup the list before modification */
[2845]513 mDeviceFilters.backup();
[1]514
515 ComObjPtr <USBDeviceFilter> filter;
516 {
[2805]517 /* iterate to the position... */
[2845]518 DeviceFilterList::iterator it = mDeviceFilters->begin();
[1]519 std::advance (it, aPosition);
[2805]520 /* ...get an element from there... */
[1]521 filter = *it;
[2805]522 /* ...and remove */
[1]523 filter->mInList = false;
[2845]524 mDeviceFilters->erase (it);
[1]525 }
526
[2805]527 /* cancel sharing (make an independent copy of data) */
[1]528 filter->unshare();
529
530 filter.queryInterfaceTo (aFilter);
531
[2805]532 /// @todo After rewriting Win32 USB support, no more necessary;
533 // a candidate for removal.
534#if 0
535 /* notify the proxy (only when the filter is active) */
[1]536 if (filter->data().mActive)
[2805]537#else
538 /* notify the proxy (only when it makes sense) */
539 if (filter->data().mActive && adep.machineState() >= MachineState_Running)
540#endif
[1]541 {
[2845]542 USBProxyService *service = mParent->virtualBox()->host()->usbProxyService();
[1]543 ComAssertRet (service, E_FAIL);
544
545 ComAssertRet (filter->id() != NULL, E_FAIL);
546 service->removeFilter (filter->id());
547 filter->id() = NULL;
548 }
549
550 return S_OK;
[7964]551#else
552 return E_NOTIMPL;
553#endif
[1]554}
555
556// public methods only for internal purposes
557/////////////////////////////////////////////////////////////////////////////
558
[7829]559/**
[6076]560 * Loads settings from the given machine node.
561 * May be called once right after this object creation.
[7829]562 *
[6076]563 * @param aMachineNode <Machine> node.
[7829]564 *
565 * @note Locks this object for writing.
[2845]566 */
[6076]567HRESULT USBController::loadSettings (const settings::Key &aMachineNode)
[1]568{
[6076]569 using namespace settings;
[1]570
[6076]571 AssertReturn (!aMachineNode.isNull(), E_FAIL);
572
[2845]573 AutoCaller autoCaller (this);
[3421]574 AssertComRCReturnRC (autoCaller.rc());
[2845]575
[8083]576 AutoWriteLock alock (this);
[2845]577
[6076]578 /* Note: we assume that the default values for attributes of optional
579 * nodes are assigned in the Data::Data() constructor and don't do it
580 * here. It implies that this method may only be called after constructing
581 * a new BIOSSettings object while all its data fields are in the default
582 * values. Exceptions are fields whose creation time defaults don't match
583 * values that should be applied when these fields are not explicitly set
584 * in the settings file (for backwards compatibility reasons). This takes
585 * place when a setting of a newly created object must default to A while
586 * the same setting of an object loaded from the old settings file must
[7829]587 * default to B. */
[1]588
[6076]589 /* USB Controller node (required) */
590 Key controller = aMachineNode.key ("USBController");
[1]591
[6076]592 /* enabled (required) */
593 mData->mEnabled = controller.value <bool> ("enabled");
[5617]594
[6076]595 /* enabledEhci (optiona, defaults to false) */
596 mData->mEnabledEhci = controller.value <bool> ("enabledEhci");
597
[7964]598#ifdef VBOX_WITH_USB
[1]599 HRESULT rc = S_OK;
600
[6076]601 Key::List children = controller.keys ("DeviceFilter");
602 for (Key::List::const_iterator it = children.begin();
603 it != children.end(); ++ it)
[1]604 {
[6076]605 /* required */
606 Bstr name = (*it).stringValue ("name");
607 bool active = (*it).value <bool> ("active");
[1]608
[6076]609 /* optional */
[7466]610 Bstr vendorId = (*it).stringValue ("vendorId");
611 Bstr productId = (*it).stringValue ("productId");
[6076]612 Bstr revision = (*it).stringValue ("revision");
613 Bstr manufacturer = (*it).stringValue ("manufacturer");
614 Bstr product = (*it).stringValue ("product");
[7466]615 Bstr serialNumber = (*it).stringValue ("serialNumber");
[6076]616 Bstr port = (*it).stringValue ("port");
617 Bstr remote = (*it).stringValue ("remote");
618 ULONG maskedIfs = (*it).value <ULONG> ("maskedInterfaces");
[1]619
620 ComObjPtr <USBDeviceFilter> filterObj;
621 filterObj.createObject();
622 rc = filterObj->init (this,
623 name, active, vendorId, productId, revision,
624 manufacturer, product, serialNumber,
[5713]625 port, remote, maskedIfs);
[2845]626 /* error info is set by init() when appropriate */
[6076]627 CheckComRCReturnRC (rc);
[1]628
[6076]629 mDeviceFilters->push_back (filterObj);
630 filterObj->mInList = true;
[1]631 }
[7964]632#endif /* VBOX_WITH_USB */
[1]633
[6076]634 return S_OK;
[1]635}
636
[7829]637/**
[6076]638 * Saves settings to the given machine node.
[7829]639 *
[6076]640 * @param aMachineNode <Machine> node.
[7829]641 *
[6076]642 * @note Locks this object for reading.
[2845]643 */
[6076]644HRESULT USBController::saveSettings (settings::Key &aMachineNode)
[1]645{
[6076]646 using namespace settings;
[1]647
[6076]648 AssertReturn (!aMachineNode.isNull(), E_FAIL);
649
[2845]650 AutoCaller autoCaller (this);
651 CheckComRCReturnRC (autoCaller.rc());
652
[8083]653 AutoReadLock alock (this);
[2845]654
655 /* first, delete the entry */
[6076]656 Key controller = aMachineNode.findKey ("USBController");
[7964]657#ifdef VBOX_WITH_USB
[6076]658 if (!controller.isNull())
659 controller.zap();
[2845]660 /* then, recreate it */
[6076]661 controller = aMachineNode.createKey ("USBController");
[7964]662#else
663 /* don't zap it. */
[7968]664 if (controller.isNull())
[7964]665 controller = aMachineNode.createKey ("USBController");
666#endif
[1]667
[2845]668 /* enabled */
[6076]669 controller.setValue <bool> ("enabled", !!mData->mEnabled);
[1]670
[5617]671 /* enabledEhci */
[6076]672 controller.setValue <bool> ("enabledEhci", !!mData->mEnabledEhci);
[5617]673
[7964]674#ifdef VBOX_WITH_USB
[2845]675 DeviceFilterList::const_iterator it = mDeviceFilters->begin();
676 while (it != mDeviceFilters->end())
[1]677 {
[8083]678 AutoWriteLock filterLock (*it);
[1]679 const USBDeviceFilter::Data &data = (*it)->data();
680
[6076]681 Key filter = controller.appendKey ("DeviceFilter");
[1]682
[6076]683 filter.setValue <Bstr> ("name", data.mName);
684 filter.setValue <bool> ("active", !!data.mActive);
[1]685
[2845]686 /* all are optional */
[3756]687 Bstr str;
688 (*it)->COMGETTER (VendorId) (str.asOutParam());
689 if (!str.isNull())
[7466]690 filter.setValue <Bstr> ("vendorId", str);
[3756]691
692 (*it)->COMGETTER (ProductId) (str.asOutParam());
693 if (!str.isNull())
[7466]694 filter.setValue <Bstr> ("productId", str);
[3756]695
696 (*it)->COMGETTER (Revision) (str.asOutParam());
697 if (!str.isNull())
[6076]698 filter.setValue <Bstr> ("revision", str);
[3756]699
700 (*it)->COMGETTER (Manufacturer) (str.asOutParam());
701 if (!str.isNull())
[6076]702 filter.setValue <Bstr> ("manufacturer", str);
[3756]703
704 (*it)->COMGETTER (Product) (str.asOutParam());
705 if (!str.isNull())
[6076]706 filter.setValue <Bstr> ("product", str);
[3756]707
708 (*it)->COMGETTER (SerialNumber) (str.asOutParam());
709 if (!str.isNull())
[7466]710 filter.setValue <Bstr> ("serialNumber", str);
[3756]711
712 (*it)->COMGETTER (Port) (str.asOutParam());
713 if (!str.isNull())
[6076]714 filter.setValue <Bstr> ("port", str);
[3756]715
716 if (data.mRemote.string())
[6076]717 filter.setValue <Bstr> ("remote", data.mRemote.string());
718
[5713]719 if (data.mMaskedIfs)
[6076]720 filter.setValue <ULONG> ("maskedInterfaces", data.mMaskedIfs);
[5713]721
[1]722 ++ it;
723 }
[7964]724#endif /* VBOX_WITH_USB */
[1]725
726 return S_OK;
727}
728
[2845]729/** @note Locks objects for reading! */
[1]730bool USBController::isModified()
731{
[2845]732 AutoCaller autoCaller (this);
733 AssertComRCReturn (autoCaller.rc(), false);
[1]734
[8083]735 AutoReadLock alock (this);
[2845]736
[7964]737 if (mData.isBackedUp()
738#ifdef VBOX_WITH_USB
739 || mDeviceFilters.isBackedUp()
740#endif
741 )
[1]742 return true;
743
[7964]744#ifdef VBOX_WITH_USB
[1]745 /* see whether any of filters has changed its data */
746 for (DeviceFilterList::const_iterator
[2845]747 it = mDeviceFilters->begin();
748 it != mDeviceFilters->end();
[1]749 ++ it)
750 {
751 if ((*it)->isModified())
752 return true;
753 }
[7964]754#endif /* VBOX_WITH_USB */
[1]755
756 return false;
757}
758
[2845]759/** @note Locks objects for reading! */
[1]760bool USBController::isReallyModified()
761{
[2845]762 AutoCaller autoCaller (this);
763 AssertComRCReturn (autoCaller.rc(), false);
[1]764
[8083]765 AutoReadLock alock (this);
[2845]766
767 if (mData.hasActualChanges())
[1]768 return true;
769
[7964]770#ifdef VBOX_WITH_USB
[2845]771 if (!mDeviceFilters.isBackedUp())
[1]772 {
773 /* see whether any of filters has changed its data */
774 for (DeviceFilterList::const_iterator
[2845]775 it = mDeviceFilters->begin();
776 it != mDeviceFilters->end();
[1]777 ++ it)
778 {
779 if ((*it)->isReallyModified())
780 return true;
781 }
782
783 return false;
784 }
785
[2845]786 if (mDeviceFilters->size() != mDeviceFilters.backedUpData()->size())
[1]787 return true;
788
[2845]789 if (mDeviceFilters->size() == 0)
[1]790 return false;
791
792 /* Make copies to speed up comparison */
[2845]793 DeviceFilterList devices = *mDeviceFilters.data();
794 DeviceFilterList backDevices = *mDeviceFilters.backedUpData();
[1]795
796 DeviceFilterList::iterator it = devices.begin();
797 while (it != devices.end())
798 {
799 bool found = false;
800 DeviceFilterList::iterator thatIt = backDevices.begin();
801 while (thatIt != backDevices.end())
802 {
803 if ((*it)->data() == (*thatIt)->data())
804 {
805 backDevices.erase (thatIt);
806 found = true;
807 break;
808 }
809 else
810 ++ thatIt;
811 }
812 if (found)
813 it = devices.erase (it);
814 else
815 return false;
816 }
817
818 Assert (devices.size() == 0 && backDevices.size() == 0);
[7964]819#endif /* VBOX_WITH_USB */
[1]820
821 return false;
822}
823
[2845]824/** @note Locks objects for writing! */
[1]825bool USBController::rollback()
826{
[2845]827 AutoCaller autoCaller (this);
828 AssertComRCReturn (autoCaller.rc(), false);
[1]829
[2805]830 /* we need the machine state */
[3421]831 Machine::AutoAnyStateDependency adep (mParent);
[2805]832 AssertComRCReturn (adep.rc(), false);
833
[8083]834 AutoWriteLock alock (this);
[2845]835
[1]836 bool dataChanged = false;
837
[2845]838 if (mData.isBackedUp())
[1]839 {
[2805]840 /* we need to check all data to see whether anything will be changed
841 * after rollback */
[2845]842 dataChanged = mData.hasActualChanges();
843 mData.rollback();
[1]844 }
845
[7964]846#ifdef VBOX_WITH_USB
[2845]847 if (mDeviceFilters.isBackedUp())
[1]848 {
[2845]849 USBProxyService *service = mParent->virtualBox()->host()->usbProxyService();
[1]850 ComAssertRet (service, false);
851
[2805]852 /* uninitialize all new filters (absent in the backed up list) */
[2845]853 DeviceFilterList::const_iterator it = mDeviceFilters->begin();
854 DeviceFilterList *backedList = mDeviceFilters.backedUpData();
855 while (it != mDeviceFilters->end())
[1]856 {
857 if (std::find (backedList->begin(), backedList->end(), *it) ==
858 backedList->end())
859 {
[2805]860 /// @todo After rewriting Win32 USB support, no more necessary;
861 // a candidate for removal.
862#if 0
863 /* notify the proxy (only when the filter is active) */
[1]864 if ((*it)->data().mActive)
[2805]865#else
866 /* notify the proxy (only when it makes sense) */
867 if ((*it)->data().mActive &&
868 adep.machineState() >= MachineState_Running)
869#endif
[1]870 {
871 USBDeviceFilter *filter = *it;
872 ComAssertRet (filter->id() != NULL, false);
873 service->removeFilter (filter->id());
874 filter->id() = NULL;
875 }
876
877 (*it)->uninit();
878 }
879 ++ it;
880 }
881
[2805]882 /// @todo After rewriting Win32 USB support, no more necessary;
883 // a candidate for removal.
884#if 0
885#else
886 if (adep.machineState() >= MachineState_Running)
887#endif
[1]888 {
[2805]889 /* find all removed old filters (absent in the new list)
890 * and insert them back to the USB proxy */
891 it = backedList->begin();
892 while (it != backedList->end())
[1]893 {
[2845]894 if (std::find (mDeviceFilters->begin(), mDeviceFilters->end(), *it) ==
895 mDeviceFilters->end())
[1]896 {
[2805]897 /* notify the proxy (only when necessary) */
898 if ((*it)->data().mActive)
899 {
900 USBDeviceFilter *flt = *it; /* resolve ambiguity */
901 ComAssertRet (flt->id() == NULL, false);
[3758]902 flt->id() = service->insertFilter (&flt->data().mUSBFilter);
[2805]903 }
[1]904 }
[2805]905 ++ it;
[1]906 }
907 }
908
[2805]909 /* restore the list */
[2845]910 mDeviceFilters.rollback();
[1]911 }
912
[2805]913 /* here we don't depend on the machine state any more */
914 adep.release();
915
916 /* rollback any changes to filters after restoring the list */
[2845]917 DeviceFilterList::const_iterator it = mDeviceFilters->begin();
918 while (it != mDeviceFilters->end())
[1]919 {
920 if ((*it)->isModified())
921 {
922 (*it)->rollback();
[2805]923 /* call this to notify the USB proxy about changes */
[1]924 onDeviceFilterChange (*it);
925 }
926 ++ it;
927 }
[7964]928#endif /* VBOX_WITH_USB */
[1]929
930 return dataChanged;
931}
932
[7992]933/**
934 * @note Locks this object for writing, together with the peer object (also
935 * for writing) if there is one.
936 */
[1]937void USBController::commit()
938{
[7992]939 /* sanity */
[2845]940 AutoCaller autoCaller (this);
941 AssertComRCReturnVoid (autoCaller.rc());
942
[7992]943 /* sanity too */
944 AutoCaller peerCaller (mPeer);
945 AssertComRCReturnVoid (peerCaller.rc());
[1]946
[7992]947 /* lock both for writing since we modify both (mPeer is "master" so locked
948 * first) */
949 AutoMultiWriteLock2 alock (mPeer, this);
950
[2845]951 if (mData.isBackedUp())
[1]952 {
[2845]953 mData.commit();
954 if (mPeer)
[1]955 {
[7992]956 /* attach new data to the peer and reshare it */
[8083]957 AutoWriteLock peerlock (mPeer);
[2845]958 mPeer->mData.attach (mData);
[1]959 }
960 }
961
[7964]962#ifdef VBOX_WITH_USB
[1]963 bool commitFilters = false;
964
[2845]965 if (mDeviceFilters.isBackedUp())
[1]966 {
[2845]967 mDeviceFilters.commit();
[1]968
[7992]969 /* apply changes to peer */
[2845]970 if (mPeer)
[1]971 {
[8083]972 AutoWriteLock peerlock (mPeer);
[7992]973 /* commit all changes to new filters (this will reshare data with
974 * peers for those who have peers) */
[1]975 DeviceFilterList *newList = new DeviceFilterList();
[2845]976 DeviceFilterList::const_iterator it = mDeviceFilters->begin();
977 while (it != mDeviceFilters->end())
[1]978 {
979 (*it)->commit();
980
[7992]981 /* look if this filter has a peer filter */
[1]982 ComObjPtr <USBDeviceFilter> peer = (*it)->peer();
983 if (!peer)
984 {
[7992]985 /* no peer means the filter is a newly created one;
986 * create a peer owning data this filter share it with */
[1]987 peer.createObject();
[2845]988 peer->init (mPeer, *it, true /* aReshare */);
[1]989 }
990 else
991 {
[7992]992 /* remove peer from the old list */
[2845]993 mPeer->mDeviceFilters->remove (peer);
[1]994 }
[7992]995 /* and add it to the new list */
[1]996 newList->push_back (peer);
997
998 ++ it;
999 }
1000
[7992]1001 /* uninit old peer's filters that are left */
[2845]1002 it = mPeer->mDeviceFilters->begin();
1003 while (it != mPeer->mDeviceFilters->end())
[1]1004 {
1005 (*it)->uninit();
1006 ++ it;
1007 }
1008
[7992]1009 /* attach new list of filters to our peer */
[2845]1010 mPeer->mDeviceFilters.attach (newList);
[1]1011 }
1012 else
1013 {
[7992]1014 /* we have no peer (our parent is the newly created machine);
1015 * just commit changes to filters */
[1]1016 commitFilters = true;
1017 }
1018 }
1019 else
1020 {
[7992]1021 /* the list of filters itself is not changed,
1022 * just commit changes to filters themselves */
[1]1023 commitFilters = true;
1024 }
1025
1026 if (commitFilters)
1027 {
[2845]1028 DeviceFilterList::const_iterator it = mDeviceFilters->begin();
1029 while (it != mDeviceFilters->end())
[1]1030 {
1031 (*it)->commit();
1032 ++ it;
1033 }
1034 }
[7964]1035#endif /* VBOX_WITH_USB */
[1]1036}
1037
[7992]1038/**
1039 * @note Locks this object for writing, together with the peer object
1040 * represented by @a aThat (locked for reading).
1041 */
[1]1042void USBController::copyFrom (USBController *aThat)
1043{
[7992]1044 AssertReturnVoid (aThat != NULL);
1045
1046 /* sanity */
[2845]1047 AutoCaller autoCaller (this);
1048 AssertComRCReturnVoid (autoCaller.rc());
[1]1049
[7992]1050 /* sanity too */
1051 AutoCaller thatCaller (aThat);
1052 AssertComRCReturnVoid (thatCaller.rc());
[2845]1053
[7992]1054 /* peer is not modified, lock it for reading (aThat is "master" so locked
1055 * first) */
1056 AutoMultiLock2 alock (aThat->rlock(), this->wlock());
1057
[2845]1058 if (mParent->isRegistered())
[1]1059 {
[2845]1060 /* reuse onMachineRegistered to tell USB proxy to remove all current
1061 filters */
[1]1062 HRESULT rc = onMachineRegistered (FALSE);
1063 AssertComRCReturn (rc, (void) 0);
1064 }
1065
[2845]1066 /* this will back up current data */
1067 mData.assignCopy (aThat->mData);
[1]1068
[7964]1069#ifdef VBOX_WITH_USB
[2845]1070 /* create private copies of all filters */
1071 mDeviceFilters.backup();
1072 mDeviceFilters->clear();
1073 for (DeviceFilterList::const_iterator it = aThat->mDeviceFilters->begin();
1074 it != aThat->mDeviceFilters->end();
[1]1075 ++ it)
1076 {
1077 ComObjPtr <USBDeviceFilter> filter;
1078 filter.createObject();
1079 filter->initCopy (this, *it);
[2845]1080 mDeviceFilters->push_back (filter);
[1]1081 }
[7964]1082#endif /* VBOX_WITH_USB */
[1]1083
[2845]1084 if (mParent->isRegistered())
[1]1085 {
[2845]1086 /* reuse onMachineRegistered to tell USB proxy to insert all current
1087 filters */
[1]1088 HRESULT rc = onMachineRegistered (TRUE);
1089 AssertComRCReturn (rc, (void) 0);
1090 }
1091}
1092
1093/**
1094 * Called by VirtualBox when it changes the registered state
1095 * of the machine this USB controller belongs to.
1096 *
1097 * @param aRegistered new registered state of the machine
[2845]1098 *
1099 * @note Locks nothing.
[1]1100 */
1101HRESULT USBController::onMachineRegistered (BOOL aRegistered)
1102{
[2845]1103 AutoCaller autoCaller (this);
1104 AssertComRCReturnRC (autoCaller.rc());
[1]1105
[2805]1106 /// @todo After rewriting Win32 USB support, no more necessary;
1107 // a candidate for removal.
1108#if 0
1109 notifyProxy (!!aRegistered);
1110#endif
[1]1111
1112 return S_OK;
1113}
1114
[7964]1115#ifdef VBOX_WITH_USB
1116
[1]1117/**
1118 * Called by setter methods of all USB device filters.
[2845]1119 *
1120 * @note Locks nothing.
[1]1121 */
1122HRESULT USBController::onDeviceFilterChange (USBDeviceFilter *aFilter,
1123 BOOL aActiveChanged /* = FALSE */)
1124{
[2845]1125 AutoCaller autoCaller (this);
1126 AssertComRCReturnRC (autoCaller.rc());
[1]1127
[2805]1128 /// @todo After rewriting Win32 USB support, no more necessary;
1129 // a candidate for removal.
1130#if 0
1131#else
1132 /* we need the machine state */
[3421]1133 Machine::AutoAnyStateDependency adep (mParent);
[2805]1134 AssertComRCReturnRC (adep.rc());
1135
1136 /* nothing to do if the machine isn't running */
1137 if (adep.machineState() < MachineState_Running)
1138 return S_OK;
1139#endif
1140
[2845]1141 /* we don't modify our data fields -- no need to lock */
1142
1143 if (aFilter->mInList && mParent->isRegistered())
[1]1144 {
[2845]1145 USBProxyService *service = mParent->virtualBox()->host()->usbProxyService();
[1]1146 ComAssertRet (service, E_FAIL);
1147
1148 if (aActiveChanged)
1149 {
[2805]1150 /* insert/remove the filter from the proxy */
[1]1151 if (aFilter->data().mActive)
1152 {
1153 ComAssertRet (aFilter->id() == NULL, E_FAIL);
[3758]1154 aFilter->id() = service->insertFilter (&aFilter->data().mUSBFilter);
[1]1155 }
1156 else
1157 {
1158 ComAssertRet (aFilter->id() != NULL, E_FAIL);
1159 service->removeFilter (aFilter->id());
1160 aFilter->id() = NULL;
1161 }
1162 }
1163 else
1164 {
1165 if (aFilter->data().mActive)
1166 {
[2805]1167 /* update the filter in the proxy */
[1]1168 ComAssertRet (aFilter->id() != NULL, E_FAIL);
1169 service->removeFilter (aFilter->id());
[3758]1170 aFilter->id() = service->insertFilter (&aFilter->data().mUSBFilter);
[1]1171 }
1172 }
1173 }
1174
1175 return S_OK;
1176}
1177
1178/**
1179 * Returns true if the given USB device matches to at least one of
1180 * this controller's USB device filters.
1181 *
1182 * A HostUSBDevice specific version.
[2845]1183 *
1184 * @note Locks this object for reading.
[1]1185 */
[5713]1186bool USBController::hasMatchingFilter (const ComObjPtr <HostUSBDevice> &aDevice, ULONG *aMaskedIfs)
[1]1187{
[2845]1188 AutoCaller autoCaller (this);
1189 AssertComRCReturn (autoCaller.rc(), false);
[1]1190
[8083]1191 AutoReadLock alock (this);
[2845]1192
[3001]1193 /* Disabled USB controllers cannot actually work with USB devices */
1194 if (!mData->mEnabled)
1195 return false;
1196
[2845]1197 /* apply self filters */
1198 for (DeviceFilterList::const_iterator it = mDeviceFilters->begin();
[5713]1199 it != mDeviceFilters->end();
[1]1200 ++ it)
1201 {
[8083]1202 AutoWriteLock filterLock (*it);
[5713]1203 if (aDevice->isMatch ((*it)->data()))
1204 {
1205 *aMaskedIfs = (*it)->data().mMaskedIfs;
1206 return true;
1207 }
[1]1208 }
1209
[5713]1210 return false;
[1]1211}
1212
1213/**
1214 * Returns true if the given USB device matches to at least one of
1215 * this controller's USB device filters.
1216 *
1217 * A generic version that accepts any IUSBDevice on input.
1218 *
1219 * @note
1220 * This method MUST correlate with HostUSBDevice::isMatch()
1221 * in the sense of the device matching logic.
[2845]1222 *
1223 * @note Locks this object for reading.
[1]1224 */
[5713]1225bool USBController::hasMatchingFilter (IUSBDevice *aUSBDevice, ULONG *aMaskedIfs)
[1]1226{
[2845]1227 LogFlowThisFuncEnter();
[1]1228
[2845]1229 AutoCaller autoCaller (this);
1230 AssertComRCReturn (autoCaller.rc(), false);
[1]1231
[8083]1232 AutoReadLock alock (this);
[2845]1233
[3001]1234 /* Disabled USB controllers cannot actually work with USB devices */
1235 if (!mData->mEnabled)
1236 return false;
1237
[1]1238 HRESULT rc = S_OK;
1239
[2845]1240 /* query fields */
[3756]1241 USBFILTER dev;
1242 USBFilterInit (&dev, USBFILTERTYPE_CAPTURE);
[1]1243
1244 USHORT vendorId = 0;
1245 rc = aUSBDevice->COMGETTER(VendorId) (&vendorId);
1246 ComAssertComRCRet (rc, false);
1247 ComAssertRet (vendorId, false);
[3756]1248 int vrc = USBFilterSetNumExact (&dev, USBFILTERIDX_VENDOR_ID, vendorId, true); AssertRC(vrc);
[1]1249
1250 USHORT productId = 0;
1251 rc = aUSBDevice->COMGETTER(ProductId) (&productId);
1252 ComAssertComRCRet (rc, false);
1253 ComAssertRet (productId, false);
[3756]1254 vrc = USBFilterSetNumExact (&dev, USBFILTERIDX_PRODUCT_ID, productId, true); AssertRC(vrc);
[1]1255
1256 USHORT revision;
1257 rc = aUSBDevice->COMGETTER(Revision) (&revision);
1258 ComAssertComRCRet (rc, false);
[3756]1259 vrc = USBFilterSetNumExact (&dev, USBFILTERIDX_DEVICE, revision, true); AssertRC(vrc);
[1]1260
1261 Bstr manufacturer;
1262 rc = aUSBDevice->COMGETTER(Manufacturer) (manufacturer.asOutParam());
1263 ComAssertComRCRet (rc, false);
[3756]1264 if (!manufacturer.isNull())
1265 USBFilterSetStringExact (&dev, USBFILTERIDX_MANUFACTURER_STR, Utf8Str(manufacturer), true);
[1]1266
1267 Bstr product;
1268 rc = aUSBDevice->COMGETTER(Product) (product.asOutParam());
1269 ComAssertComRCRet (rc, false);
[3756]1270 if (!product.isNull())
1271 USBFilterSetStringExact (&dev, USBFILTERIDX_PRODUCT_STR, Utf8Str(product), true);
[1]1272
1273 Bstr serialNumber;
1274 rc = aUSBDevice->COMGETTER(SerialNumber) (serialNumber.asOutParam());
1275 ComAssertComRCRet (rc, false);
[3756]1276 if (!serialNumber.isNull())
1277 USBFilterSetStringExact (&dev, USBFILTERIDX_SERIAL_NUMBER_STR, Utf8Str(serialNumber), true);
[1]1278
1279 Bstr address;
1280 rc = aUSBDevice->COMGETTER(Address) (address.asOutParam());
1281 ComAssertComRCRet (rc, false);
1282
1283 USHORT port = 0;
1284 rc = aUSBDevice->COMGETTER(Port)(&port);
1285 ComAssertComRCRet (rc, false);
[3756]1286 USBFilterSetNumExact (&dev, USBFILTERIDX_PORT, port, true);
[1]1287
1288 BOOL remote = FALSE;
1289 rc = aUSBDevice->COMGETTER(Remote)(&remote);
1290 ComAssertComRCRet (rc, false);
1291 ComAssertRet (remote == TRUE, false);
1292
1293 bool match = false;
1294
[2845]1295 /* apply self filters */
1296 for (DeviceFilterList::const_iterator it = mDeviceFilters->begin();
1297 it != mDeviceFilters->end();
[1]1298 ++ it)
1299 {
[8083]1300 AutoWriteLock filterLock (*it);
[1]1301 const USBDeviceFilter::Data &aData = (*it)->data();
1302
1303 if (!aData.mActive)
1304 continue;
[3756]1305 if (!aData.mRemote.isMatch (remote))
1306 continue;
1307 if (!USBFilterMatch (&aData.mUSBFilter, &dev))
[1]1308 continue;
1309
1310 match = true;
[5713]1311 *aMaskedIfs = aData.mMaskedIfs;
[1]1312 break;
1313 }
1314
[2845]1315 LogFlowThisFunc (("returns: %d\n", match));
1316 LogFlowThisFuncLeave();
1317
[1]1318 return match;
1319}
1320
[2845]1321/**
1322 * Notifies the proxy service about all filters as requested by the
1323 * @a aInsertFilters argument.
1324 *
1325 * @param aInsertFilters @c true to insert filters, @c false to remove.
1326 *
1327 * @note Locks this object for reading.
1328 */
[2805]1329HRESULT USBController::notifyProxy (bool aInsertFilters)
1330{
1331 LogFlowThisFunc (("aInsertFilters=%RTbool\n", aInsertFilters));
1332
[2845]1333 AutoCaller autoCaller (this);
1334 AssertComRCReturn (autoCaller.rc(), false);
[2805]1335
[8083]1336 AutoReadLock alock (this);
[2845]1337
1338 USBProxyService *service = mParent->virtualBox()->host()->usbProxyService();
[2805]1339 AssertReturn (service, E_FAIL);
1340
[2845]1341 DeviceFilterList::const_iterator it = mDeviceFilters->begin();
1342 while (it != mDeviceFilters->end())
[2805]1343 {
1344 USBDeviceFilter *flt = *it; /* resolve ambiguity (for ComPtr below) */
1345
1346 /* notify the proxy (only if the filter is active) */
1347 if (flt->data().mActive)
1348 {
1349 if (aInsertFilters)
1350 {
1351 AssertReturn (flt->id() == NULL, E_FAIL);
[3758]1352 flt->id() = service->insertFilter (&flt->data().mUSBFilter);
[2805]1353 }
1354 else
1355 {
[2978]1356 /* It's possible that the given filter was not inserted the proxy
1357 * when this method gets called (as a result of an early VM
1358 * process crash for example. So, don't assert that ID != NULL. */
1359 if (flt->id() != NULL)
1360 {
1361 service->removeFilter (flt->id());
1362 flt->id() = NULL;
1363 }
[2805]1364 }
1365 }
1366 ++ it;
1367 }
1368
[3007]1369 return S_OK;
[2805]1370}
1371
[7964]1372#endif /* VBOX_WITH_USB */
1373
[1]1374// private methods
1375/////////////////////////////////////////////////////////////////////////////
1376
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use