VirtualBox

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

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

misc compiler warning fixes, comment typos and other minor cleanups

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