VirtualBox

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

Last change on this file since 3942 was 3653, checked in by vboxsync, 17 years ago

Parallel port support. Contributed by: Alexander Eichner

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.9 KB
Line 
1/* $Id: ParallelPortImpl.cpp 3653 2007-07-16 16:03:07Z vboxsync $ */
2/** @file
3 * VirtualBox COM class implementation
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
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// constructor / destructor
31/////////////////////////////////////////////////////////////////////////////
32
33DEFINE_EMPTY_CTOR_DTOR (ParallelPort)
34
35HRESULT ParallelPort::FinalConstruct()
36{
37 return S_OK;
38}
39
40void ParallelPort::FinalRelease()
41{
42 uninit();
43}
44
45// public initializer/uninitializer for internal purposes only
46/////////////////////////////////////////////////////////////////////////////
47
48/**
49 * Initializes the Parallel Port object.
50 *
51 * @param aParent Handle of the parent object.
52 */
53HRESULT ParallelPort::init (Machine *aParent, ULONG aSlot)
54{
55 LogFlowThisFunc (("aParent=%p, aSlot=%d\n", aParent, aSlot));
56
57 ComAssertRet (aParent, E_INVALIDARG);
58
59 /* Enclose the state transition NotReady->InInit->Ready */
60 AutoInitSpan autoInitSpan (this);
61 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
62
63 unconst (mParent) = aParent;
64 /* mPeer is left null */
65
66 mData.allocate();
67
68 /* initialize data */
69 mData->mSlot = aSlot;
70
71 /* Confirm a successful initialization */
72 autoInitSpan.setSucceeded();
73
74 return S_OK;
75}
76
77/**
78 * Initializes the Parallel Port object given another serial port object
79 * (a kind of copy constructor). This object shares data with
80 * the object passed as an argument.
81 *
82 * @note This object must be destroyed before the original object
83 * it shares data with is destroyed.
84 *
85 * @note Locks @a aThat object for reading.
86 */
87HRESULT ParallelPort::init (Machine *aParent, ParallelPort *aThat)
88{
89 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
90
91 ComAssertRet (aParent && aThat, E_INVALIDARG);
92
93 /* Enclose the state transition NotReady->InInit->Ready */
94 AutoInitSpan autoInitSpan (this);
95 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
96
97 unconst (mParent) = aParent;
98 unconst (mPeer) = aThat;
99
100 AutoCaller thatCaller (aThat);
101 AssertComRCReturnRC (thatCaller.rc());
102
103 AutoReaderLock thatLock (aThat);
104 mData.share (aThat->mData);
105
106 /* Confirm a successful initialization */
107 autoInitSpan.setSucceeded();
108
109 return S_OK;
110}
111
112/**
113 * Initializes the guest object given another guest object
114 * (a kind of copy constructor). This object makes a private copy of data
115 * of the original object passed as an argument.
116 *
117 * @note Locks @a aThat object for reading.
118 */
119HRESULT ParallelPort::initCopy (Machine *aParent, ParallelPort *aThat)
120{
121 LogFlowThisFunc (("aParent=%p, aThat=%p\n", aParent, aThat));
122
123 ComAssertRet (aParent && aThat, E_INVALIDARG);
124
125 /* Enclose the state transition NotReady->InInit->Ready */
126 AutoInitSpan autoInitSpan (this);
127 AssertReturn (autoInitSpan.isOk(), E_UNEXPECTED);
128
129 unconst (mParent) = aParent;
130 /* mPeer is left null */
131
132 AutoCaller thatCaller (aThat);
133 AssertComRCReturnRC (thatCaller.rc());
134
135 AutoReaderLock thatLock (aThat);
136 mData.attachCopy (aThat->mData);
137
138 /* Confirm a successful initialization */
139 autoInitSpan.setSucceeded();
140
141 return S_OK;
142}
143
144/**
145 * Uninitializes the instance and sets the ready flag to FALSE.
146 * Called either from FinalRelease() or by the parent when it gets destroyed.
147 */
148void ParallelPort::uninit()
149{
150 LogFlowThisFunc (("\n"));
151
152 /* Enclose the state transition Ready->InUninit->NotReady */
153 AutoUninitSpan autoUninitSpan (this);
154 if (autoUninitSpan.uninitDone())
155 return;
156
157 mData.free();
158
159 unconst (mPeer).setNull();
160 unconst (mParent).setNull();
161}
162
163// public methods only for internal purposes
164////////////////////////////////////////////////////////////////////////////////
165
166/**
167 * @note Locks this object for writing.
168 */
169bool ParallelPort::rollback()
170{
171 /* sanity */
172 AutoCaller autoCaller (this);
173 AssertComRCReturn (autoCaller.rc(), false);
174
175 AutoLock alock (this);
176
177 bool changed = false;
178
179 if (mData.isBackedUp())
180 {
181 /* we need to check all data to see whether anything will be changed
182 * after rollback */
183 changed = mData.hasActualChanges();
184 mData.rollback();
185 }
186
187 return changed;
188}
189
190/**
191 * @note Locks this object for writing, together with the peer object (also
192 * for writing) if there is one.
193 */
194void ParallelPort::commit()
195{
196 /* sanity */
197 AutoCaller autoCaller (this);
198 AssertComRCReturnVoid (autoCaller.rc());
199
200 /* sanity too */
201 AutoCaller thatCaller (mPeer);
202 AssertComRCReturnVoid (thatCaller.rc());
203
204 /* lock both for writing since we modify both */
205 AutoMultiLock <2> alock (this->wlock(), AutoLock::maybeWlock (mPeer));
206
207 if (mData.isBackedUp())
208 {
209 mData.commit();
210 if (mPeer)
211 {
212 /* attach new data to the peer and reshare it */
213 mPeer->mData.attach (mData);
214 }
215 }
216}
217
218/**
219 * @note Locks this object for writing, together with the peer object
220 * represented by @a aThat (locked for reading).
221 */
222void ParallelPort::copyFrom (ParallelPort *aThat)
223{
224 AssertReturnVoid (aThat != NULL);
225
226 /* sanity */
227 AutoCaller autoCaller (this);
228 AssertComRCReturnVoid (autoCaller.rc());
229
230 /* sanity too */
231 AutoCaller thatCaller (mPeer);
232 AssertComRCReturnVoid (thatCaller.rc());
233
234 /* peer is not modified, lock it for reading */
235 AutoMultiLock <2> alock (this->wlock(), aThat->rlock());
236
237 /* this will back up current data */
238 mData.assignCopy (aThat->mData);
239}
240
241HRESULT ParallelPort::loadSettings (CFGNODE aNode, ULONG aSlot)
242{
243 LogFlowThisFunc (("aMachine=%p\n", aNode));
244
245 AssertReturn (aNode, E_FAIL);
246
247 AutoCaller autoCaller (this);
248 AssertComRCReturnRC (autoCaller.rc());
249
250 AutoLock alock (this);
251
252 CFGNODE portNode = NULL;
253 CFGLDRGetChildNode (aNode, "Port", aSlot, &portNode);
254
255 /* slot number (required) */
256 /* slot unicity is guaranteed by XML Schema */
257 uint32_t uSlot = 0;
258 CFGLDRQueryUInt32 (portNode, "slot", &uSlot);
259 /* enabled (required) */
260 bool fEnabled = false;
261 CFGLDRQueryBool (portNode, "enabled", &fEnabled);
262 /* I/O base (required) */
263 uint32_t uIOBase;
264 CFGLDRQueryUInt32 (portNode, "IOBase", &uIOBase);
265 /* IRQ (required) */
266 uint32_t uIRQ;
267 CFGLDRQueryUInt32 (portNode, "IRQ", &uIRQ);
268 /* device path (required) */
269 Bstr DevicePath;
270 CFGLDRQueryBSTR (portNode, "DevicePath", DevicePath.asOutParam());
271
272 mData->mEnabled = fEnabled;
273 mData->mSlot = uSlot;
274 mData->mIOBase = uIOBase;
275 mData->mIRQ = uIRQ;
276 mData->mDevicePath = DevicePath;
277
278 return S_OK;
279}
280
281HRESULT ParallelPort::saveSettings (CFGNODE aNode)
282{
283 AssertReturn (aNode, E_FAIL);
284
285 AutoCaller autoCaller (this);
286 CheckComRCReturnRC (autoCaller.rc());
287
288 AutoReaderLock alock (this);
289
290 CFGNODE portNode = 0;
291 int vrc = CFGLDRAppendChildNode (aNode, "Port", &portNode);
292 ComAssertRCRet (vrc, E_FAIL);
293
294 CFGLDRSetUInt32 (portNode, "slot", mData->mSlot);
295 CFGLDRSetBool (portNode, "enabled", !!mData->mEnabled);
296 CFGLDRSetUInt32 (portNode, "IOBase", mData->mIOBase);
297 CFGLDRSetUInt32 (portNode, "IRQ", mData->mIRQ);
298 CFGLDRSetBSTR (portNode, "DevicePath", mData->mDevicePath);
299
300 return S_OK;
301}
302
303// IParallelPort properties
304/////////////////////////////////////////////////////////////////////////////
305
306STDMETHODIMP ParallelPort::COMGETTER(Enabled) (BOOL *aEnabled)
307{
308 if (!aEnabled)
309 return E_POINTER;
310
311 AutoCaller autoCaller (this);
312 CheckComRCReturnRC (autoCaller.rc());
313
314 AutoReaderLock alock (this);
315
316 *aEnabled = mData->mEnabled;
317
318 return S_OK;
319}
320
321STDMETHODIMP ParallelPort::COMSETTER(Enabled) (BOOL aEnabled)
322{
323 LogFlowThisFunc (("aEnabled=%RTbool\n", aEnabled));
324
325 AutoCaller autoCaller (this);
326 CheckComRCReturnRC (autoCaller.rc());
327
328 /* the machine needs to be mutable */
329 Machine::AutoMutableStateDependency adep (mParent);
330 CheckComRCReturnRC (adep.rc());
331
332 AutoLock alock (this);
333
334 if (mData->mEnabled != aEnabled)
335 {
336 mData.backup();
337 mData->mEnabled = aEnabled;
338
339 /* leave the lock before informing callbacks */
340 alock.unlock();
341
342 mParent->onParallelPortChange (this);
343 }
344
345 return S_OK;
346}
347
348STDMETHODIMP ParallelPort::COMGETTER(Slot) (ULONG *aSlot)
349{
350 if (!aSlot)
351 return E_POINTER;
352
353 AutoCaller autoCaller (this);
354 CheckComRCReturnRC (autoCaller.rc());
355
356 AutoReaderLock alock (this);
357
358 *aSlot = mData->mSlot;
359
360 return S_OK;
361}
362
363STDMETHODIMP ParallelPort::COMGETTER(IRQ) (ULONG *aIRQ)
364{
365 if (!aIRQ)
366 return E_POINTER;
367
368 AutoCaller autoCaller (this);
369 CheckComRCReturnRC (autoCaller.rc());
370
371 AutoReaderLock alock (this);
372
373 *aIRQ = mData->mIRQ;
374
375 return S_OK;
376}
377
378STDMETHODIMP ParallelPort::COMSETTER(IRQ)(ULONG aIRQ)
379{
380 AutoCaller autoCaller (this);
381 CheckComRCReturnRC (autoCaller.rc());
382
383 /* the machine needs to be mutable */
384 Machine::AutoMutableStateDependency adep (mParent);
385 CheckComRCReturnRC (adep.rc());
386
387 AutoLock alock (this);
388
389 HRESULT rc = S_OK;
390 bool emitChangeEvent = false;
391
392 if (mData->mIRQ != aIRQ)
393 {
394 mData.backup();
395 mData->mIRQ = aIRQ;
396 emitChangeEvent = true;
397 }
398
399 if (emitChangeEvent)
400 {
401 /* leave the lock before informing callbacks */
402 alock.unlock();
403
404 mParent->onParallelPortChange (this);
405 }
406
407 return rc;
408}
409
410STDMETHODIMP ParallelPort::COMGETTER(IOBase) (ULONG *aIOBase)
411{
412 if (!aIOBase)
413 return E_POINTER;
414
415 AutoCaller autoCaller (this);
416 CheckComRCReturnRC (autoCaller.rc());
417
418 AutoReaderLock alock (this);
419
420 *aIOBase = mData->mIOBase;
421
422 return S_OK;
423}
424
425STDMETHODIMP ParallelPort::COMSETTER(IOBase)(ULONG aIOBase)
426{
427 AutoCaller autoCaller (this);
428 CheckComRCReturnRC (autoCaller.rc());
429
430 /* the machine needs to be mutable */
431 Machine::AutoMutableStateDependency adep (mParent);
432 CheckComRCReturnRC (adep.rc());
433
434 AutoLock alock (this);
435
436 HRESULT rc = S_OK;
437 bool emitChangeEvent = false;
438
439 if (mData->mIOBase != aIOBase)
440 {
441 mData.backup();
442 mData->mIOBase = aIOBase;
443 emitChangeEvent = true;
444 }
445
446 if (emitChangeEvent)
447 {
448 /* leave the lock before informing callbacks */
449 alock.unlock();
450
451 mParent->onParallelPortChange (this);
452 }
453
454 return rc;
455}
456
457STDMETHODIMP ParallelPort::COMGETTER(DevicePath) (BSTR *aDevicePath)
458{
459 if (!aDevicePath)
460 return E_POINTER;
461
462 AutoCaller autoCaller (this);
463 CheckComRCReturnRC (autoCaller.rc());
464
465 AutoReaderLock alock (this);
466
467 mData->mDevicePath.cloneTo (aDevicePath);
468
469 return S_OK;
470}
471
472STDMETHODIMP ParallelPort::COMSETTER(DevicePath) (INPTR BSTR aDevicePath)
473{
474 if (!aDevicePath || *aDevicePath == 0)
475 return E_INVALIDARG;
476
477 AutoCaller autoCaller (this);
478 CheckComRCReturnRC (autoCaller.rc());
479
480 /* the machine needs to be mutable */
481 Machine::AutoMutableStateDependency adep (mParent);
482 CheckComRCReturnRC (adep.rc());
483
484 AutoLock alock (this);
485
486 if (mData->mDevicePath != aDevicePath)
487 {
488 mData.backup();
489 mData->mDevicePath = aDevicePath;
490
491 /* leave the lock before informing callbacks */
492 alock.unlock();
493
494 return mParent->onParallelPortChange (this);
495 }
496
497 return S_OK;
498}
499
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