VirtualBox

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

Last change on this file since 54883 was 50721, checked in by vboxsync, 11 years ago

Updated USB configuration.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.3 KB
Line 
1/* $Id: USBControllerImpl.cpp 50721 2014-03-06 21:40:39Z 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_XHCI))
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// Wrapped IUSBController properties
237/////////////////////////////////////////////////////////////////////////////
238HRESULT USBController::getName(com::Utf8Str &aName)
239{
240 /* strName is constant during life time, no need to lock */
241 aName = m->bd->strName;
242
243 return S_OK;
244}
245
246HRESULT USBController::getType(USBControllerType_T *aType)
247{
248 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
249
250 *aType = m->bd->enmType;
251
252 return S_OK;
253}
254
255HRESULT USBController::getUSBStandard(USHORT *aUSBStandard)
256{
257 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
258
259 switch (m->bd->enmType)
260 {
261 case USBControllerType_OHCI:
262 *aUSBStandard = 0x0101;
263 break;
264 case USBControllerType_EHCI:
265 *aUSBStandard = 0x0200;
266 break;
267 case USBControllerType_XHCI:
268 *aUSBStandard = 0x0200;
269 break;
270 default:
271 AssertMsgFailedReturn(("Invalid controller type %d\n", m->bd->enmType),
272 E_FAIL);
273 }
274
275 return S_OK;
276}
277
278// public methods only for internal purposes
279/////////////////////////////////////////////////////////////////////////////
280
281/** @note Locks objects for writing! */
282void USBController::i_rollback()
283{
284 AutoCaller autoCaller(this);
285 AssertComRCReturnVoid(autoCaller.rc());
286
287 /* we need the machine state */
288 AutoAnyStateDependency adep(m->pParent);
289 AssertComRCReturnVoid(adep.rc());
290
291 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
292
293 m->bd.rollback();
294}
295
296/**
297 * @note Locks this object for writing, together with the peer object (also
298 * for writing) if there is one.
299 */
300void USBController::i_commit()
301{
302 /* sanity */
303 AutoCaller autoCaller(this);
304 AssertComRCReturnVoid(autoCaller.rc());
305
306 /* sanity too */
307 AutoCaller peerCaller(m->pPeer);
308 AssertComRCReturnVoid(peerCaller.rc());
309
310 /* lock both for writing since we modify both (mPeer is "master" so locked
311 * first) */
312 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
313
314 if (m->bd.isBackedUp())
315 {
316 m->bd.commit();
317 if (m->pPeer)
318 {
319 /* attach new data to the peer and reshare it */
320 AutoWriteLock peerlock(m->pPeer COMMA_LOCKVAL_SRC_POS);
321 m->pPeer->m->bd.attach(m->bd);
322 }
323 }
324}
325
326/**
327 * @note Locks this object for writing, together with the peer object
328 * represented by @a aThat (locked for reading).
329 */
330void USBController::i_copyFrom(USBController *aThat)
331{
332 AssertReturnVoid(aThat != NULL);
333
334 /* sanity */
335 AutoCaller autoCaller(this);
336 AssertComRCReturnVoid(autoCaller.rc());
337
338 /* sanity too */
339 AutoCaller thatCaller(aThat);
340 AssertComRCReturnVoid(thatCaller.rc());
341
342 /* even more sanity */
343 AutoAnyStateDependency adep(m->pParent);
344 AssertComRCReturnVoid(adep.rc());
345 /* Machine::copyFrom() may not be called when the VM is running */
346 AssertReturnVoid(!Global::IsOnline(adep.machineState()));
347
348 /* peer is not modified, lock it for reading (aThat is "master" so locked
349 * first) */
350 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
351 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
352
353 /* this will back up current data */
354 m->bd.assignCopy(aThat->m->bd);
355}
356
357/**
358 * Cancels sharing (if any) by making an independent copy of data.
359 * This operation also resets this object's peer to NULL.
360 *
361 * @note Locks this object for writing, together with the peer object
362 * represented by @a aThat (locked for reading).
363 */
364void USBController::i_unshare()
365{
366 /* sanity */
367 AutoCaller autoCaller(this);
368 AssertComRCReturnVoid (autoCaller.rc());
369
370 /* sanity too */
371 AutoCaller peerCaller (m->pPeer);
372 AssertComRCReturnVoid (peerCaller.rc());
373
374 /* peer is not modified, lock it for reading (m->pPeer is "master" so locked
375 * first) */
376 AutoReadLock rl(m->pPeer COMMA_LOCKVAL_SRC_POS);
377 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
378
379 if (m->bd.isShared())
380 {
381 if (!m->bd.isBackedUp())
382 m->bd.backup();
383
384 m->bd.commit();
385 }
386
387 unconst(m->pPeer) = NULL;
388}
389
390const Utf8Str &USBController::i_getName() const
391{
392 return m->bd->strName;
393}
394
395const USBControllerType_T &USBController::i_getControllerType() const
396{
397 return m->bd->enmType;
398}
399
400ComObjPtr<USBController> USBController::i_getPeer()
401{
402 return m->pPeer;
403}
404
405/////////////////////////////////////////////////////////////////////////////
406/* 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