[8620] | 1 | /** @file
|
---|
| 2 | *
|
---|
| 3 | * VirtualBox COM class implementation
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[8155] | 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.
|
---|
[8620] | 20 | */
|
---|
| 21 |
|
---|
| 22 | #include "SerialPortImpl.h"
|
---|
| 23 | #include "MachineImpl.h"
|
---|
| 24 | #include "VirtualBoxImpl.h"
|
---|
[21607] | 25 | #include "GuestOSTypeImpl.h"
|
---|
[8620] | 26 | #include "Logging.h"
|
---|
| 27 |
|
---|
| 28 | #include <iprt/string.h>
|
---|
| 29 | #include <iprt/cpputils.h>
|
---|
| 30 |
|
---|
[16560] | 31 | #include <VBox/settings.h>
|
---|
| 32 |
|
---|
[25203] | 33 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 34 | //
|
---|
| 35 | // SerialPort private data definition
|
---|
| 36 | //
|
---|
| 37 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 38 |
|
---|
| 39 | struct SerialPort::Data
|
---|
| 40 | {
|
---|
| 41 | Data()
|
---|
| 42 | { }
|
---|
| 43 |
|
---|
| 44 | const ComObjPtr<Machine, ComWeakRef> pMachine;
|
---|
| 45 | const ComObjPtr<SerialPort> pPeer;
|
---|
| 46 |
|
---|
| 47 | Backupable<settings::SerialPort> bd;
|
---|
| 48 | };
|
---|
| 49 |
|
---|
[8620] | 50 | // constructor / destructor
|
---|
| 51 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 52 |
|
---|
| 53 | DEFINE_EMPTY_CTOR_DTOR (SerialPort)
|
---|
| 54 |
|
---|
| 55 | HRESULT SerialPort::FinalConstruct()
|
---|
| 56 | {
|
---|
| 57 | return S_OK;
|
---|
| 58 | }
|
---|
| 59 |
|
---|
| 60 | void SerialPort::FinalRelease()
|
---|
| 61 | {
|
---|
| 62 | uninit();
|
---|
| 63 | }
|
---|
| 64 |
|
---|
| 65 | // public initializer/uninitializer for internal purposes only
|
---|
| 66 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 67 |
|
---|
| 68 | /**
|
---|
| 69 | * Initializes the Serial Port object.
|
---|
| 70 | *
|
---|
| 71 | * @param aParent Handle of the parent object.
|
---|
| 72 | */
|
---|
[25203] | 73 | HRESULT SerialPort::init(Machine *aParent, ULONG aSlot)
|
---|
[8620] | 74 | {
|
---|
[21878] | 75 | LogFlowThisFunc(("aParent=%p, aSlot=%d\n", aParent, aSlot));
|
---|
[8620] | 76 |
|
---|
| 77 | ComAssertRet (aParent, E_INVALIDARG);
|
---|
| 78 |
|
---|
| 79 | /* Enclose the state transition NotReady->InInit->Ready */
|
---|
[21878] | 80 | AutoInitSpan autoInitSpan(this);
|
---|
| 81 | AssertReturn(autoInitSpan.isOk(), E_FAIL);
|
---|
[8620] | 82 |
|
---|
[25203] | 83 | m = new Data();
|
---|
[8620] | 84 |
|
---|
[25203] | 85 | unconst(m->pMachine) = aParent;
|
---|
| 86 | /* m->pPeer is left null */
|
---|
[8620] | 87 |
|
---|
[25203] | 88 | m->bd.allocate();
|
---|
| 89 |
|
---|
[8620] | 90 | /* initialize data */
|
---|
[25203] | 91 | m->bd->ulSlot = aSlot;
|
---|
[8620] | 92 |
|
---|
| 93 | /* Confirm a successful initialization */
|
---|
| 94 | autoInitSpan.setSucceeded();
|
---|
| 95 |
|
---|
| 96 | return S_OK;
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | /**
|
---|
| 100 | * Initializes the Serial Port object given another serial port object
|
---|
| 101 | * (a kind of copy constructor). This object shares data with
|
---|
| 102 | * the object passed as an argument.
|
---|
| 103 | *
|
---|
| 104 | * @note This object must be destroyed before the original object
|
---|
| 105 | * it shares data with is destroyed.
|
---|
| 106 | *
|
---|
| 107 | * @note Locks @a aThat object for reading.
|
---|
| 108 | */
|
---|
[25203] | 109 | HRESULT SerialPort::init(Machine *aParent, SerialPort *aThat)
|
---|
[8620] | 110 | {
|
---|
[21878] | 111 | LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
|
---|
[8620] | 112 |
|
---|
| 113 | ComAssertRet (aParent && aThat, E_INVALIDARG);
|
---|
| 114 |
|
---|
| 115 | /* Enclose the state transition NotReady->InInit->Ready */
|
---|
[21878] | 116 | AutoInitSpan autoInitSpan(this);
|
---|
| 117 | AssertReturn(autoInitSpan.isOk(), E_FAIL);
|
---|
[8620] | 118 |
|
---|
[25203] | 119 | m = new Data();
|
---|
[8620] | 120 |
|
---|
[25203] | 121 | unconst(m->pMachine) = aParent;
|
---|
| 122 | unconst(m->pPeer) = aThat;
|
---|
| 123 |
|
---|
[8620] | 124 | AutoCaller thatCaller (aThat);
|
---|
[21878] | 125 | AssertComRCReturnRC(thatCaller.rc());
|
---|
[8620] | 126 |
|
---|
| 127 | AutoReadLock thatLock (aThat);
|
---|
[25203] | 128 | m->bd.share (aThat->m->bd);
|
---|
[8620] | 129 |
|
---|
| 130 | /* Confirm a successful initialization */
|
---|
| 131 | autoInitSpan.setSucceeded();
|
---|
| 132 |
|
---|
| 133 | return S_OK;
|
---|
| 134 | }
|
---|
| 135 |
|
---|
| 136 | /**
|
---|
| 137 | * Initializes the guest object given another guest object
|
---|
| 138 | * (a kind of copy constructor). This object makes a private copy of data
|
---|
| 139 | * of the original object passed as an argument.
|
---|
| 140 | *
|
---|
| 141 | * @note Locks @a aThat object for reading.
|
---|
| 142 | */
|
---|
[25203] | 143 | HRESULT SerialPort::initCopy(Machine *aParent, SerialPort *aThat)
|
---|
[8620] | 144 | {
|
---|
[21878] | 145 | LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
|
---|
[8620] | 146 |
|
---|
| 147 | ComAssertRet (aParent && aThat, E_INVALIDARG);
|
---|
| 148 |
|
---|
| 149 | /* Enclose the state transition NotReady->InInit->Ready */
|
---|
[21878] | 150 | AutoInitSpan autoInitSpan(this);
|
---|
| 151 | AssertReturn(autoInitSpan.isOk(), E_FAIL);
|
---|
[8620] | 152 |
|
---|
[25203] | 153 | m = new Data();
|
---|
[8620] | 154 |
|
---|
[25203] | 155 | unconst(m->pMachine) = aParent;
|
---|
| 156 | /* pPeer is left null */
|
---|
| 157 |
|
---|
[8620] | 158 | AutoCaller thatCaller (aThat);
|
---|
[21878] | 159 | AssertComRCReturnRC(thatCaller.rc());
|
---|
[8620] | 160 |
|
---|
| 161 | AutoReadLock thatLock (aThat);
|
---|
[25203] | 162 | m->bd.attachCopy (aThat->m->bd);
|
---|
[8620] | 163 |
|
---|
| 164 | /* Confirm a successful initialization */
|
---|
| 165 | autoInitSpan.setSucceeded();
|
---|
| 166 |
|
---|
| 167 | return S_OK;
|
---|
| 168 | }
|
---|
| 169 |
|
---|
| 170 | /**
|
---|
| 171 | * Uninitializes the instance and sets the ready flag to FALSE.
|
---|
| 172 | * Called either from FinalRelease() or by the parent when it gets destroyed.
|
---|
| 173 | */
|
---|
| 174 | void SerialPort::uninit()
|
---|
| 175 | {
|
---|
[21878] | 176 | LogFlowThisFunc(("\n"));
|
---|
[8620] | 177 |
|
---|
| 178 | /* Enclose the state transition Ready->InUninit->NotReady */
|
---|
[21878] | 179 | AutoUninitSpan autoUninitSpan(this);
|
---|
[8620] | 180 | if (autoUninitSpan.uninitDone())
|
---|
| 181 | return;
|
---|
| 182 |
|
---|
[25203] | 183 | m->bd.free();
|
---|
[8620] | 184 |
|
---|
[25203] | 185 | unconst(m->pPeer).setNull();
|
---|
| 186 | unconst(m->pMachine).setNull();
|
---|
[8620] | 187 |
|
---|
[25203] | 188 | delete m;
|
---|
| 189 | m = NULL;
|
---|
[8620] | 190 | }
|
---|
| 191 |
|
---|
| 192 | // ISerialPort properties
|
---|
| 193 | /////////////////////////////////////////////////////////////////////////////
|
---|
| 194 |
|
---|
| 195 | STDMETHODIMP SerialPort::COMGETTER(Enabled) (BOOL *aEnabled)
|
---|
| 196 | {
|
---|
[14972] | 197 | CheckComArgOutPointerValid(aEnabled);
|
---|
[8620] | 198 |
|
---|
[21878] | 199 | AutoCaller autoCaller(this);
|
---|
[25149] | 200 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 201 |
|
---|
[21878] | 202 | AutoReadLock alock(this);
|
---|
[8620] | 203 |
|
---|
[25203] | 204 | *aEnabled = m->bd->fEnabled;
|
---|
[8620] | 205 |
|
---|
| 206 | return S_OK;
|
---|
| 207 | }
|
---|
| 208 |
|
---|
| 209 | STDMETHODIMP SerialPort::COMSETTER(Enabled) (BOOL aEnabled)
|
---|
| 210 | {
|
---|
[21878] | 211 | LogFlowThisFunc(("aEnabled=%RTbool\n", aEnabled));
|
---|
[8620] | 212 |
|
---|
[21878] | 213 | AutoCaller autoCaller(this);
|
---|
[25149] | 214 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 215 |
|
---|
| 216 | /* the machine needs to be mutable */
|
---|
[25203] | 217 | Machine::AutoMutableStateDependency adep(m->pMachine);
|
---|
[25149] | 218 | if (FAILED(adep.rc())) return adep.rc();
|
---|
[8620] | 219 |
|
---|
[21878] | 220 | AutoWriteLock alock(this);
|
---|
[8620] | 221 |
|
---|
[25203] | 222 | if (m->bd->fEnabled != aEnabled)
|
---|
[8620] | 223 | {
|
---|
[25203] | 224 | m->bd.backup();
|
---|
| 225 | m->bd->fEnabled = aEnabled;
|
---|
[8620] | 226 |
|
---|
| 227 | /* leave the lock before informing callbacks */
|
---|
| 228 | alock.unlock();
|
---|
| 229 |
|
---|
[25203] | 230 | m->pMachine->onSerialPortChange (this);
|
---|
[8620] | 231 | }
|
---|
| 232 |
|
---|
| 233 | return S_OK;
|
---|
| 234 | }
|
---|
| 235 |
|
---|
| 236 | STDMETHODIMP SerialPort::COMGETTER(HostMode) (PortMode_T *aHostMode)
|
---|
| 237 | {
|
---|
[14972] | 238 | CheckComArgOutPointerValid(aHostMode);
|
---|
[8620] | 239 |
|
---|
[21878] | 240 | AutoCaller autoCaller(this);
|
---|
[25149] | 241 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 242 |
|
---|
[21878] | 243 | AutoReadLock alock(this);
|
---|
[8620] | 244 |
|
---|
[25203] | 245 | *aHostMode = m->bd->portMode;
|
---|
[8620] | 246 |
|
---|
| 247 | return S_OK;
|
---|
| 248 | }
|
---|
| 249 |
|
---|
| 250 | STDMETHODIMP SerialPort::COMSETTER(HostMode) (PortMode_T aHostMode)
|
---|
| 251 | {
|
---|
[21878] | 252 | AutoCaller autoCaller(this);
|
---|
[25149] | 253 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 254 |
|
---|
| 255 | /* the machine needs to be mutable */
|
---|
[25203] | 256 | Machine::AutoMutableStateDependency adep(m->pMachine);
|
---|
[25149] | 257 | if (FAILED(adep.rc())) return adep.rc();
|
---|
[8620] | 258 |
|
---|
[21878] | 259 | AutoWriteLock alock(this);
|
---|
[8620] | 260 |
|
---|
| 261 | HRESULT rc = S_OK;
|
---|
| 262 | bool emitChangeEvent = false;
|
---|
| 263 |
|
---|
[25203] | 264 | if (m->bd->portMode != aHostMode)
|
---|
[8620] | 265 | {
|
---|
| 266 | switch (aHostMode)
|
---|
| 267 | {
|
---|
[19624] | 268 | case PortMode_RawFile:
|
---|
[25203] | 269 | if (m->bd->strPath.isEmpty())
|
---|
[19624] | 270 | return setError (E_INVALIDARG,
|
---|
| 271 | tr ("Cannot set the raw file mode of the serial port %d "
|
---|
| 272 | "because the file path is empty or null"),
|
---|
[25203] | 273 | m->bd->ulSlot);
|
---|
[19624] | 274 | break;
|
---|
[8620] | 275 | case PortMode_HostPipe:
|
---|
[25203] | 276 | if (m->bd->strPath.isEmpty())
|
---|
[8620] | 277 | return setError (E_INVALIDARG,
|
---|
| 278 | tr ("Cannot set the host pipe mode of the serial port %d "
|
---|
| 279 | "because the pipe path is empty or null"),
|
---|
[25203] | 280 | m->bd->ulSlot);
|
---|
[8620] | 281 | break;
|
---|
| 282 | case PortMode_HostDevice:
|
---|
[25203] | 283 | if (m->bd->strPath.isEmpty())
|
---|
[8620] | 284 | return setError (E_INVALIDARG,
|
---|
| 285 | tr ("Cannot set the host device mode of the serial port %d "
|
---|
| 286 | "because the device path is empty or null"),
|
---|
[25203] | 287 | m->bd->ulSlot);
|
---|
[8620] | 288 | break;
|
---|
| 289 | case PortMode_Disconnected:
|
---|
| 290 | break;
|
---|
| 291 | }
|
---|
| 292 |
|
---|
[25203] | 293 | m->bd.backup();
|
---|
| 294 | m->bd->portMode = aHostMode;
|
---|
[8620] | 295 |
|
---|
| 296 | emitChangeEvent = true;
|
---|
| 297 | }
|
---|
| 298 |
|
---|
| 299 | if (emitChangeEvent)
|
---|
| 300 | {
|
---|
| 301 | /* leave the lock before informing callbacks */
|
---|
| 302 | alock.unlock();
|
---|
| 303 |
|
---|
[25203] | 304 | m->pMachine->onSerialPortChange (this);
|
---|
[8620] | 305 | }
|
---|
| 306 |
|
---|
| 307 | return rc;
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | STDMETHODIMP SerialPort::COMGETTER(Slot) (ULONG *aSlot)
|
---|
| 311 | {
|
---|
[14972] | 312 | CheckComArgOutPointerValid(aSlot);
|
---|
[8620] | 313 |
|
---|
[21878] | 314 | AutoCaller autoCaller(this);
|
---|
[25149] | 315 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 316 |
|
---|
[21878] | 317 | AutoReadLock alock(this);
|
---|
[8620] | 318 |
|
---|
[25203] | 319 | *aSlot = m->bd->ulSlot;
|
---|
[8620] | 320 |
|
---|
| 321 | return S_OK;
|
---|
| 322 | }
|
---|
| 323 |
|
---|
| 324 | STDMETHODIMP SerialPort::COMGETTER(IRQ) (ULONG *aIRQ)
|
---|
| 325 | {
|
---|
[14972] | 326 | CheckComArgOutPointerValid(aIRQ);
|
---|
[8620] | 327 |
|
---|
[21878] | 328 | AutoCaller autoCaller(this);
|
---|
[25149] | 329 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 330 |
|
---|
[21878] | 331 | AutoReadLock alock(this);
|
---|
[8620] | 332 |
|
---|
[25203] | 333 | *aIRQ = m->bd->ulIRQ;
|
---|
[8620] | 334 |
|
---|
| 335 | return S_OK;
|
---|
| 336 | }
|
---|
| 337 |
|
---|
| 338 | STDMETHODIMP SerialPort::COMSETTER(IRQ)(ULONG aIRQ)
|
---|
| 339 | {
|
---|
| 340 | /* check IRQ limits
|
---|
| 341 | * (when changing this, make sure it corresponds to XML schema */
|
---|
| 342 | if (aIRQ > 255)
|
---|
| 343 | return setError (E_INVALIDARG,
|
---|
| 344 | tr ("Invalid IRQ number of the serial port %d: "
|
---|
| 345 | "%lu (must be in range [0, %lu])"),
|
---|
[25203] | 346 | m->bd->ulSlot, aIRQ, 255);
|
---|
[8620] | 347 |
|
---|
[21878] | 348 | AutoCaller autoCaller(this);
|
---|
[25149] | 349 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 350 |
|
---|
| 351 | /* the machine needs to be mutable */
|
---|
[25203] | 352 | Machine::AutoMutableStateDependency adep(m->pMachine);
|
---|
[25149] | 353 | if (FAILED(adep.rc())) return adep.rc();
|
---|
[8620] | 354 |
|
---|
[21878] | 355 | AutoWriteLock alock(this);
|
---|
[8620] | 356 |
|
---|
| 357 | HRESULT rc = S_OK;
|
---|
| 358 | bool emitChangeEvent = false;
|
---|
| 359 |
|
---|
[25203] | 360 | if (m->bd->ulIRQ != aIRQ)
|
---|
[8620] | 361 | {
|
---|
[25203] | 362 | m->bd.backup();
|
---|
| 363 | m->bd->ulIRQ = aIRQ;
|
---|
[8620] | 364 | emitChangeEvent = true;
|
---|
| 365 | }
|
---|
| 366 |
|
---|
| 367 | if (emitChangeEvent)
|
---|
| 368 | {
|
---|
| 369 | /* leave the lock before informing callbacks */
|
---|
| 370 | alock.unlock();
|
---|
| 371 |
|
---|
[25203] | 372 | m->pMachine->onSerialPortChange (this);
|
---|
[8620] | 373 | }
|
---|
| 374 |
|
---|
| 375 | return rc;
|
---|
| 376 | }
|
---|
| 377 |
|
---|
| 378 | STDMETHODIMP SerialPort::COMGETTER(IOBase) (ULONG *aIOBase)
|
---|
| 379 | {
|
---|
[14972] | 380 | CheckComArgOutPointerValid(aIOBase);
|
---|
[8620] | 381 |
|
---|
[21878] | 382 | AutoCaller autoCaller(this);
|
---|
[25149] | 383 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 384 |
|
---|
[21878] | 385 | AutoReadLock alock(this);
|
---|
[8620] | 386 |
|
---|
[25203] | 387 | *aIOBase = m->bd->ulIOBase;
|
---|
[8620] | 388 |
|
---|
| 389 | return S_OK;
|
---|
| 390 | }
|
---|
| 391 |
|
---|
| 392 | STDMETHODIMP SerialPort::COMSETTER(IOBase)(ULONG aIOBase)
|
---|
| 393 | {
|
---|
| 394 | /* check IOBase limits
|
---|
| 395 | * (when changing this, make sure it corresponds to XML schema */
|
---|
| 396 | if (aIOBase > 0xFFFF)
|
---|
| 397 | return setError (E_INVALIDARG,
|
---|
| 398 | tr ("Invalid I/O port base address of the serial port %d: "
|
---|
| 399 | "%lu (must be in range [0, 0x%X])"),
|
---|
[25203] | 400 | m->bd->ulSlot, aIOBase, 0, 0xFFFF);
|
---|
[8620] | 401 |
|
---|
[21878] | 402 | AutoCaller autoCaller(this);
|
---|
[25149] | 403 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 404 |
|
---|
| 405 | /* the machine needs to be mutable */
|
---|
[25203] | 406 | Machine::AutoMutableStateDependency adep(m->pMachine);
|
---|
[25149] | 407 | if (FAILED(adep.rc())) return adep.rc();
|
---|
[8620] | 408 |
|
---|
[21878] | 409 | AutoWriteLock alock(this);
|
---|
[8620] | 410 |
|
---|
| 411 | HRESULT rc = S_OK;
|
---|
| 412 | bool emitChangeEvent = false;
|
---|
| 413 |
|
---|
[25203] | 414 | if (m->bd->ulIOBase != aIOBase)
|
---|
[8620] | 415 | {
|
---|
[25203] | 416 | m->bd.backup();
|
---|
| 417 | m->bd->ulIOBase = aIOBase;
|
---|
[8620] | 418 | emitChangeEvent = true;
|
---|
| 419 | }
|
---|
| 420 |
|
---|
| 421 | if (emitChangeEvent)
|
---|
| 422 | {
|
---|
| 423 | /* leave the lock before informing callbacks */
|
---|
| 424 | alock.unlock();
|
---|
| 425 |
|
---|
[25203] | 426 | m->pMachine->onSerialPortChange (this);
|
---|
[8620] | 427 | }
|
---|
| 428 |
|
---|
| 429 | return rc;
|
---|
| 430 | }
|
---|
| 431 |
|
---|
| 432 | STDMETHODIMP SerialPort::COMGETTER(Path) (BSTR *aPath)
|
---|
| 433 | {
|
---|
[14972] | 434 | CheckComArgOutPointerValid(aPath);
|
---|
[8620] | 435 |
|
---|
[21878] | 436 | AutoCaller autoCaller(this);
|
---|
[25149] | 437 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 438 |
|
---|
[21878] | 439 | AutoReadLock alock(this);
|
---|
[8620] | 440 |
|
---|
[25203] | 441 | m->bd->strPath.cloneTo(aPath);
|
---|
[8620] | 442 |
|
---|
| 443 | return S_OK;
|
---|
| 444 | }
|
---|
| 445 |
|
---|
[15051] | 446 | STDMETHODIMP SerialPort::COMSETTER(Path) (IN_BSTR aPath)
|
---|
[8620] | 447 | {
|
---|
[21878] | 448 | AutoCaller autoCaller(this);
|
---|
[25149] | 449 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 450 |
|
---|
| 451 | /* the machine needs to be mutable */
|
---|
[25203] | 452 | Machine::AutoMutableStateDependency adep(m->pMachine);
|
---|
[25149] | 453 | if (FAILED(adep.rc())) return adep.rc();
|
---|
[8620] | 454 |
|
---|
[21878] | 455 | AutoWriteLock alock(this);
|
---|
[8620] | 456 |
|
---|
[13580] | 457 | /* we treat empty as null when e.g. saving to XML, do the same here */
|
---|
| 458 | if (aPath && *aPath == '\0')
|
---|
| 459 | aPath = NULL;
|
---|
| 460 |
|
---|
[25203] | 461 | Utf8Str str(aPath);
|
---|
| 462 | if (str != m->bd->strPath)
|
---|
[8620] | 463 | {
|
---|
[25203] | 464 | HRESULT rc = checkSetPath(str);
|
---|
[25149] | 465 | if (FAILED(rc)) return rc;
|
---|
[8620] | 466 |
|
---|
[25203] | 467 | m->bd.backup();
|
---|
| 468 | m->bd->strPath = str;
|
---|
[8620] | 469 |
|
---|
| 470 | /* leave the lock before informing callbacks */
|
---|
| 471 | alock.unlock();
|
---|
| 472 |
|
---|
[25203] | 473 | return m->pMachine->onSerialPortChange(this);
|
---|
[8620] | 474 | }
|
---|
| 475 |
|
---|
| 476 | return S_OK;
|
---|
| 477 | }
|
---|
| 478 |
|
---|
| 479 | STDMETHODIMP SerialPort::COMGETTER(Server) (BOOL *aServer)
|
---|
| 480 | {
|
---|
[14972] | 481 | CheckComArgOutPointerValid(aServer);
|
---|
[8620] | 482 |
|
---|
[21878] | 483 | AutoCaller autoCaller(this);
|
---|
[25149] | 484 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 485 |
|
---|
[21878] | 486 | AutoReadLock alock(this);
|
---|
[8620] | 487 |
|
---|
[25203] | 488 | *aServer = m->bd->fServer;
|
---|
[8620] | 489 |
|
---|
| 490 | return S_OK;
|
---|
| 491 | }
|
---|
| 492 |
|
---|
| 493 | STDMETHODIMP SerialPort::COMSETTER(Server) (BOOL aServer)
|
---|
| 494 | {
|
---|
[21878] | 495 | AutoCaller autoCaller(this);
|
---|
[25149] | 496 | if (FAILED(autoCaller.rc())) return autoCaller.rc();
|
---|
[8620] | 497 |
|
---|
| 498 | /* the machine needs to be mutable */
|
---|
[25203] | 499 | Machine::AutoMutableStateDependency adep(m->pMachine);
|
---|
[25149] | 500 | if (FAILED(adep.rc())) return adep.rc();
|
---|
[8620] | 501 |
|
---|
[21878] | 502 | AutoWriteLock alock(this);
|
---|
[8620] | 503 |
|
---|
[25203] | 504 | if (m->bd->fServer != aServer)
|
---|
[8620] | 505 | {
|
---|
[25203] | 506 | m->bd.backup();
|
---|
| 507 | m->bd->fServer = aServer;
|
---|
[8620] | 508 |
|
---|
| 509 | /* leave the lock before informing callbacks */
|
---|
| 510 | alock.unlock();
|
---|
| 511 |
|
---|
[25203] | 512 | m->pMachine->onSerialPortChange (this);
|
---|
[8620] | 513 | }
|
---|
| 514 |
|
---|
| 515 | return S_OK;
|
---|
| 516 | }
|
---|
[25203] | 517 |
|
---|
| 518 | // public methods only for internal purposes
|
---|
| 519 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 520 |
|
---|
| 521 | /**
|
---|
| 522 | * Loads settings from the given port node.
|
---|
| 523 | * May be called once right after this object creation.
|
---|
| 524 | *
|
---|
| 525 | * @param aPortNode <Port> node.
|
---|
| 526 | *
|
---|
| 527 | * @note Locks this object for writing.
|
---|
| 528 | */
|
---|
| 529 | HRESULT SerialPort::loadSettings(const settings::SerialPort &data)
|
---|
| 530 | {
|
---|
| 531 | AutoCaller autoCaller(this);
|
---|
| 532 | AssertComRCReturnRC(autoCaller.rc());
|
---|
| 533 |
|
---|
| 534 | AutoWriteLock alock(this);
|
---|
| 535 |
|
---|
| 536 | // simply copy
|
---|
| 537 | *m->bd.data() = data;
|
---|
| 538 |
|
---|
| 539 | return S_OK;
|
---|
| 540 | }
|
---|
| 541 |
|
---|
| 542 | /**
|
---|
| 543 | * Saves the port settings to the given port node.
|
---|
| 544 | *
|
---|
| 545 | * Note that the given Port node is comletely empty on input.
|
---|
| 546 | *
|
---|
| 547 | * @param aPortNode <Port> node.
|
---|
| 548 | *
|
---|
| 549 | * @note Locks this object for reading.
|
---|
| 550 | */
|
---|
| 551 | HRESULT SerialPort::saveSettings(settings::SerialPort &data)
|
---|
| 552 | {
|
---|
| 553 | AutoCaller autoCaller(this);
|
---|
| 554 | AssertComRCReturnRC(autoCaller.rc());
|
---|
| 555 |
|
---|
| 556 | AutoReadLock alock(this);
|
---|
| 557 |
|
---|
| 558 | // simply copy
|
---|
| 559 | data = *m->bd.data();
|
---|
| 560 |
|
---|
| 561 | return S_OK;
|
---|
| 562 | }
|
---|
| 563 |
|
---|
| 564 | bool SerialPort::isModified()
|
---|
| 565 | {
|
---|
| 566 | AutoWriteLock alock (this);
|
---|
| 567 | return m->bd.isBackedUp();
|
---|
| 568 | }
|
---|
| 569 |
|
---|
| 570 | bool SerialPort::isReallyModified()
|
---|
| 571 | {
|
---|
| 572 | AutoWriteLock alock(this);
|
---|
| 573 | return m->bd.hasActualChanges();
|
---|
| 574 | }
|
---|
| 575 |
|
---|
| 576 | /**
|
---|
| 577 | * @note Locks this object for writing.
|
---|
| 578 | */
|
---|
| 579 | bool SerialPort::rollback()
|
---|
| 580 | {
|
---|
| 581 | /* sanity */
|
---|
| 582 | AutoCaller autoCaller(this);
|
---|
| 583 | AssertComRCReturn (autoCaller.rc(), false);
|
---|
| 584 |
|
---|
| 585 | AutoWriteLock alock(this);
|
---|
| 586 |
|
---|
| 587 | bool changed = false;
|
---|
| 588 |
|
---|
| 589 | if (m->bd.isBackedUp())
|
---|
| 590 | {
|
---|
| 591 | /* we need to check all data to see whether anything will be changed
|
---|
| 592 | * after rollback */
|
---|
| 593 | changed = m->bd.hasActualChanges();
|
---|
| 594 | m->bd.rollback();
|
---|
| 595 | }
|
---|
| 596 |
|
---|
| 597 | return changed;
|
---|
| 598 | }
|
---|
| 599 |
|
---|
| 600 | /**
|
---|
| 601 | * @note Locks this object for writing, together with the peer object (also
|
---|
| 602 | * for writing) if there is one.
|
---|
| 603 | */
|
---|
| 604 | void SerialPort::commit()
|
---|
| 605 | {
|
---|
| 606 | /* sanity */
|
---|
| 607 | AutoCaller autoCaller(this);
|
---|
| 608 | AssertComRCReturnVoid (autoCaller.rc());
|
---|
| 609 |
|
---|
| 610 | /* sanity too */
|
---|
| 611 | AutoCaller peerCaller(m->pPeer);
|
---|
| 612 | AssertComRCReturnVoid(peerCaller.rc());
|
---|
| 613 |
|
---|
| 614 | /* lock both for writing since we modify both (pPeer is "master" so locked
|
---|
| 615 | * first) */
|
---|
| 616 | AutoMultiWriteLock2 alock(m->pPeer, this);
|
---|
| 617 |
|
---|
| 618 | if (m->bd.isBackedUp())
|
---|
| 619 | {
|
---|
| 620 | m->bd.commit();
|
---|
| 621 | if (m->pPeer)
|
---|
| 622 | {
|
---|
| 623 | /* attach new data to the peer and reshare it */
|
---|
| 624 | m->pPeer->m->bd.attach(m->bd);
|
---|
| 625 | }
|
---|
| 626 | }
|
---|
| 627 | }
|
---|
| 628 |
|
---|
| 629 | /**
|
---|
| 630 | * @note Locks this object for writing, together with the peer object
|
---|
| 631 | * represented by @a aThat (locked for reading).
|
---|
| 632 | */
|
---|
| 633 | void SerialPort::copyFrom (SerialPort *aThat)
|
---|
| 634 | {
|
---|
| 635 | AssertReturnVoid (aThat != NULL);
|
---|
| 636 |
|
---|
| 637 | /* sanity */
|
---|
| 638 | AutoCaller autoCaller(this);
|
---|
| 639 | AssertComRCReturnVoid (autoCaller.rc());
|
---|
| 640 |
|
---|
| 641 | /* sanity too */
|
---|
| 642 | AutoCaller thatCaller (aThat);
|
---|
| 643 | AssertComRCReturnVoid (thatCaller.rc());
|
---|
| 644 |
|
---|
| 645 | /* peer is not modified, lock it for reading (aThat is "master" so locked
|
---|
| 646 | * first) */
|
---|
| 647 | AutoMultiLock2 alock (aThat->rlock(), this->wlock());
|
---|
| 648 |
|
---|
| 649 | /* this will back up current data */
|
---|
| 650 | m->bd.assignCopy (aThat->m->bd);
|
---|
| 651 | }
|
---|
| 652 |
|
---|
| 653 | void SerialPort::applyDefaults (GuestOSType *aOsType)
|
---|
| 654 | {
|
---|
| 655 | AssertReturnVoid (aOsType != NULL);
|
---|
| 656 |
|
---|
| 657 | /* sanity */
|
---|
| 658 | AutoCaller autoCaller(this);
|
---|
| 659 | AssertComRCReturnVoid (autoCaller.rc());
|
---|
| 660 |
|
---|
| 661 | AutoWriteLock alock(this);
|
---|
| 662 |
|
---|
| 663 | uint32_t numSerialEnabled = aOsType->numSerialEnabled();
|
---|
| 664 |
|
---|
| 665 | /* Enable port if requested */
|
---|
| 666 | if (m->bd->ulSlot < numSerialEnabled)
|
---|
| 667 | {
|
---|
| 668 | m->bd->fEnabled = true;
|
---|
| 669 | }
|
---|
| 670 | }
|
---|
| 671 |
|
---|
| 672 | /**
|
---|
| 673 | * Validates COMSETTER(Path) arguments.
|
---|
| 674 | */
|
---|
| 675 | HRESULT SerialPort::checkSetPath(const Utf8Str &str)
|
---|
| 676 | {
|
---|
| 677 | AssertReturn(isWriteLockOnCurrentThread(), E_FAIL);
|
---|
| 678 |
|
---|
| 679 | if ( ( m->bd->portMode == PortMode_HostDevice
|
---|
| 680 | || m->bd->portMode == PortMode_HostPipe
|
---|
| 681 | || m->bd->portMode == PortMode_RawFile
|
---|
| 682 | ) && str.isEmpty()
|
---|
| 683 | )
|
---|
| 684 | return setError(E_INVALIDARG,
|
---|
| 685 | tr("Path of the serial port %d may not be empty or null in "
|
---|
| 686 | "host pipe or host device mode"),
|
---|
| 687 | m->bd->ulSlot);
|
---|
| 688 |
|
---|
| 689 | return S_OK;
|
---|
| 690 | }
|
---|
| 691 |
|
---|
[14772] | 692 | /* vi: set tabstop=4 shiftwidth=4 expandtab: */
|
---|