VirtualBox

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

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

6813 - User server side API wrapper code in all interfaces.. stage 4 rev 1

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