VirtualBox

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

Last change on this file since 60952 was 59926, checked in by vboxsync, 9 years ago

Main/Machine+SerialPort+ParallelPort: only write the non-default serial/parallel port config lines to the settings file, plus some other minor cleanups, including whitespace

  • 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 59926 2016-03-04 14:01:54Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2016 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 m->bd.backup();
218 m->bd->fEnabled = !!aEnabled;
219
220 m->fModified = true;
221 // leave the lock before informing callbacks
222 alock.release();
223
224 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
225 m->pMachine->i_setModified(Machine::IsModified_ParallelPorts);
226 mlock.release();
227
228 m->pMachine->i_onParallelPortChange(this);
229 }
230
231 return S_OK;
232}
233
234HRESULT ParallelPort::getSlot(ULONG *aSlot)
235{
236 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
237
238 *aSlot = m->bd->ulSlot;
239
240 return S_OK;
241}
242
243HRESULT ParallelPort::getIRQ(ULONG *aIRQ)
244{
245 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
246
247 *aIRQ = m->bd->ulIRQ;
248
249 return S_OK;
250}
251
252HRESULT ParallelPort::setIRQ(ULONG aIRQ)
253{
254 /* check IRQ limits
255 * (when changing this, make sure it corresponds to XML schema */
256 if (aIRQ > 255)
257 return setError(E_INVALIDARG,
258 tr("Invalid IRQ number of the parallel port %d: %lu (must be in range [0, %lu])"),
259 m->bd->ulSlot, aIRQ, 255);
260
261 /* the machine needs to be mutable */
262 AutoMutableStateDependency adep(m->pMachine);
263 if (FAILED(adep.rc())) return adep.rc();
264
265 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
266
267 if (m->bd->ulIRQ != aIRQ)
268 {
269 m->bd.backup();
270 m->bd->ulIRQ = aIRQ;
271
272 m->fModified = true;
273 // leave the lock before informing callbacks
274 alock.release();
275
276 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
277 m->pMachine->i_setModified(Machine::IsModified_ParallelPorts);
278 mlock.release();
279
280 m->pMachine->i_onParallelPortChange(this);
281 }
282
283 return S_OK;
284}
285
286HRESULT ParallelPort::getIOBase(ULONG *aIOBase)
287{
288 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
289
290 *aIOBase = m->bd->ulIOBase;
291
292 return S_OK;
293}
294
295HRESULT ParallelPort::setIOBase(ULONG aIOBase)
296{
297 /* check IOBase limits
298 * (when changing this, make sure it corresponds to XML schema */
299 if (aIOBase > 0xFFFF)
300 return setError(E_INVALIDARG,
301 tr("Invalid I/O port base address of the parallel port %d: %lu (must be in range [0, 0x%X])"),
302 m->bd->ulSlot, aIOBase, 0, 0xFFFF);
303
304 /* the machine needs to be mutable */
305 AutoMutableStateDependency adep(m->pMachine);
306 if (FAILED(adep.rc())) return adep.rc();
307
308 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
309
310 if (m->bd->ulIOBase != aIOBase)
311 {
312 m->bd.backup();
313 m->bd->ulIOBase = aIOBase;
314
315 m->fModified = true;
316 // leave the lock before informing callbacks
317 alock.release();
318
319 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
320 m->pMachine->i_setModified(Machine::IsModified_ParallelPorts);
321 mlock.release();
322
323 m->pMachine->i_onParallelPortChange(this);
324 }
325
326 return S_OK;
327}
328
329
330HRESULT ParallelPort::getPath(com::Utf8Str &aPath)
331{
332 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
333 aPath = m->bd->strPath;
334 return S_OK;
335}
336
337
338HRESULT ParallelPort::setPath(const com::Utf8Str &aPath)
339{
340 /* the machine needs to be mutable */
341 AutoMutableOrSavedStateDependency adep(m->pMachine);
342 if (FAILED(adep.rc())) return adep.rc();
343
344 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
345
346 if (aPath != m->bd->strPath)
347 {
348 m->bd.backup();
349 m->bd->strPath = aPath;
350
351 m->fModified = true;
352
353 // leave the lock before informing callbacks
354 alock.release();
355
356 AutoWriteLock mlock(m->pMachine COMMA_LOCKVAL_SRC_POS);
357 m->pMachine->i_setModified(Machine::IsModified_ParallelPorts);
358 mlock.release();
359
360 return m->pMachine->i_onParallelPortChange(this);
361 }
362
363 return S_OK;
364}
365
366// public methods only for internal purposes
367////////////////////////////////////////////////////////////////////////////////
368
369/**
370 * Loads settings from the given port node.
371 * May be called once right after this object creation.
372 *
373 * @param aPortNode <Port> node.
374 *
375 * @note Locks this object for writing.
376 */
377HRESULT ParallelPort::i_loadSettings(const settings::ParallelPort &data)
378{
379 AutoCaller autoCaller(this);
380 AssertComRCReturnRC(autoCaller.rc());
381
382 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
383
384 // simply copy
385 *m->bd.data() = data;
386
387 return S_OK;
388}
389
390/**
391 * Saves settings to the given port node.
392 *
393 * Note that the given Port node is completely empty on input.
394 *
395 * @param <data> node.
396 *
397 * @note Locks this object for reading.
398 */
399HRESULT ParallelPort::i_saveSettings(settings::ParallelPort &data)
400{
401 AutoCaller autoCaller(this);
402 AssertComRCReturnRC(autoCaller.rc());
403
404 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
405
406 // simply copy
407 data = *m->bd.data();
408
409 return S_OK;
410}
411
412/**
413 * Returns true if any setter method has modified settings of this instance.
414 * @return
415 */
416bool ParallelPort::i_isModified()
417{
418 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
419 return m->fModified;
420}
421
422/**
423 * @note Locks this object for writing.
424 */
425void ParallelPort::i_rollback()
426{
427 /* sanity */
428 AutoCaller autoCaller(this);
429 AssertComRCReturnVoid(autoCaller.rc());
430
431 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
432
433 m->bd.rollback();
434}
435
436/**
437 * @note Locks this object for writing, together with the peer object (also
438 * for writing) if there is one.
439 */
440void ParallelPort::i_commit()
441{
442 /* sanity */
443 AutoCaller autoCaller(this);
444 AssertComRCReturnVoid(autoCaller.rc());
445
446 /* sanity too */
447 AutoCaller peerCaller(m->pPeer);
448 AssertComRCReturnVoid(peerCaller.rc());
449
450 /* lock both for writing since we modify both (m->pPeer is "master" so locked
451 * first) */
452 AutoMultiWriteLock2 alock(m->pPeer, this COMMA_LOCKVAL_SRC_POS);
453
454 if (m->bd.isBackedUp())
455 {
456 m->bd.commit();
457 if (m->pPeer)
458 {
459 /* attach new data to the peer and reshare it */
460 m->pPeer->m->bd.attach(m->bd);
461 }
462 }
463}
464
465/**
466 * @note Locks this object for writing, together with the peer object
467 * represented by @a aThat (locked for reading).
468 */
469void ParallelPort::i_copyFrom(ParallelPort *aThat)
470{
471 AssertReturnVoid(aThat != NULL);
472
473 /* sanity */
474 AutoCaller autoCaller(this);
475 AssertComRCReturnVoid(autoCaller.rc());
476
477 /* sanity too */
478 AutoCaller thatCaller(aThat);
479 AssertComRCReturnVoid(thatCaller.rc());
480
481 /* peer is not modified, lock it for reading (aThat is "master" so locked
482 * first) */
483 AutoReadLock rl(aThat COMMA_LOCKVAL_SRC_POS);
484 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
485
486 /* this will back up current data */
487 m->bd.assignCopy(aThat->m->bd);
488}
489
490/**
491 * Applies the defaults for the given parallel port.
492 */
493void ParallelPort::i_applyDefaults()
494{
495 /* sanity */
496 AutoCaller autoCaller(this);
497 AssertComRCReturnVoid(autoCaller.rc());
498
499 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
500
501 /* Set some more defaults based on the slot. */
502 switch (m->bd->ulSlot)
503 {
504 case 0:
505 {
506 m->bd->ulIOBase = 0x378;
507 m->bd->ulIRQ = 7;
508 break;
509 }
510 case 1:
511 {
512 m->bd->ulIOBase = 0x278;
513 m->bd->ulIRQ = 5;
514 break;
515 }
516 default:
517 AssertMsgFailed(("Parallel port slot %u exceeds limit\n", m->bd->ulSlot));
518 break;
519 }
520}
521
522bool ParallelPort::i_hasDefaults()
523{
524 /* sanity */
525 AutoCaller autoCaller(this);
526 AssertComRCReturn(autoCaller.rc(), true);
527
528 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
529
530 if (!m->bd->fEnabled)
531 {
532 /* Could be default, check the IO base and IRQ. */
533 switch (m->bd->ulSlot)
534 {
535 case 0:
536 if (m->bd->ulIOBase == 0x378 && m->bd->ulIRQ == 7)
537 return true;
538 break;
539 case 1:
540 if (m->bd->ulIOBase == 0x278 && m->bd->ulIRQ == 5)
541 return true;
542 break;
543 default:
544 AssertMsgFailed(("Parallel port slot %u exceeds limit\n", m->bd->ulSlot));
545 break;
546 }
547
548 /* Detect old-style defaults (0x378, irq 4) in any slot, they are still
549 * in place for many VMs created by old VirtualBox versions. */
550 if (m->bd->ulIOBase == 0x378 && m->bd->ulIRQ == 4)
551 return true;
552 }
553
554 return false;
555}
556
557/* 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