void DeviceDescriptor::Close() { assert(InMainThread()); assert(!IsBorrowed()); CancelAsync(); #ifdef HAVE_INTERNAL_GPS delete internal_sensors; internal_sensors = nullptr; #endif #ifdef ANDROID delete droidsoar_v2; droidsoar_v2 = nullptr; for (unsigned i=0; i<sizeof i2cbaro/sizeof i2cbaro[0]; i++) { delete i2cbaro[i]; i2cbaro[i] = nullptr; } delete nunchuck; nunchuck = nullptr; delete voltage; voltage = nullptr; #endif /* safely delete the Device object */ Device *old_device = device; { const ScopeLock protect(mutex); device = nullptr; /* after leaving this scope, no other thread may use the old object; to avoid locking the mutex for too long, the "delete" is called after the scope */ } delete old_device; delete second_device; second_device = nullptr; Port *old_port = port; port = nullptr; delete old_port; ticker = false; { const ScopeLock lock(device_blackboard->mutex); device_blackboard->SetRealState(index).Reset(); device_blackboard->ScheduleMerge(); } settings_sent.Clear(); settings_received.Clear(); }
void DeviceDescriptor::OnSysTicker() { assert(InMainThread()); if (port != nullptr && port->GetState() == PortState::FAILED && !IsOccupied()) Close(); if (device == nullptr) return; const bool now_alive = IsAlive(); if (!now_alive && was_alive && !IsOccupied()) { /* connection was just lost */ device->LinkTimeout(); NullOperationEnvironment env; EnableNMEA(env); } was_alive = now_alive; if (now_alive || IsBorrowed()) { ticker = !ticker; if (ticker) // write settings to vario every second device->OnSysTicker(); } }
void DeviceDescriptor::Reopen(OperationEnvironment &env) { assert(InMainThread()); assert(!IsBorrowed()); Close(); Open(env); }
bool DeviceDescriptor::OpenOnPort(DumpPort *_port, OperationEnvironment &env) { #if !CLANG_CHECK_VERSION(3,6) /* disabled on clang due to -Wtautological-pointer-compare */ assert(_port != nullptr); #endif assert(port == nullptr); assert(device == nullptr); assert(second_device == nullptr); assert(driver != nullptr); assert(!ticker); assert(!IsBorrowed()); reopen_clock.Update(); device_blackboard->mutex.Lock(); device_blackboard->SetRealState(index).Reset(); device_blackboard->ScheduleMerge(); device_blackboard->mutex.Unlock(); settings_sent.Clear(); settings_received.Clear(); was_alive = false; port = _port; parser.Reset(); parser.SetReal(!StringIsEqual(driver->name, _T("Condor"))); if (config.IsDriver(_T("Condor"))) parser.DisableGeoid(); if (driver->CreateOnPort != nullptr) { Device *new_device = driver->CreateOnPort(config, *port); const ScopeLock protect(mutex); device = new_device; if (driver->HasPassThrough() && config.use_second_device) second_device = second_driver->CreateOnPort(config, *port); } else port->StartRxThread(); EnableNMEA(env); if (env.IsCancelled()) { /* the caller is responsible for freeing the port on error */ port = nullptr; delete device; device = nullptr; delete second_device; second_device = nullptr; return false; } return true; }
bool DeviceDescriptor::Open(Port &_port, OperationEnvironment &env) { assert(port == NULL); assert(device == NULL); assert(driver != NULL); assert(!ticker); assert(!IsBorrowed()); reopen_clock.Update(); device_blackboard->mutex.Lock(); device_blackboard->SetRealState(index).Reset(); device_blackboard->ScheduleMerge(); device_blackboard->mutex.Unlock(); settings_sent.Clear(); settings_received.Clear(); was_alive = false; port = &_port; assert(driver->CreateOnPort != NULL || driver->IsNMEAOut()); if (driver->CreateOnPort == NULL) { assert(driver->IsNMEAOut()); /* start the Port thread for NMEA out; this is a kludge for TCPPort, because TCPPort calls accept() only in the receive thread. Data received from NMEA out is discarded by our method DataReceived(). Once TCPPort gets fixed, this kludge can be removed. */ port->StartRxThread(); return true; } parser.Reset(); parser.SetReal(_tcscmp(driver->name, _T("Condor")) != 0); parser.SetIgnoreChecksum(config.ignore_checksum); if (config.IsDriver(_T("Condor"))) parser.DisableGeoid(); Device *new_device = driver->CreateOnPort(config, *port); { const ScopeLock protect(mutex); device = new_device; } EnableNMEA(env); return true; }
void DeviceDescriptor::Return() { assert(InMainThread()); assert(IsBorrowed()); borrowed = false; assert(!IsOccupied()); /* if the caller has disabled the NMEA while the device was borrowed, we may not have received new values for some time, but that doesn't mean the device has failed; give it some time to recover, and don't reopen right away */ reopen_clock.Update(); }
void DeviceDescriptor::Open(OperationEnvironment &env) { assert(InMainThread()); assert(port == nullptr); assert(device == nullptr); assert(!ticker); assert(!IsBorrowed()); if (is_simulator() || !config.IsAvailable()) return; CancelAsync(); assert(!IsOccupied()); assert(open_job == nullptr); TCHAR buffer[64]; LogFormat(_T("Opening device %s"), config.GetPortName(buffer, 64)); open_job = new OpenDeviceJob(*this); async.Start(open_job, env, this); }
/** * Is this device currently occupied, i.e. does somebody have * exclusive access? * * May only be called from the main thread. */ bool IsOccupied() const { assert(InMainThread()); return IsBorrowed() || async.IsBusy(); }
/** * Is this device currently occupied, i.e. does somebody have * exclusive access? * * May only be called from the main thread. */ bool IsOccupied() const { return IsBorrowed() || async.IsBusy(); }