VirtualBox

source: vbox/trunk/src/VBox/Main/SerialPortImpl.cpp@ 3516

Last change on this file since 3516 was 3501, checked in by vboxsync, 17 years ago

export

File size: 12.7 KB
Line 
1/** @file
2 *
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 "SerialPortImpl.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 (SerialPort)
34
35HRESULT SerialPort::FinalConstruct()
36{
37 return S_OK;
38}
39
40void SerialPort::FinalRelease()
41{
42 uninit();
43}
44
45// public initializer/uninitializer for internal purposes only
46/////////////////////////////////////////////////////////////////////////////
47
48/**
49 * Initializes the Serial Port object.
50 *
51 * @param aParent Handle of the parent object.
52 */
53HRESULT SerialPort::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 Serial 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 SerialPort::init (Machine *aParent, SerialPort *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 SerialPort::initCopy (Machine *aParent, SerialPort *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 SerialPort::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 SerialPort::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 SerialPort::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 SerialPort::copyFrom (SerialPort *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 SerialPort::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 /* name of the pipe (required) */
269 Bstr pipe;
270 CFGLDRQueryBSTR (portNode, "pipe", pipe.asOutParam());
271 bool fServer = true;
272 CFGLDRQueryBool (portNode, "server", &fServer);
273
274 mData->mEnabled = fEnabled;
275 mData->mSlot = uSlot;
276 mData->mIobase = uIOBase;
277 mData->mIrq = uIRQ;
278 mData->mPipe = pipe;
279 mData->mServer = fServer;
280
281 return S_OK;
282}
283
284HRESULT SerialPort::saveSettings (CFGNODE aNode)
285{
286 AssertReturn (aNode, E_FAIL);
287
288 AutoCaller autoCaller (this);
289 CheckComRCReturnRC (autoCaller.rc());
290
291 AutoReaderLock alock (this);
292
293 CFGNODE portNode = 0;
294 int vrc = CFGLDRAppendChildNode (aNode, "Port", &portNode);
295 ComAssertRCRet (vrc, E_FAIL);
296
297 CFGLDRSetUInt32 (portNode, "slot", mData->mSlot);
298 CFGLDRSetBool (portNode, "enabled", !!mData->mEnabled);
299 CFGLDRSetUInt32 (portNode, "IOBase", mData->mIobase);
300 CFGLDRSetUInt32 (portNode, "IRQ", mData->mIrq);
301 CFGLDRSetBSTR (portNode, "pipe", mData->mPipe);
302 CFGLDRSetBool (portNode, "server", !!mData->mServer);
303
304 return S_OK;
305}
306
307// ISerialPort properties
308/////////////////////////////////////////////////////////////////////////////
309
310STDMETHODIMP SerialPort::COMGETTER(Enabled) (BOOL *aEnabled)
311{
312 if (!aEnabled)
313 return E_POINTER;
314
315 AutoCaller autoCaller (this);
316 CheckComRCReturnRC (autoCaller.rc());
317
318 AutoReaderLock alock (this);
319
320 *aEnabled = mData->mEnabled;
321
322 return S_OK;
323}
324
325STDMETHODIMP SerialPort::COMSETTER(Enabled) (BOOL aEnabled)
326{
327 LogFlowThisFunc (("aEnabled=%RTbool\n", aEnabled));
328
329 AutoCaller autoCaller (this);
330 CheckComRCReturnRC (autoCaller.rc());
331
332 /* the machine needs to be mutable */
333 Machine::AutoMutableStateDependency adep (mParent);
334 CheckComRCReturnRC (adep.rc());
335
336 AutoLock alock (this);
337
338 if (mData->mEnabled != aEnabled)
339 {
340 mData.backup();
341 mData->mEnabled = aEnabled;
342
343 /* leave the lock before informing callbacks */
344 alock.unlock();
345
346 mParent->onSerialPortChange (this);
347 }
348
349 return S_OK;
350}
351
352STDMETHODIMP SerialPort::COMGETTER(Slot) (ULONG *aSlot)
353{
354 if (!aSlot)
355 return E_POINTER;
356
357 AutoCaller autoCaller (this);
358 CheckComRCReturnRC (autoCaller.rc());
359
360 AutoReaderLock alock (this);
361
362 *aSlot = mData->mSlot;
363
364 return S_OK;
365}
366
367STDMETHODIMP SerialPort::COMGETTER(Irq) (ULONG *aIrq)
368{
369 if (!aIrq)
370 return E_POINTER;
371
372 AutoCaller autoCaller (this);
373 CheckComRCReturnRC (autoCaller.rc());
374
375 AutoReaderLock alock (this);
376
377 *aIrq = mData->mIrq;
378
379 return S_OK;
380}
381
382STDMETHODIMP SerialPort::COMSETTER(Irq)(ULONG aIrq)
383{
384 AutoCaller autoCaller (this);
385 CheckComRCReturnRC (autoCaller.rc());
386
387 /* the machine needs to be mutable */
388 Machine::AutoMutableStateDependency adep (mParent);
389 CheckComRCReturnRC (adep.rc());
390
391 AutoLock alock (this);
392
393 HRESULT rc = S_OK;
394 bool emitChangeEvent = false;
395
396 if (mData->mIrq != aIrq)
397 {
398 mData.backup();
399 mData->mIrq = aIrq;
400 emitChangeEvent = true;
401 }
402
403 if (emitChangeEvent)
404 {
405 /* leave the lock before informing callbacks */
406 alock.unlock();
407
408 mParent->onSerialPortChange (this);
409 }
410
411 return rc;
412}
413
414STDMETHODIMP SerialPort::COMGETTER(Iobase) (ULONG *aIobase)
415{
416 if (!aIobase)
417 return E_POINTER;
418
419 AutoCaller autoCaller (this);
420 CheckComRCReturnRC (autoCaller.rc());
421
422 AutoReaderLock alock (this);
423
424 *aIobase = mData->mIobase;
425
426 return S_OK;
427}
428
429STDMETHODIMP SerialPort::COMSETTER(Iobase)(ULONG aIobase)
430{
431 AutoCaller autoCaller (this);
432 CheckComRCReturnRC (autoCaller.rc());
433
434 /* the machine needs to be mutable */
435 Machine::AutoMutableStateDependency adep (mParent);
436 CheckComRCReturnRC (adep.rc());
437
438 AutoLock alock (this);
439
440 HRESULT rc = S_OK;
441 bool emitChangeEvent = false;
442
443 if (mData->mIobase != aIobase)
444 {
445 mData.backup();
446 mData->mIobase = aIobase;
447 emitChangeEvent = true;
448 }
449
450 if (emitChangeEvent)
451 {
452 /* leave the lock before informing callbacks */
453 alock.unlock();
454
455 mParent->onSerialPortChange (this);
456 }
457
458 return rc;
459}
460
461STDMETHODIMP SerialPort::COMGETTER(Pipe) (BSTR *aPipe)
462{
463 if (!aPipe)
464 return E_POINTER;
465
466 AutoCaller autoCaller (this);
467 CheckComRCReturnRC (autoCaller.rc());
468
469 AutoReaderLock alock (this);
470
471 mData->mPipe.cloneTo (aPipe);
472
473 return S_OK;
474}
475
476STDMETHODIMP SerialPort::COMSETTER(Pipe) (INPTR BSTR aPipe)
477{
478 if (!aPipe || *aPipe == 0)
479 return E_INVALIDARG;
480
481 AutoCaller autoCaller (this);
482 CheckComRCReturnRC (autoCaller.rc());
483
484 /* the machine needs to be mutable */
485 Machine::AutoMutableStateDependency adep (mParent);
486 CheckComRCReturnRC (adep.rc());
487
488 AutoLock alock (this);
489
490 if (mData->mPipe != aPipe)
491 {
492 mData.backup();
493 mData->mPipe = aPipe;
494
495 /* leave the lock before informing callbacks */
496 alock.unlock();
497
498 return mParent->onSerialPortChange (this);
499 }
500
501 return S_OK;
502}
503
504STDMETHODIMP SerialPort::COMGETTER(Server) (BOOL *aServer)
505{
506 if (!aServer)
507 return E_POINTER;
508
509 AutoCaller autoCaller (this);
510 CheckComRCReturnRC (autoCaller.rc());
511
512 AutoReaderLock alock (this);
513
514 *aServer = mData->mServer;
515
516 return S_OK;
517}
518
519STDMETHODIMP SerialPort::COMSETTER(Server) (BOOL aServer)
520{
521 LogFlowThisFunc (("aServer=%RTbool\n", aServer));
522
523 AutoCaller autoCaller (this);
524 CheckComRCReturnRC (autoCaller.rc());
525
526 /* the machine needs to be mutable */
527 Machine::AutoMutableStateDependency adep (mParent);
528 CheckComRCReturnRC (adep.rc());
529
530 AutoLock alock (this);
531
532 if (mData->mServer != aServer)
533 {
534 mData.backup();
535 mData->mServer = aServer;
536
537 /* leave the lock before informing callbacks */
538 alock.unlock();
539
540 mParent->onSerialPortChange (this);
541 }
542
543 return S_OK;
544}
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