VirtualBox

source: vbox/trunk/src/VBox/Main/ParallelPortImpl.cpp@ 25202

Last change on this file since 25202 was 25202, checked in by vboxsync, 15 years ago

Main: make ParallelPort instance data private and make it use the XML settings struct for simplicity

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

© 2023 Oracle
ContactPrivacy policyTerms of Use