VirtualBox

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

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

Main: cleanup: get rid of VirtualBoxBaseProto, move AutoCaller*/*Span* classes out of VirtualBoxBaseProto class scope and into separate header; move CombinedProgress into separate header (it's only used by Console any more)

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