VirtualBox

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

Last change on this file since 2042 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.4 KB
Line 
1/** @file
2 *
3 * Implementation of IUSBController.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23
24#include "USBControllerImpl.h"
25#include "MachineImpl.h"
26#include "VirtualBoxImpl.h"
27#include "HostImpl.h"
28#include "USBDeviceImpl.h"
29#include "HostUSBDeviceImpl.h"
30#include "Logging.h"
31
32#include "USBProxyService.h"
33
34#include <iprt/string.h>
35#include <VBox/err.h>
36
37#include <algorithm>
38
39// defines
40/////////////////////////////////////////////////////////////////////////////
41
42// constructor / destructor
43/////////////////////////////////////////////////////////////////////////////
44
45HRESULT USBController::FinalConstruct()
46{
47 return S_OK;
48}
49
50void USBController::FinalRelease()
51{
52 if (isReady())
53 uninit();
54}
55
56// public initializer/uninitializer for internal purposes only
57/////////////////////////////////////////////////////////////////////////////
58
59/**
60 * Initializes the USB controller object.
61 *
62 * @returns COM result indicator.
63 * @param a_pParent Pointer to our parent object.
64 */
65HRESULT USBController::init(Machine *a_pParent)
66{
67 LogFlowMember(("USBController::init (%p)\n", a_pParent));
68
69 ComAssertRet (a_pParent, E_INVALIDARG);
70
71 AutoLock alock(this);
72 ComAssertRet (!isReady(), E_UNEXPECTED);
73
74 m_Parent = a_pParent;
75 // m_Peer is left null
76
77 m_Data.allocate();
78 m_DeviceFilters.allocate();
79
80 setReady(true);
81 return S_OK;
82}
83
84
85/**
86 * Initializes the USB controller object given another USB controller object
87 * (a kind of copy constructor). This object shares data with
88 * the object passed as an argument.
89 *
90 * @returns COM result indicator.
91 * @param a_pParent Pointer to our parent object.
92 * @param a_pPeer The object to share.
93 *
94 * @remark This object must be destroyed before the original object
95 * it shares data with is destroyed.
96 */
97HRESULT USBController::init(Machine *a_pParent, USBController *a_pPeer)
98{
99 LogFlowMember(("USBController::init (%p, %p)\n", a_pParent, a_pPeer));
100
101 ComAssertRet (a_pParent && a_pPeer, E_INVALIDARG);
102
103 AutoLock alock(this);
104 ComAssertRet (!isReady(), E_UNEXPECTED);
105
106 m_Parent = a_pParent;
107 m_Peer = a_pPeer;
108
109 AutoLock thatlock(a_pPeer);
110 m_Data.share(a_pPeer->m_Data);
111
112 // create copies of all filters
113 m_DeviceFilters.allocate();
114 DeviceFilterList::const_iterator it = a_pPeer->m_DeviceFilters->begin();
115 while (it != a_pPeer->m_DeviceFilters->end())
116 {
117 ComObjPtr <USBDeviceFilter> filter;
118 filter.createObject();
119 filter->init (this, *it);
120 m_DeviceFilters->push_back (filter);
121 ++ it;
122 }
123
124 setReady(true);
125 return S_OK;
126}
127
128
129/**
130 * Initializes the USB controller object given another guest object
131 * (a kind of copy constructor). This object makes a private copy of data
132 * of the original object passed as an argument.
133 */
134HRESULT USBController::initCopy (Machine *a_pParent, USBController *a_pPeer)
135{
136 LogFlowMember(("USBController::initCopy (%p, %p)\n", a_pParent, a_pPeer));
137
138 ComAssertRet (a_pParent && a_pPeer, E_INVALIDARG);
139
140 AutoLock alock(this);
141 ComAssertRet (!isReady(), E_UNEXPECTED);
142
143 m_Parent = a_pParent;
144 // m_Peer is left null
145
146 AutoLock thatlock(a_pPeer);
147 m_Data.attachCopy (a_pPeer->m_Data);
148
149 // create private copies of all filters
150 m_DeviceFilters.allocate();
151 DeviceFilterList::const_iterator it = a_pPeer->m_DeviceFilters->begin();
152 while (it != a_pPeer->m_DeviceFilters->end())
153 {
154 ComObjPtr <USBDeviceFilter> filter;
155 filter.createObject();
156 filter->initCopy (this, *it);
157 m_DeviceFilters->push_back (filter);
158 ++ it;
159 }
160
161 setReady(true);
162 return S_OK;
163}
164
165
166/**
167 * Uninitializes the instance and sets the ready flag to FALSE.
168 * Called either from FinalRelease() or by the parent when it gets destroyed.
169 */
170void USBController::uninit()
171{
172 LogFlowMember(("USBController::uninit()\n"));
173
174 AutoLock alock(this);
175 AssertReturn (isReady(), (void) 0);
176
177 // uninit all filters (including those still referenced by clients)
178 uninitDependentChildren();
179
180 m_DeviceFilters.free();
181 m_Data.free();
182
183 m_Peer.setNull();
184 m_Parent.setNull();
185
186 setReady(false);
187}
188
189
190
191// IUSBController properties
192/////////////////////////////////////////////////////////////////////////////
193
194STDMETHODIMP USBController::COMGETTER(Enabled)(BOOL *a_pfEnabled)
195{
196 if (!a_pfEnabled)
197 return E_POINTER;
198
199 AutoLock alock(this);
200 CHECK_READY();
201
202 *a_pfEnabled = m_Data->m_fEnabled;
203 LogFlowMember(("USBController::GetEnabled: returns %p\n", *a_pfEnabled));
204 return S_OK;
205}
206
207
208STDMETHODIMP USBController::COMSETTER(Enabled)(BOOL a_fEnabled)
209{
210 LogFlowMember(("USBController::SetEnabled: %s\n", a_fEnabled ? "enable" : "disable"));
211
212 AutoLock alock(this);
213 CHECK_READY();
214
215 CHECK_MACHINE_MUTABILITY (m_Parent);
216
217 if (m_Data->m_fEnabled != a_fEnabled)
218 {
219 m_Data.backup();
220 m_Data->m_fEnabled = a_fEnabled;
221
222 alock.unlock();
223 m_Parent->onUSBControllerChange();
224 }
225
226 return S_OK;
227}
228
229/**
230 * Get the USB standard version.
231 *
232 * @param a_pusUSBStandard Where to store the BCD version word.
233 */
234STDMETHODIMP USBController::COMGETTER(USBStandard)(USHORT *a_pusUSBStandard)
235{
236 if (!a_pusUSBStandard)
237 return E_POINTER;
238
239 AutoLock alock(this);
240 CHECK_READY();
241
242 *a_pusUSBStandard = 0x0101;
243 LogFlowMember(("USBController::GetUSBStandard: returns 0x0101\n"));
244 return S_OK;
245}
246
247STDMETHODIMP USBController::COMGETTER(DeviceFilters) (IUSBDeviceFilterCollection **aDevicesFilters)
248{
249 if (!aDevicesFilters)
250 return E_POINTER;
251
252 AutoLock lock(this);
253 CHECK_READY();
254
255 ComObjPtr <USBDeviceFilterCollection> collection;
256 collection.createObject();
257 collection->init (*m_DeviceFilters.data());
258 collection.queryInterfaceTo (aDevicesFilters);
259 return S_OK;
260}
261
262// IUSBController methods
263/////////////////////////////////////////////////////////////////////////////
264
265STDMETHODIMP USBController::CreateDeviceFilter (INPTR BSTR aName,
266 IUSBDeviceFilter **aFilter)
267{
268 if (!aFilter)
269 return E_POINTER;
270
271 if (!aName || *aName == 0)
272 return E_INVALIDARG;
273
274 AutoLock lock (this);
275 CHECK_READY();
276
277 CHECK_MACHINE_MUTABILITY (m_Parent);
278
279 ComObjPtr <USBDeviceFilter> filter;
280 filter.createObject();
281 HRESULT rc = filter->init (this, aName);
282 ComAssertComRCRet (rc, rc);
283 rc = filter.queryInterfaceTo (aFilter);
284 AssertComRCReturn (rc, rc);
285 return S_OK;
286}
287
288STDMETHODIMP USBController::InsertDeviceFilter (ULONG aPosition,
289 IUSBDeviceFilter *aFilter)
290{
291 if (!aFilter)
292 return E_INVALIDARG;
293
294 AutoLock lock (this);
295 CHECK_READY();
296
297 CHECK_MACHINE_MUTABILITY (m_Parent);
298
299 ComObjPtr <USBDeviceFilter> filter = getDependentChild (aFilter);
300 if (!filter)
301 return setError (E_INVALIDARG,
302 tr ("The given USB device filter is not created within "
303 "this VirtualBox instance"));
304
305 if (filter->mInList)
306 return setError (E_INVALIDARG,
307 tr ("The given USB device filter is already in the list"));
308
309 // backup the list before modification
310 m_DeviceFilters.backup();
311
312 // iterate to the position...
313 DeviceFilterList::iterator it;
314 if (aPosition < m_DeviceFilters->size())
315 {
316 it = m_DeviceFilters->begin();
317 std::advance (it, aPosition);
318 }
319 else
320 it = m_DeviceFilters->end();
321 // ...and insert
322 m_DeviceFilters->insert (it, filter);
323 filter->mInList = true;
324
325 // notify the proxy (only when the filter is active)
326 if (filter->data().mActive)
327 {
328 USBProxyService *service = m_Parent->virtualBox()->host()->usbProxyService();
329 ComAssertRet (service, E_FAIL);
330
331 ComAssertRet (filter->id() == NULL, E_FAIL);
332 filter->id() = service->insertFilter (ComPtr <IUSBDeviceFilter> (aFilter));
333 }
334
335 return S_OK;
336}
337
338STDMETHODIMP USBController::RemoveDeviceFilter (ULONG aPosition,
339 IUSBDeviceFilter **aFilter)
340{
341 if (!aFilter)
342 return E_POINTER;
343
344 AutoLock lock (this);
345 CHECK_READY();
346
347 CHECK_MACHINE_MUTABILITY (m_Parent);
348
349 if (!m_DeviceFilters->size())
350 return setError (E_INVALIDARG,
351 tr ("The USB device filter list is empty"));
352
353 if (aPosition >= m_DeviceFilters->size())
354 return setError (E_INVALIDARG,
355 tr ("Invalid position: %lu (must be in range [0, %lu])"),
356 aPosition, m_DeviceFilters->size() - 1);
357
358 // backup the list before modification
359 m_DeviceFilters.backup();
360
361 ComObjPtr <USBDeviceFilter> filter;
362 {
363 // iterate to the position...
364 DeviceFilterList::iterator it = m_DeviceFilters->begin();
365 std::advance (it, aPosition);
366 // ...get an element from there...
367 filter = *it;
368 // ...and remove
369 filter->mInList = false;
370 m_DeviceFilters->erase (it);
371 }
372
373 // cancel sharing (make an independent copy of data)
374 filter->unshare();
375
376 filter.queryInterfaceTo (aFilter);
377
378 // notify the proxy (only when the filter is active)
379 if (filter->data().mActive)
380 {
381 USBProxyService *service = m_Parent->virtualBox()->host()->usbProxyService();
382 ComAssertRet (service, E_FAIL);
383
384 ComAssertRet (filter->id() != NULL, E_FAIL);
385 service->removeFilter (filter->id());
386 filter->id() = NULL;
387 }
388
389 return S_OK;
390}
391
392// public methods only for internal purposes
393/////////////////////////////////////////////////////////////////////////////
394
395/** Loads settings from the configuration node */
396HRESULT USBController::loadSettings (CFGNODE aMachine)
397{
398 AutoLock lock (this);
399 CHECK_READY();
400
401 ComAssertRet (aMachine, E_FAIL);
402
403 CFGNODE controller = NULL;
404 CFGLDRGetChildNode (aMachine, "USBController", 0, &controller);
405 Assert (controller);
406
407 // enabled
408 bool enabled;
409 CFGLDRQueryBool (controller, "enabled", &enabled);
410 m_Data->m_fEnabled = enabled;
411
412 HRESULT rc = S_OK;
413
414 unsigned filterCount = 0;
415 CFGLDRCountChildren (controller, "DeviceFilter", &filterCount);
416 for (unsigned i = 0; i < filterCount && SUCCEEDED (rc); i++)
417 {
418 CFGNODE filter = NULL;
419 CFGLDRGetChildNode (controller, "DeviceFilter", i, &filter);
420 Assert (filter);
421
422 Bstr name;
423 CFGLDRQueryBSTR (filter, "name", name.asOutParam());
424 bool active;
425 CFGLDRQueryBool (filter, "active", &active);
426
427 Bstr vendorId;
428 CFGLDRQueryBSTR (filter, "vendorid", vendorId.asOutParam());
429 Bstr productId;
430 CFGLDRQueryBSTR (filter, "productid", productId.asOutParam());
431 Bstr revision;
432 CFGLDRQueryBSTR (filter, "revision", revision.asOutParam());
433 Bstr manufacturer;
434 CFGLDRQueryBSTR (filter, "manufacturer", manufacturer.asOutParam());
435 Bstr product;
436 CFGLDRQueryBSTR (filter, "product", product.asOutParam());
437 Bstr serialNumber;
438 CFGLDRQueryBSTR (filter, "serialnumber", serialNumber.asOutParam());
439 Bstr port;
440 CFGLDRQueryBSTR (filter, "port", port.asOutParam());
441 Bstr remote;
442 CFGLDRQueryBSTR (filter, "remote", remote.asOutParam());
443
444 ComObjPtr <USBDeviceFilter> filterObj;
445 filterObj.createObject();
446 rc = filterObj->init (this,
447 name, active, vendorId, productId, revision,
448 manufacturer, product, serialNumber,
449 port, remote);
450 // error info is set by init() when appropriate
451 if (SUCCEEDED (rc))
452 {
453 m_DeviceFilters->push_back (filterObj);
454 filterObj->mInList = true;
455 }
456
457 CFGLDRReleaseNode (filter);
458 }
459
460 CFGLDRReleaseNode (controller);
461
462 return rc;
463}
464
465/** Saves settings to the configuration node */
466HRESULT USBController::saveSettings (CFGNODE aMachine)
467{
468 AutoLock lock (this);
469 CHECK_READY();
470
471 ComAssertRet (aMachine, E_FAIL);
472
473 // first, delete the entry
474 CFGNODE controller = NULL;
475 int vrc = CFGLDRGetChildNode (aMachine, "USBController", 0, &controller);
476 if (VBOX_SUCCESS (vrc))
477 {
478 vrc = CFGLDRDeleteNode (controller);
479 ComAssertRCRet (vrc, E_FAIL);
480 }
481 // then, recreate it
482 vrc = CFGLDRCreateChildNode (aMachine, "USBController", &controller);
483 ComAssertRCRet (vrc, E_FAIL);
484
485 // enabled
486 CFGLDRSetBool (controller, "enabled", !!m_Data->m_fEnabled);
487
488 DeviceFilterList::const_iterator it = m_DeviceFilters->begin();
489 while (it != m_DeviceFilters->end())
490 {
491 AutoLock filterLock (*it);
492 const USBDeviceFilter::Data &data = (*it)->data();
493
494 CFGNODE filter = NULL;
495 CFGLDRAppendChildNode (controller, "DeviceFilter", &filter);
496
497 CFGLDRSetBSTR (filter, "name", data.mName);
498 CFGLDRSetBool (filter, "active", !!data.mActive);
499
500 // all are optional
501 if (data.mVendorId.string())
502 CFGLDRSetBSTR (filter, "vendorid", data.mVendorId.string());
503 if (data.mProductId.string())
504 CFGLDRSetBSTR (filter, "productid", data.mProductId.string());
505 if (data.mRevision.string())
506 CFGLDRSetBSTR (filter, "revision", data.mRevision.string());
507 if (data.mManufacturer.string())
508 CFGLDRSetBSTR (filter, "manufacturer", data.mManufacturer.string());
509 if (data.mProduct.string())
510 CFGLDRSetBSTR (filter, "product", data.mProduct.string());
511 if (data.mSerialNumber.string())
512 CFGLDRSetBSTR (filter, "serialnumber", data.mSerialNumber.string());
513 if (data.mPort.string())
514 CFGLDRSetBSTR (filter, "port", data.mPort.string());
515 if (data.mRemote.string())
516 CFGLDRSetBSTR (filter, "remote", data.mRemote.string());
517
518 CFGLDRReleaseNode (filter);
519
520 ++ it;
521 }
522
523 CFGLDRReleaseNode (controller);
524
525 return S_OK;
526}
527
528bool USBController::isModified()
529{
530 AutoLock alock(this);
531
532 if (m_Data.isBackedUp() || m_DeviceFilters.isBackedUp())
533 return true;
534
535 /* see whether any of filters has changed its data */
536 for (DeviceFilterList::const_iterator
537 it = m_DeviceFilters->begin();
538 it != m_DeviceFilters->end();
539 ++ it)
540 {
541 if ((*it)->isModified())
542 return true;
543 }
544
545 return false;
546}
547
548bool USBController::isReallyModified()
549{
550 AutoLock alock(this);
551
552 if (m_Data.hasActualChanges())
553 return true;
554
555 if (!m_DeviceFilters.isBackedUp())
556 {
557 /* see whether any of filters has changed its data */
558 for (DeviceFilterList::const_iterator
559 it = m_DeviceFilters->begin();
560 it != m_DeviceFilters->end();
561 ++ it)
562 {
563 if ((*it)->isReallyModified())
564 return true;
565 }
566
567 return false;
568 }
569
570 if (m_DeviceFilters->size() != m_DeviceFilters.backedUpData()->size())
571 return true;
572
573 if (m_DeviceFilters->size() == 0)
574 return false;
575
576 /* Make copies to speed up comparison */
577 DeviceFilterList devices = *m_DeviceFilters.data();
578 DeviceFilterList backDevices = *m_DeviceFilters.backedUpData();
579
580 DeviceFilterList::iterator it = devices.begin();
581 while (it != devices.end())
582 {
583 bool found = false;
584 DeviceFilterList::iterator thatIt = backDevices.begin();
585 while (thatIt != backDevices.end())
586 {
587 if ((*it)->data() == (*thatIt)->data())
588 {
589 backDevices.erase (thatIt);
590 found = true;
591 break;
592 }
593 else
594 ++ thatIt;
595 }
596 if (found)
597 it = devices.erase (it);
598 else
599 return false;
600 }
601
602 Assert (devices.size() == 0 && backDevices.size() == 0);
603
604 return false;
605}
606
607bool USBController::rollback()
608{
609 AutoLock alock(this);
610
611 bool dataChanged = false;
612
613 if (m_Data.isBackedUp())
614 {
615 // we need to check all data to see whether anything will be changed
616 // after rollback
617 dataChanged = m_Data.hasActualChanges();
618 m_Data.rollback();
619 }
620
621 if (m_DeviceFilters.isBackedUp())
622 {
623 USBProxyService *service = m_Parent->virtualBox()->host()->usbProxyService();
624 ComAssertRet (service, false);
625
626 // uninitialize all new filters (absent in the backed up list)
627 DeviceFilterList::const_iterator it = m_DeviceFilters->begin();
628 DeviceFilterList *backedList = m_DeviceFilters.backedUpData();
629 while (it != m_DeviceFilters->end())
630 {
631 if (std::find (backedList->begin(), backedList->end(), *it) ==
632 backedList->end())
633 {
634 // notify the proxy (only when the filter is active)
635 if ((*it)->data().mActive)
636 {
637 USBDeviceFilter *filter = *it;
638 ComAssertRet (filter->id() != NULL, false);
639 service->removeFilter (filter->id());
640 filter->id() = NULL;
641 }
642
643 (*it)->uninit();
644 }
645 ++ it;
646 }
647
648 // find all removed old filters (absent in the new list)
649 // and insert them back to the USB proxy
650 it = backedList->begin();
651 while (it != backedList->end())
652 {
653 if (std::find (m_DeviceFilters->begin(), m_DeviceFilters->end(), *it) ==
654 m_DeviceFilters->end())
655 {
656 // notify the proxy (only when the filter is active)
657 if ((*it)->data().mActive)
658 {
659 USBDeviceFilter *flt = *it; // resolve ambiguity
660 ComAssertRet (flt->id() == NULL, false);
661 flt->id() = service->insertFilter (ComPtr <IUSBDeviceFilter> (flt));
662 }
663 }
664 ++ it;
665 }
666
667 // restore the list
668 m_DeviceFilters.rollback();
669 }
670
671 // rollback any changes to filters after restoring the list
672 DeviceFilterList::const_iterator it = m_DeviceFilters->begin();
673 while (it != m_DeviceFilters->end())
674 {
675 if ((*it)->isModified())
676 {
677 (*it)->rollback();
678 // call this to notify the USB proxy about changes
679 onDeviceFilterChange (*it);
680 }
681 ++ it;
682 }
683
684 return dataChanged;
685}
686
687void USBController::commit()
688{
689 AutoLock alock (this);
690
691 if (m_Data.isBackedUp())
692 {
693 m_Data.commit();
694 if (m_Peer)
695 {
696 // attach new data to the peer and reshare it
697 AutoLock peerlock (m_Peer);
698 m_Peer->m_Data.attach (m_Data);
699 }
700 }
701
702 bool commitFilters = false;
703
704 if (m_DeviceFilters.isBackedUp())
705 {
706 m_DeviceFilters.commit();
707
708 // apply changes to peer
709 if (m_Peer)
710 {
711 AutoLock peerlock (m_Peer);
712 // commit all changes to new filters (this will reshare data with
713 // peers for those who have peers)
714 DeviceFilterList *newList = new DeviceFilterList();
715 DeviceFilterList::const_iterator it = m_DeviceFilters->begin();
716 while (it != m_DeviceFilters->end())
717 {
718 (*it)->commit();
719
720 // look if this filter has a peer filter
721 ComObjPtr <USBDeviceFilter> peer = (*it)->peer();
722 if (!peer)
723 {
724 // no peer means the filter is a newly created one;
725 // create a peer owning data this filter share it with
726 peer.createObject();
727 peer->init (m_Peer, *it, true /* aReshare */);
728 }
729 else
730 {
731 // remove peer from the old list
732 m_Peer->m_DeviceFilters->remove (peer);
733 }
734 // and add it to the new list
735 newList->push_back (peer);
736
737 ++ it;
738 }
739
740 // uninit old peer's filters that are left
741 it = m_Peer->m_DeviceFilters->begin();
742 while (it != m_Peer->m_DeviceFilters->end())
743 {
744 (*it)->uninit();
745 ++ it;
746 }
747
748 // attach new list of filters to our peer
749 m_Peer->m_DeviceFilters.attach (newList);
750 }
751 else
752 {
753 // we have no peer (our parent is the newly created machine);
754 // just commit changes to filters
755 commitFilters = true;
756 }
757 }
758 else
759 {
760 // the list of filters itself is not changed,
761 // just commit changes to filters themselves
762 commitFilters = true;
763 }
764
765 if (commitFilters)
766 {
767 DeviceFilterList::const_iterator it = m_DeviceFilters->begin();
768 while (it != m_DeviceFilters->end())
769 {
770 (*it)->commit();
771 ++ it;
772 }
773 }
774}
775
776void USBController::copyFrom (USBController *aThat)
777{
778 AutoLock alock (this);
779 AutoLock thatLock (aThat);
780
781 if (m_Parent->isRegistered())
782 {
783 // reuse onMachineRegistered to tell USB proxy to remove all current filters
784 HRESULT rc = onMachineRegistered (FALSE);
785 AssertComRCReturn (rc, (void) 0);
786 }
787
788 // this will back up current data
789 m_Data.assignCopy (aThat->m_Data);
790
791 // create private copies of all filters
792 m_DeviceFilters.backup();
793 m_DeviceFilters->clear();
794 for (DeviceFilterList::const_iterator it = aThat->m_DeviceFilters->begin();
795 it != aThat->m_DeviceFilters->end();
796 ++ it)
797 {
798 ComObjPtr <USBDeviceFilter> filter;
799 filter.createObject();
800 filter->initCopy (this, *it);
801 m_DeviceFilters->push_back (filter);
802 }
803
804 if (m_Parent->isRegistered())
805 {
806 // reuse onMachineRegistered to tell USB proxy to insert all current filters
807 HRESULT rc = onMachineRegistered (TRUE);
808 AssertComRCReturn (rc, (void) 0);
809 }
810}
811
812/**
813 * Called by VirtualBox when it changes the registered state
814 * of the machine this USB controller belongs to.
815 *
816 * @param aRegistered new registered state of the machine
817 */
818HRESULT USBController::onMachineRegistered (BOOL aRegistered)
819{
820 AutoLock alock (this);
821 CHECK_READY();
822
823 USBProxyService *service = m_Parent->virtualBox()->host()->usbProxyService();
824 ComAssertRet (service, E_FAIL);
825
826 // iterate over the filter list and notify the proxy accordingly
827
828 DeviceFilterList::const_iterator it = m_DeviceFilters->begin();
829 while (it != m_DeviceFilters->end())
830 {
831 USBDeviceFilter *flt = *it; // resolve ambiguity (for ComPtr below)
832
833 // notify the proxy (only if the filter is active)
834 if (flt->data().mActive)
835 {
836 if (aRegistered)
837 {
838 ComAssertRet (flt->id() == NULL, E_FAIL);
839 flt->id() = service->insertFilter (ComPtr <IUSBDeviceFilter> (flt));
840 }
841 else
842 {
843 ComAssertRet (flt->id() != NULL, E_FAIL);
844 service->removeFilter (flt->id());
845 flt->id() = NULL;
846 }
847 }
848 ++ it;
849 }
850
851 return S_OK;
852}
853
854/**
855 * Called by setter methods of all USB device filters.
856 */
857HRESULT USBController::onDeviceFilterChange (USBDeviceFilter *aFilter,
858 BOOL aActiveChanged /* = FALSE */)
859{
860 AutoLock alock (this);
861 CHECK_READY();
862
863 if (aFilter->mInList && m_Parent->isRegistered())
864 {
865 USBProxyService *service = m_Parent->virtualBox()->host()->usbProxyService();
866 ComAssertRet (service, E_FAIL);
867
868 if (aActiveChanged)
869 {
870 // insert/remove the filter from the proxy
871 if (aFilter->data().mActive)
872 {
873 ComAssertRet (aFilter->id() == NULL, E_FAIL);
874 aFilter->id() =
875 service->insertFilter (ComPtr <IUSBDeviceFilter> (aFilter));
876 }
877 else
878 {
879 ComAssertRet (aFilter->id() != NULL, E_FAIL);
880 service->removeFilter (aFilter->id());
881 aFilter->id() = NULL;
882 }
883 }
884 else
885 {
886 if (aFilter->data().mActive)
887 {
888 // update the filter in the proxy
889 ComAssertRet (aFilter->id() != NULL, E_FAIL);
890 service->removeFilter (aFilter->id());
891 aFilter->id() =
892 service->insertFilter (ComPtr <IUSBDeviceFilter> (aFilter));
893 }
894 }
895 }
896
897 return S_OK;
898}
899
900/**
901 * Returns true if the given USB device matches to at least one of
902 * this controller's USB device filters.
903 *
904 * A HostUSBDevice specific version.
905 */
906bool USBController::hasMatchingFilter (ComObjPtr <HostUSBDevice> &aDevice)
907{
908 AutoLock alock (this);
909 if (!isReady())
910 return false;
911
912 bool match = false;
913
914 // apply self filters
915 for (DeviceFilterList::const_iterator it = m_DeviceFilters->begin();
916 !match && it != m_DeviceFilters->end();
917 ++ it)
918 {
919 AutoLock filterLock (*it);
920 match = aDevice->isMatch ((*it)->data());
921 }
922
923 return match;
924}
925
926/**
927 * Returns true if the given USB device matches to at least one of
928 * this controller's USB device filters.
929 *
930 * A generic version that accepts any IUSBDevice on input.
931 *
932 * @note
933 * This method MUST correlate with HostUSBDevice::isMatch()
934 * in the sense of the device matching logic.
935 */
936bool USBController::hasMatchingFilter (IUSBDevice *aUSBDevice)
937{
938 LogFlowMember (("USBController::hasMatchingFilter()\n"));
939
940 AutoLock alock (this);
941 if (!isReady())
942 return false;
943
944 HRESULT rc = S_OK;
945
946 // query fields
947
948 USHORT vendorId = 0;
949 rc = aUSBDevice->COMGETTER(VendorId) (&vendorId);
950 ComAssertComRCRet (rc, false);
951 ComAssertRet (vendorId, false);
952
953 USHORT productId = 0;
954 rc = aUSBDevice->COMGETTER(ProductId) (&productId);
955 ComAssertComRCRet (rc, false);
956 ComAssertRet (productId, false);
957
958 USHORT revision;
959 rc = aUSBDevice->COMGETTER(Revision) (&revision);
960 ComAssertComRCRet (rc, false);
961
962 Bstr manufacturer;
963 rc = aUSBDevice->COMGETTER(Manufacturer) (manufacturer.asOutParam());
964 ComAssertComRCRet (rc, false);
965
966 Bstr product;
967 rc = aUSBDevice->COMGETTER(Product) (product.asOutParam());
968 ComAssertComRCRet (rc, false);
969
970 Bstr serialNumber;
971 rc = aUSBDevice->COMGETTER(SerialNumber) (serialNumber.asOutParam());
972 ComAssertComRCRet (rc, false);
973
974 Bstr address;
975 rc = aUSBDevice->COMGETTER(Address) (address.asOutParam());
976 ComAssertComRCRet (rc, false);
977
978 USHORT port = 0;
979 rc = aUSBDevice->COMGETTER(Port)(&port);
980 ComAssertComRCRet (rc, false);
981
982 BOOL remote = FALSE;
983 rc = aUSBDevice->COMGETTER(Remote)(&remote);
984 ComAssertComRCRet (rc, false);
985 ComAssertRet (remote == TRUE, false);
986
987 bool match = false;
988
989 // apply self filters
990 for (DeviceFilterList::const_iterator it = m_DeviceFilters->begin();
991 it != m_DeviceFilters->end();
992 ++ it)
993 {
994 AutoLock filterLock (*it);
995 const USBDeviceFilter::Data &aData = (*it)->data();
996
997 if (!aData.mActive)
998 continue;
999 if (!aData.mVendorId.isMatch (vendorId))
1000 continue;
1001 if (!aData.mProductId.isMatch (productId))
1002 continue;
1003 if (!aData.mRevision.isMatch (revision))
1004 continue;
1005
1006#if !defined (__WIN__)
1007 // these filters are temporarily ignored on Win32
1008 if (!aData.mManufacturer.isMatch (manufacturer))
1009 continue;
1010 if (!aData.mProduct.isMatch (product))
1011 continue;
1012 if (!aData.mSerialNumber.isMatch (serialNumber))
1013 continue;
1014 if (!aData.mPort.isMatch (port))
1015 continue;
1016#endif
1017
1018 if (!aData.mRemote.isMatch (remote))
1019 continue;
1020
1021 match = true;
1022 break;
1023 }
1024
1025 LogFlowMember (("USBController::hasMatchingFilter() returns: %d\n", match));
1026 return match;
1027}
1028
1029// private methods
1030/////////////////////////////////////////////////////////////////////////////
1031
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