示例#1
0
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();
}
示例#2
0
bool
DeviceDescriptor::PutQNH(const AtmosphericPressure &value,
                         OperationEnvironment &env)
{
  assert(InMainThread());

  if (device == nullptr || settings_sent.CompareQNH(value) ||
      !config.sync_to_device)
    return true;

  if (!Borrow())
    /* TODO: postpone until the borrowed device has been returned */
    return false;

  ScopeReturnDevice restore(*this, env);
  if (!device->PutQNH(value, env))
    return false;

  ScopeLock protect(device_blackboard->mutex);
  NMEAInfo &basic = device_blackboard->SetRealState(index);
  settings_sent.qnh = value;
  settings_sent.qnh_available.Update(basic.clock);

  return true;
}
示例#3
0
bool
DeviceDescriptor::PutBallast(fixed fraction, fixed overload,
                             OperationEnvironment &env)
{
  assert(InMainThread());

  if (device == nullptr || !config.sync_to_device ||
      (settings_sent.CompareBallastFraction(fraction) &&
       settings_sent.CompareBallastOverload(overload)))
    return true;

  if (!Borrow())
    /* TODO: postpone until the borrowed device has been returned */
    return false;

  ScopeReturnDevice restore(*this, env);
  if (!device->PutBallast(fraction, overload, env))
    return false;

  ScopeLock protect(device_blackboard->mutex);
  NMEAInfo &basic = device_blackboard->SetRealState(index);
  settings_sent.ballast_fraction = fraction;
  settings_sent.ballast_fraction_available.Update(basic.clock);
  settings_sent.ballast_overload = overload;
  settings_sent.ballast_overload_available.Update(basic.clock);

  return true;
}
示例#4
0
void
ApplyVegaSwitches()
{
  assert(InMainThread());

  const VegaSwitchState &switches = CommonInterface::Basic().switch_state.vega;

  // detect changes to ON: on now (x) and not on before (!lastx)
  // detect changes to OFF: off now (!x) and on before (lastx)

  const unsigned up_inputs = switches.inputs & ~last_vega_switches.inputs;
  const unsigned down_inputs = ~switches.inputs & last_vega_switches.inputs;
  const unsigned up_outputs = switches.outputs & ~last_vega_switches.outputs;
  const unsigned down_outputs = ~switches.outputs & last_vega_switches.outputs;
  last_vega_switches = switches;

  for (unsigned i = 0; i < 32; ++i) {
    const unsigned thebit = 1 << i;

    if (down_inputs & thebit)
      InputEvents::processNmea(i);
    else if (up_inputs & thebit)
      InputEvents::processNmea(i + 64);

    if (down_outputs & thebit)
      InputEvents::processNmea(i + 32);
    else if (up_outputs & thebit)
      InputEvents::processNmea(i + 96);
  }

}
示例#5
0
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();
  }
}
示例#6
0
void
InputEvents::DoQueuedEvents()
{
  assert(InMainThread());

  int GCE_Queue_copy[MAX_GCE_QUEUE];
  int i;

  // copy the queue first, blocking
  {
    const ScopeLock lock(mutexEventQueue);
    std::copy_n(GCE_Queue, MAX_GCE_QUEUE, GCE_Queue_copy);
    std::fill_n(GCE_Queue, MAX_GCE_QUEUE, -1);
  }

  // process each item in the queue
  for (i = 0; i < MAX_GCE_QUEUE; i++) {
    if (GCE_Queue_copy[i] != -1) {
      processGlideComputer_real(GCE_Queue_copy[i]);
    }
  }
  for (i = 0; i < MAX_NMEA_QUEUE; i++) {
    if (NMEA_Queue[i] != -1)
      processNmea_real(NMEA_Queue[i]);
  }
}
示例#7
0
void
EnterDrawThread()
{
  assert(InMainThread());
  assert(draw_thread_handle == zero_thread_handle);

  draw_thread_handle = ThreadHandle::GetCurrent();
}
示例#8
0
void
LeaveDrawThread()
{
  assert(InMainThread());
  assert(draw_thread_handle.IsInside());

  draw_thread_handle = zero_thread_handle;
}
示例#9
0
void
DeviceDescriptor::Reopen(OperationEnvironment &env)
{
  assert(InMainThread());
  assert(!IsBorrowed());

  Close();
  Open(env);
}
示例#10
0
bool
InDrawThread()
{
#ifdef ENABLE_OPENGL
  return InMainThread() && draw_thread_handle.IsInside();
#else
  return draw_thread != nullptr && draw_thread->IsInside();
#endif
}
示例#11
0
void
DeviceDescriptor::OnCalculatedUpdate(const MoreData &basic,
                                     const DerivedInfo &calculated)
{
  assert(InMainThread());

  if (device != nullptr)
    device->OnCalculatedUpdate(basic, calculated);
}
示例#12
0
bool
DeviceDescriptor::Borrow()
{
  assert(InMainThread());

  if (!CanBorrow())
    return false;

  borrowed = true;
  return true;
}
示例#13
0
void
DeviceDescriptor::OnNotification()
{
  /* notification from AsyncJobRunner, the Job was finished */

  assert(InMainThread());
  assert(open_job != nullptr);

  async.Wait();

  delete open_job;
  open_job = nullptr;
}
示例#14
0
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();
}
示例#15
0
bool
InputEvents::processNmea(unsigned ne_id)
{
  assert(InMainThread());

  // add an event to the bottom of the queue
  for (int i = 0; i < MAX_NMEA_QUEUE; i++) {
    if (NMEA_Queue[i] == -1) {
      NMEA_Queue[i] = ne_id;
      break;
    }
  }

  return true; // ok.
}
示例#16
0
bool
DeviceDescriptor::PutVolume(unsigned volume, OperationEnvironment &env)
{
  assert(InMainThread());

  if (device == nullptr || !config.sync_to_device)
    return true;

  if (!Borrow())
    /* TODO: postpone until the borrowed device has been returned */
    return false;

  ScopeReturnDevice restore(*this, env);
  return device->PutVolume(volume, env);
}
示例#17
0
bool
DeviceDescriptor::PutStandbyFrequency(RadioFrequency frequency,
                                      OperationEnvironment &env)
{
  assert(InMainThread());

  if (device == NULL || !config.sync_to_device)
    return true;

  if (!Borrow())
    /* TODO: postpone until the borrowed device has been returned */
    return false;

  ScopeReturnDevice restore(*this, env);
  return device->PutStandbyFrequency(frequency, env);
}
示例#18
0
void
DeviceDescriptor::CancelAsync()
{
  assert(InMainThread());

  if (!async.IsBusy())
    return;

  assert(open_job != nullptr);

  async.Cancel();
  async.Wait();

  delete open_job;
  open_job = nullptr;
}
示例#19
0
void
DeviceDescriptor::OnNotification()
{
  /* notification from AsyncJobRunner, the Job was finished */

  assert(InMainThread());
  assert(open_job != nullptr);

  try {
    async.Wait();
  } catch (const std::runtime_error &e) {
    LogError(e);
  }

  delete open_job;
  open_job = nullptr;
}
示例#20
0
void
DeviceDescriptor::AutoReopen(OperationEnvironment &env)
{
  assert(InMainThread());

  if (/* don't reopen a device that is occupied */
      IsOccupied() ||
      !config.IsAvailable() ||
      !ShouldReopen() ||
      /* attempt to reopen a failed device every 30 seconds */
      !reopen_clock.CheckUpdate(30000))
    return;

  TCHAR buffer[64];
  LogStartUp(_T("Reconnecting to device %s"), config.GetPortName(buffer, 64));

  InputEvents::processGlideComputer(GCE_COMMPORT_RESTART);
  Reopen(env);
}
示例#21
0
void
DeviceDescriptor::CancelAsync()
{
  assert(InMainThread());

  if (!async.IsBusy())
    return;

  assert(open_job != nullptr);

  async.Cancel();

  try {
    async.Wait();
  } catch (const std::runtime_error &e) {
    LogError(e);
  }

  delete open_job;
  open_job = nullptr;
}
示例#22
0
void
DeviceDescriptor::AutoReopen(OperationEnvironment &env)
{
  assert(InMainThread());

  if (/* don't reopen a device that is occupied */
      IsOccupied() ||
      !config.IsAvailable() ||
      !ShouldReopen() ||
      /* attempt to reopen a failed device every 30 seconds */
      !reopen_clock.CheckUpdate(30000))
    return;

#ifdef ANDROID
  if (config.port_type == DeviceConfig::PortType::RFCOMM &&
      android_api_level < 11 && n_failures >= 2) {
    /* on Android < 3.0, system_server's "BT EventLoop" thread
       eventually crashes with JNI reference table overflow due to a
       memory leak after too many Bluetooth failures
       (https://code.google.com/p/android/issues/detail?id=8676);
       don't attempt to reconnect on this Android version over and
       over to keep the chance of this bug occurring low enough */

    if (n_failures == 2) {
      LogFormat(_T("Giving up on Bluetooth device %s to avoid Android crash bug"),
                config.bluetooth_mac.c_str());
      ++n_failures;
    }

    return;
  }
#endif

  TCHAR buffer[64];
  LogFormat(_T("Reconnecting to device %s"), config.GetPortName(buffer, 64));

  InputEvents::processGlideComputer(GCE_COMMPORT_RESTART);
  Reopen(env);
}
示例#23
0
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);
}
示例#24
0
  /**
   * Returns the InterfaceBlackboard.ComputerSettings (read-only)
   * @return The InterfaceBlackboard.ComputerSettings
   */
  gcc_const
  static inline const ComputerSettings& GetComputerSettings() {
    assert(InMainThread());

    return Private::blackboard.GetComputerSettings();
  }
示例#25
0
bool
InDrawThread()
{
  return InMainThread();
}
示例#26
0
  /**
   * Returns InterfaceBlackboard.Basic (NMEA_INFO) (read-only)
   * @return InterfaceBlackboard.Basic
   */
  gcc_const
  static inline const MoreData &Basic() {
    assert(InMainThread());

    return Private::blackboard.Basic();
  }
示例#27
0
  /**
   * Returns InterfaceBlackboard.Calculated (DERIVED_INFO) (read-only)
   * @return InterfaceBlackboard.Calculated
   */
  gcc_const
  static inline const DerivedInfo &Calculated() {
    assert(InMainThread());

    return Private::blackboard.Calculated();
  }
示例#28
0
  /**
   * Can this device be borrowed?
   *
   * May only be called from the main thread.
   *
   * @see Borrow()
   */
  bool CanBorrow() const {
    assert(InMainThread());

    return device != nullptr && GetState() == PortState::READY &&
      !IsOccupied();
  }
示例#29
0
  /**
   * 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();
  }
示例#30
0
  gcc_const
  static inline SystemSettings &SetSystemSettings() {
    assert(InMainThread());

    return Private::blackboard.SetSystemSettings();
  }