VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/ParallelPortImpl.cpp@ 53517

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

6813 - MachineImpl use of server side wrappers + misc mods on other classes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1/* $Id: ParallelPortImpl.cpp 51498 2014-06-02 18:53:08Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2014 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 "ParallelPortImpl.h"
19#include "MachineImpl.h"
20#include "VirtualBoxImpl.h"
21
22#include <iprt/string.h>
23#include <iprt/cpp/utils.h>
24
25#include <VBox/settings.h>
26
27#include "AutoStateDep.h"
28#include "AutoCaller.h"
29#include "Logging.h"
30
31////////////////////////////////////////////////////////////////////////////////
32//
33// ParallelPort private data definition
34//
35////////////////////////////////////////////////////////////////////////////////
36
37struct ParallelPort::Data
38{
39 Data()
40 : fModified(false),
41 pMachine(NULL)
42 { }
43
44 bool fModified;
45
46 Machine * const pMachine;
47 const ComObjPtr<ParallelPort> pPeer;
48
49 Backupable<settings::ParallelPort> bd;
50};
51
52// constructor / destructor
53/////////////////////////////////////////////////////////////////////////////
54DEFINE_EMPTY_CTOR_DTOR(ParallelPort)
55
56HRESULT ParallelPort::FinalConstruct()
57{
58 return BaseFinalConstruct();
59}
60
61void ParallelPort::FinalRelease()
62{
63 uninit();
64 BaseFinalRelease();
65}
66
67// public initializer/uninitializer for internal purposes only
68/////////////////////////////////////////////////////////////////////////////
69
70/**
71 * Initializes the Parallel Port object.
72 *
73 * @param aParent Handle of the parent object.
74 */
75HRESULT ParallelPort::init(Machine *aParent, ULONG aSlot)
76{
77 LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
78
79 ComAssertRet(aParent, E_INVALIDARG);
80
81 /* Enclose the state transition NotReady->InInit->Ready */
82 AutoInitSpan autoInitSpan(this);
83 AssertReturn(autoInitSpan.isOk(), E_FAIL);
84
85 m = new Data;
86
87 unconst(m->pMachine) = aParent;
88 /* m->pPeer is left null */
89
90 m->bd.allocate();
91
92 /* initialize data */
93 m->bd->ulSlot = aSlot;
94
95 /* Confirm a successful initialization */
96 autoInitSpan.setSucceeded();
97
98 return S_OK;
99}
100
101/**
102 * Initializes the Parallel Port object given another serial port object
103 * (a kind of copy constructor). This object shares data with
104 * the object passed as an argument.
105 *
106 * @note This object must be destroyed before the original object
107 * it shares data with is destroyed.
108 *
109 * @note Locks @a aThat object for reading.
110 */
111HRESULT ParallelPort::init(Machine *aParent, ParallelPort *aThat)
112{
113 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
114
115 ComAssertRet(aParent && aThat, E_INVALIDARG);
116
117 /* Enclose the state transition NotReady->InInit->Ready */
118 AutoInitSpan autoInitSpan(this);
119 AssertReturn(autoInitSpan.isOk(), E_FAIL);
120
121 m = new Data;
122
123 unconst(m->pMachine) = aParent;
124 unconst(m->pPeer) = aThat;
125
126 AutoCaller thatCaller (aThat);
127 AssertComRCReturnRC(thatCaller.rc());
128
129 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
130 m->bd.share(aThat->m->bd);
131
132 /* Confirm a successful initialization */
133 autoInitSpan.setSucceeded();
134
135 return S_OK;
136}
137
138/**
139 * Initializes the guest object given another guest object
140 * (a kind of copy constructor). This object makes a private copy of data
141 * of the original object passed as an argument.
142 *
143 * @note Locks @a aThat object for reading.
144 */
145HRESULT ParallelPort::initCopy(Machine *aParent, ParallelPort *aThat)
146{
147 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
148
149 ComAssertRet(aParent && aThat, E_INVALIDARG);
150
151 /* Enclose the state transition NotReady->InInit->Ready */
152 AutoInitSpan autoInitSpan(this);
153 AssertReturn(autoInitSpan.isOk(), E_FAIL);
154
155 m = new Data;
156
157 unconst(m->pMachine) = aParent;
158 /* m->pPeer is left null */
159
160 AutoCaller thatCaller(aThat);
161 AssertComRCReturnRC(thatCaller.rc());
162
163 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
164 m->bd.attachCopy(aThat->m->bd);
165
166 /* Confirm a successful initialization */
167 autoInitSpan.setSucceeded();
168
169 return S_OK;
170}
171
172/**
173 * Uninitializes the instance and sets the ready flag to FALSE.
174 * Called either from FinalRelease() or by the parent when it gets destroyed.
175 */
176void ParallelPort::uninit()
177{
178 LogFlowThisFunc(("\n"));
179
180 /* Enclose the state transition Ready->InUninit->NotReady */
181 AutoUninitSpan autoUninitSpan(this);
182 if (autoUninitSpan.uninitDone())
183 return;
184
185 m->bd.free();
186
187 unconst(m->pPeer) = NULL;
188 unconst(m->pMachine) = NULL;
189
190 delete m;
191 m = NULL;
192}
193
194// IParallelPort properties
195/////////////////////////////////////////////////////////////////////////////
196
197HRESULT ParallelPort::getEnabled(BOOL *aEnabled)
198{
199 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
200
201 *aEnabled = m->bd->fEnabled;
202
203 return S_OK;
204}
205
206HRESULT ParallelPort::setEnabled(BOOL aEnabled)
207{
208 LogFlowThisFunc(("aEnabled=%RTbool\n", aEnabled));
209 /* the machine needs to be mutable */
210 AutoMutableStateDependency adep(m->pMachine);
211 if (FAILED(adep.rc())) return adep.rc();
212
213 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
214
215 if (m->bd->fEnabled != !!aEnabled)
216 {
217 if (aEnabled &&
218 m->bd->strPath.isEmpty())
219 return setError(E_INVALIDARG,
220 tr("Cannot enable the parallel port %d because the port path is empty or null"),
221 m->bd->ulSlot);
222
223 m->bd.backup();
224 m->bd->fEnabled = !!aEnabled;
225
226 m->fModified = true;
227 // leave the lock before informing callbacks
228 alock.release();
229
230 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
231 m->pMachine->i_setModified(Machine::IsModified_ParallelPorts);
232 mlock.release();
233
234 m->pMachine->i_onParallelPortChange(this);
235 }
236
237 return S_OK;
238}
239
240HRESULT ParallelPort::getSlot(ULONG *aSlot)
241{
242 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
243
244 *aSlot = m->bd->ulSlot;
245
246 return S_OK;
247}
248
249HRESULT ParallelPort::getIRQ(ULONG *aIRQ)
250{
251 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
252
253 *aIRQ = m->bd->ulIRQ;
254
255 return S_OK;
256}
257
258HRESULT ParallelPort::setIRQ(ULONG aIRQ)
259{
260 /* check IRQ limits
261 * (when changing this, make sure it corresponds to XML schema */
262 if (aIRQ > 255)
263 return setError(E_INVALIDARG,
264 tr("Invalid IRQ number of the parallel port %d: %lu (must be in range [0, %lu])"),
265 m->bd->ulSlot, aIRQ, 255);
266
267 /* the machine needs to be mutable */
268 AutoMutableStateDependency adep(m->pMachine);
269 if (FAILED(adep.rc())) return adep.rc();
270
271 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
272
273 if (m->bd->ulIRQ != aIRQ)
274 {
275 m->bd.backup();
276 m->bd->ulIRQ = aIRQ;
277
278 m->fModified = true;
279 // leave the lock before informing callbacks
280 alock.release();
281
282 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
283 m->pMachine->i_setModified(Machine::IsModified_ParallelPorts);
284 mlock.release();
285
286 m->pMachine->i_onParallelPortChange(this);
287 }
288
289 return S_OK;
290}
291
292HRESULT ParallelPort::getIOBase(ULONG *aIOBase)
293{
294 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
295
296 *aIOBase = m->bd->ulIOBase;
297
298 return S_OK;
299}
300
301HRESULT ParallelPort::setIOBase(ULONG aIOBase)
302{
303 /* check IOBase limits
304 * (when changing this, make sure it corresponds to XML schema */
305 if (aIOBase > 0xFFFF)
306 return setError(E_INVALIDARG,
307 tr("Invalid I/O port base address of the parallel port %d: %lu (must be in range [0, 0x%X])"),
308 m->bd->ulSlot, aIOBase, 0, 0xFFFF);
309
310 /* the machine needs to be mutable */
311 AutoMutableStateDependency adep(m->pMachine);
312 if (FAILED(adep.rc())) return adep.rc();
313
314 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
315
316 if (m->bd->ulIOBase != aIOBase)
317 {
318 m->bd.backup();
319 m->bd->ulIOBase = aIOBase;
320
321 m->fModified = true;
322 // leave the lock before informing callbacks
323 alock.release();
324
325 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
326 m->pMachine->i_setModified(Machine::IsModified_ParallelPorts);
327 mlock.release();
328
329 m->pMachine->i_onParallelPortChange(this);
330 }
331
332 return S_OK;
333}
334
335
336HRESULT ParallelPort::getPath(com::Utf8Str &aPath)
337{
338 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
339 aPath = m->bd->strPath;
340 return S_OK;
341}
342
343
344HRESULT ParallelPort::setPath(const com::Utf8Str &aPath)
345{
346 /* the machine needs to be mutable */
347 AutoMutableStateDependency adep(m->pMachine);
348 if (FAILED(adep.rc())) return adep.rc();
349
350 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
351
352 if (aPath != m->bd->strPath)
353 {
354 HRESULT rc = i_checkSetPath(aPath);
355 if (FAILED(rc)) return rc;
356
357 m->bd.backup();
358 m->bd->strPath = aPath;
359
360 m->fModified = true;
361
362 // leave the lock before informing callbacks
363 alock.release();
364
365 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
366 m->pMachine->i_setModified(Machine::IsModified_ParallelPorts);
367 mlock.release();
368
369 return m->pMachine->i_onParallelPortChange(this);
370 }
371
372 return S_OK;
373}
374
375// public methods only for internal purposes
376////////////////////////////////////////////////////////////////////////////////
377
378/**
379 * Loads settings from the given port node.
380 * May be called once right after this object creation.
381 *
382 * @param aPortNode <Port> node.
383 *
384 * @note Locks this object for writing.
385 */
386HRESULT ParallelPort::i_loadSettings(const settings::ParallelPort &data)
387{
388 AutoCaller autoCaller(this);
389 AssertComRCReturnRC(autoCaller.rc());
390
391 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
392
393 // simply copy
394 *m->bd.data() = data;
395
396 return S_OK;
397}
398
399/**
400 * Saves settings to the given port node.
401 *
402 * Note that the given Port node is completely empty on input.
403 *
404 * @param <data> node.
405 *
406 * @note Locks this object for reading.
407 */
408HRESULT ParallelPort::i_saveSettings(settings::ParallelPort &data)
409{
410 AutoCaller autoCaller(this);
411 AssertComRCReturnRC(autoCaller.rc());
412
413 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
414
415 // simply copy
416 data = *m->bd.data();
417
418 return S_OK;
419}
420
421/**
422 * Returns true if any setter method has modified settings of this instance.
423 * @return
424 */
425bool ParallelPort::i_isModified()
426{
427 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
428 return m->fModified;
429}
430
431/**
432 * @note Locks this object for writing.
433 */
434void ParallelPort::i_rollback()
435{
436 /* sanity */
437 AutoCaller autoCaller(this);
438 AssertComRCReturnVoid(autoCaller.rc());
439
440 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
441
442 m->bd.rollback();
443}
444
445/**
446 * @note Locks this object for writing, together with the peer object (also
447 * for writing) if there is one.
448 */
449void ParallelPort::i_commit()
450{
451 /* sanity */
452 AutoCaller autoCaller(this);
453 AssertComRCReturnVoid (autoCaller.rc());
454
455 /* sanity too */
456 AutoCaller peerCaller (m->pPeer);
457 AssertComRCReturnVoid (peerCaller.rc());
458
459 /* lock both for writing since we modify both (m->pPeer is "master" so locked
460 * first) */
461 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
462
463 if (m->bd.isBackedUp())
464 {
465 m->bd.commit();
466 if (m->pPeer)
467 {
468 /* attach new data to the peer and reshare it */
469 m->pPeer->m->bd.attach(m->bd);
470 }
471 }
472}
473
474/**
475 * @note Locks this object for writing, together with the peer object
476 * represented by @a aThat (locked for reading).
477 */
478void ParallelPort::i_copyFrom(ParallelPort *aThat)
479{
480 AssertReturnVoid (aThat != NULL);
481
482 /* sanity */
483 AutoCaller autoCaller(this);
484 AssertComRCReturnVoid (autoCaller.rc());
485
486 /* sanity too */
487 AutoCaller thatCaller (aThat);
488 AssertComRCReturnVoid (thatCaller.rc());
489
490 /* peer is not modified, lock it for reading (aThat is "master" so locked
491 * first) */
492 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
493 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
494
495 /* this will back up current data */
496 m->bd.assignCopy(aThat->m->bd);
497}
498
499/**
500 * Validates COMSETTER(Path) arguments.
501 */
502HRESULT ParallelPort::i_checkSetPath(const Utf8Str &str)
503{
504 AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
505
506 if ( m->bd->fEnabled
507 && str.isEmpty()
508 )
509 return setError(E_INVALIDARG,
510 tr("Path of the parallel port %d may not be empty or null "
511 "when the port is enabled"),
512 m->bd->ulSlot);
513
514 return S_OK;
515}
516
517
518/* 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