VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/USBControllerImpl.cpp@ 47698

Last change on this file since 47698 was 47401, checked in by vboxsync, 11 years ago

Main,Frontends: Second step of USB controller rework. There is one controller instance for every USB controller now. Adapt frontends and testsuite to work with the changed API

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* $Id: USBControllerImpl.cpp 47401 2013-07-25 19:12:24Z vboxsync $ */
2/** @file
3 * Implementation of IUSBController.
4 */
5
6/*
7 * Copyright (C) 2005-2013 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#include "USBControllerImpl.h"
19
20#include "Global.h"
21#include "MachineImpl.h"
22#include "VirtualBoxImpl.h"
23#include "HostImpl.h"
24
25#include <iprt/string.h>
26#include <iprt/cpp/utils.h>
27
28#include <VBox/err.h>
29#include <VBox/settings.h>
30#include <VBox/com/array.h>
31
32#include <algorithm>
33
34#include "AutoStateDep.h"
35#include "AutoCaller.h"
36#include "Logging.h"
37
38// defines
39/////////////////////////////////////////////////////////////////////////////
40
41struct BackupableUSBData
42{
43 BackupableUSBData()
44 : enmType(USBControllerType_Null)
45 { }
46
47 Utf8Str strName;
48 USBControllerType_T enmType;
49};
50
51struct USBController::Data
52{
53 Data(Machine *pMachine)
54 : pParent(pMachine)
55 { }
56
57 ~Data()
58 {};
59
60 Machine * const pParent;
61
62 // peer machine's USB controller
63 const ComObjPtr<USBController> pPeer;
64
65 Backupable<BackupableUSBData> bd;
66};
67
68
69
70// constructor / destructor
71/////////////////////////////////////////////////////////////////////////////
72
73DEFINE_EMPTY_CTOR_DTOR(USBController)
74
75HRESULT USBController::FinalConstruct()
76{
77 return BaseFinalConstruct();
78}
79
80void USBController::FinalRelease()
81{
82 uninit();
83 BaseFinalRelease();
84}
85
86// public initializer/uninitializer for internal purposes only
87/////////////////////////////////////////////////////////////////////////////
88
89/**
90 * Initializes the USB controller object.
91 *
92 * @returns COM result indicator.
93 * @param aParent Pointer to our parent object.
94 * @param aName The name of the USB controller.
95 * @param enmType The USB controller type.
96 */
97HRESULT USBController::init(Machine *aParent, const Utf8Str &aName, USBControllerType_T enmType)
98{
99 LogFlowThisFunc(("aParent=%p aName=\"%s\"\n", aParent, aName.c_str()));
100
101 ComAssertRet(aParent && !aName.isEmpty(), E_INVALIDARG);
102 if ( (enmType <= USBControllerType_Null)
103 || (enmType > USBControllerType_EHCI))
104 return setError(E_INVALIDARG,
105 tr("Invalid USB controller type"));
106
107 /* Enclose the state transition NotReady->InInit->Ready */
108 AutoInitSpan autoInitSpan(this);
109 AssertReturn(autoInitSpan.isOk(), E_FAIL);
110
111 m = new Data(aParent);
112
113 /* mPeer is left null */
114
115 m->bd.allocate();
116 m->bd->strName = aName;
117 m->bd->enmType = enmType;
118
119 /* Confirm a successful initialization */
120 autoInitSpan.setSucceeded();
121
122 return S_OK;
123}
124
125/**
126 * Initializes the USB controller object given another USB controller object
127 * (a kind of copy constructor). This object shares data with
128 * the object passed as an argument.
129 *
130 * @returns COM result indicator.
131 * @param aParent Pointer to our parent object.
132 * @param aPeer The object to share.
133 * @param aReshare
134 * When false, the original object will remain a data owner.
135 * Otherwise, data ownership will be transferred from the original
136 * object to this one.
137 *
138 * @note This object must be destroyed before the original object
139 * it shares data with is destroyed.
140 *
141 * @note Locks @a aThat object for writing if @a aReshare is @c true, or for
142 * reading if @a aReshare is false.
143 */
144HRESULT USBController::init(Machine *aParent, USBController *aPeer,
145 bool fReshare /* = false */)
146{
147 LogFlowThisFunc(("aParent=%p, aPeer=%p, fReshare=%RTbool\n",
148 aParent, aPeer, fReshare));
149
150 ComAssertRet(aParent && aPeer, E_INVALIDARG);
151
152 /* Enclose the state transition NotReady->InInit->Ready */
153 AutoInitSpan autoInitSpan(this);
154 AssertReturn(autoInitSpan.isOk(), E_FAIL);
155
156 m = new Data(aParent);
157
158 /* sanity */
159 AutoCaller peerCaller(aPeer);
160 AssertComRCReturnRC(peerCaller.rc());
161
162 if (fReshare)
163 {
164 AutoWriteLock peerLock(aPeer COMMA_LOCKVAL_SRC_POS);
165
166 unconst(aPeer->m->pPeer) = this;
167 m->bd.attach (aPeer->m->bd);
168 }
169 else
170 {
171 unconst(m->pPeer) = aPeer;
172
173 AutoReadLock peerLock(aPeer COMMA_LOCKVAL_SRC_POS);
174 m->bd.share (aPeer->m->bd);
175 }
176
177 /* Confirm a successful initialization */
178 autoInitSpan.setSucceeded();
179
180 return S_OK;
181}
182
183
184/**
185 * Initializes the USB controller object given another guest object
186 * (a kind of copy constructor). This object makes a private copy of data
187 * of the original object passed as an argument.
188 */
189HRESULT USBController::initCopy(Machine *aParent, USBController *aPeer)
190{
191 LogFlowThisFunc(("aParent=%p, aPeer=%p\n", aParent, aPeer));
192
193 ComAssertRet(aParent && aPeer, E_INVALIDARG);
194
195 /* Enclose the state transition NotReady->InInit->Ready */
196 AutoInitSpan autoInitSpan(this);
197 AssertReturn(autoInitSpan.isOk(), E_FAIL);
198
199 m = new Data(aParent);
200
201 /* mPeer is left null */
202
203 AutoWriteLock thatlock(aPeer COMMA_LOCKVAL_SRC_POS);
204 m->bd.attachCopy(aPeer->m->bd);
205
206 /* Confirm a successful initialization */
207 autoInitSpan.setSucceeded();
208
209 return S_OK;
210}
211
212
213/**
214 * Uninitializes the instance and sets the ready flag to FALSE.
215 * Called either from FinalRelease() or by the parent when it gets destroyed.
216 */
217void USBController::uninit()
218{
219 LogFlowThisFunc(("\n"));
220
221 /* Enclose the state transition Ready->InUninit->NotReady */
222 AutoUninitSpan autoUninitSpan(this);
223 if (autoUninitSpan.uninitDone())
224 return;
225
226 m->bd.free();
227
228 unconst(m->pPeer) = NULL;
229 unconst(m->pParent) = NULL;
230
231 delete m;
232 m = NULL;
233}
234
235
236// IUSBController properties
237/////////////////////////////////////////////////////////////////////////////
238STDMETHODIMP USBController::COMGETTER(Name) (BSTR *aName)
239{
240 CheckComArgOutPointerValid(aName);
241
242 AutoCaller autoCaller(this);
243 if (FAILED(autoCaller.rc())) return autoCaller.rc();
244
245 /* strName is constant during life time, no need to lock */
246 m->bd->strName.cloneTo(aName);
247
248 return S_OK;
249}
250
251STDMETHODIMP USBController::COMGETTER(Type)(USBControllerType_T *aType)
252{
253 CheckComArgOutPointerValid(aType);
254
255 AutoCaller autoCaller(this);
256 if (FAILED(autoCaller.rc())) return autoCaller.rc();
257
258 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
259
260 *aType = m->bd->enmType;
261
262 return S_OK;
263}
264
265STDMETHODIMP USBController::COMGETTER(USBStandard)(USHORT *aUSBStandard)
266{
267 CheckComArgOutPointerValid(aUSBStandard);
268
269 AutoCaller autoCaller(this);
270 if (FAILED(autoCaller.rc())) return autoCaller.rc();
271
272 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
273
274 switch (m->bd->enmType)
275 {
276 case USBControllerType_OHCI:
277 *aUSBStandard = 0x0101;
278 break;
279 case USBControllerType_EHCI:
280 *aUSBStandard = 0x0200;
281 break;
282 default:
283 AssertMsgFailedReturn(("Invalid controller type %d\n", m->bd->enmType),
284 E_FAIL);
285 }
286
287 return S_OK;
288}
289
290// public methods only for internal purposes
291/////////////////////////////////////////////////////////////////////////////
292
293/** @note Locks objects for writing! */
294void USBController::rollback()
295{
296 AutoCaller autoCaller(this);
297 AssertComRCReturnVoid(autoCaller.rc());
298
299 /* we need the machine state */
300 AutoAnyStateDependency adep(m->pParent);
301 AssertComRCReturnVoid(adep.rc());
302
303 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
304
305 m->bd.rollback();
306}
307
308/**
309 * @note Locks this object for writing, together with the peer object (also
310 * for writing) if there is one.
311 */
312void USBController::commit()
313{
314 /* sanity */
315 AutoCaller autoCaller(this);
316 AssertComRCReturnVoid(autoCaller.rc());
317
318 /* sanity too */
319 AutoCaller peerCaller(m->pPeer);
320 AssertComRCReturnVoid(peerCaller.rc());
321
322 /* lock both for writing since we modify both (mPeer is "master" so locked
323 * first) */
324 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
325
326 if (m->bd.isBackedUp())
327 {
328 m->bd.commit();
329 if (m->pPeer)
330 {
331 /* attach new data to the peer and reshare it */
332 AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
333 m->pPeer->m->bd.attach(m->bd);
334 }
335 }
336}
337
338/**
339 * @note Locks this object for writing, together with the peer object
340 * represented by @a aThat (locked for reading).
341 */
342void USBController::copyFrom(USBController *aThat)
343{
344 AssertReturnVoid(aThat != NULL);
345
346 /* sanity */
347 AutoCaller autoCaller(this);
348 AssertComRCReturnVoid(autoCaller.rc());
349
350 /* sanity too */
351 AutoCaller thatCaller(aThat);
352 AssertComRCReturnVoid(thatCaller.rc());
353
354 /* even more sanity */
355 AutoAnyStateDependency adep(m->pParent);
356 AssertComRCReturnVoid(adep.rc());
357 /* Machine::copyFrom() may not be called when the VM is running */
358 AssertReturnVoid(!Global::IsOnline(adep.machineState()));
359
360 /* peer is not modified, lock it for reading (aThat is "master" so locked
361 * first) */
362 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
363 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
364
365 /* this will back up current data */
366 m->bd.assignCopy(aThat->m->bd);
367}
368
369/**
370 * Cancels sharing (if any) by making an independent copy of data.
371 * This operation also resets this object's peer to NULL.
372 *
373 * @note Locks this object for writing, together with the peer object
374 * represented by @a aThat (locked for reading).
375 */
376void USBController::unshare()
377{
378 /* sanity */
379 AutoCaller autoCaller(this);
380 AssertComRCReturnVoid (autoCaller.rc());
381
382 /* sanity too */
383 AutoCaller peerCaller (m->pPeer);
384 AssertComRCReturnVoid (peerCaller.rc());
385
386 /* peer is not modified, lock it for reading (m->pPeer is "master" so locked
387 * first) */
388 AutoReadLock rl(m->pPeer COMMA_LOCKVAL_SRC_POS);
389 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
390
391 if (m->bd.isShared())
392 {
393 if (!m->bd.isBackedUp())
394 m->bd.backup();
395
396 m->bd.commit();
397 }
398
399 unconst(m->pPeer) = NULL;
400}
401
402const Utf8Str& USBController::getName() const
403{
404 return m->bd->strName;
405}
406
407USBControllerType_T USBController::getControllerType() const
408{
409 return m->bd->enmType;
410}
411
412ComObjPtr<USBController> USBController::getPeer()
413{
414 return m->pPeer;
415}
416
417// private methods
418/////////////////////////////////////////////////////////////////////////////
419/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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