4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #ifndef XCSOAR_DEVICE_DESCRIPTOR_HPP
25 #define XCSOAR_DEVICE_DESCRIPTOR_HPP
27 #include "IO/DataHandler.hpp"
28 #include "Port/LineSplitter.hpp"
29 #include "Port/State.hpp"
30 #include "Device/Parser.hpp"
31 #include "Profile/DeviceConfig.hpp"
32 #include "RadioFrequency.hpp"
33 #include "NMEA/ExternalSettings.hpp"
34 #include "Time/PeriodClock.hpp"
35 #include "Job/Async.hpp"
36 #include "Event/Notify.hpp"
37 #include "Thread/Mutex.hpp"
38 #include "Thread/Debug.hpp"
51 class AtmosphericPressure
;
52 struct DeviceRegister
;
53 class InternalSensors
;
58 class RecordedFlightList
;
59 struct RecordedFlightInfo
;
60 class OperationEnvironment
;
63 class DeviceDescriptor final
: private Notify
, private PortLineSplitter
{
65 * This mutex protects modifications of the attribute "device". If
66 * you use the attribute "device" from a thread other than the main
67 * thread, you must hold this mutex.
71 /** the index of this device in the global list */
75 * This device's configuration. It may differ from the instance in
76 * #SystemSettings, because overlapping devices might have been
82 * This object runs the DoOpen() method in background to make it
88 * The #Job that currently opens the device. NULL if the device is
89 * not currently being opened.
91 OpenDeviceJob
*open_job
;
94 * The #Port used by this device. This is not applicable to some
95 * devices, and is NULL in that case.
100 * A handler that will receive all data, to display it on the
101 * screen. Can be set with SetMonitor().
103 DataHandler
*monitor
;
106 * A handler that will receive all NMEA lines, to dispatch it to
109 PortLineHandler
*dispatcher
;
112 * The device driver used to handle data to/from the device.
114 const DeviceRegister
*driver
;
117 * An instance of the driver.
119 * Modifications (from the main thread) must be protected by the
120 * attribute "mutex". Read access and any use of this object
121 * outside of the main thread must also be protected, unless the
122 * device was borrowed with the method Borrow(). The latter,
123 * however, is only possible from the main thread.
129 * A pointer to the Java object managing all Android sensors (GPS,
130 * baro sensor and others).
132 InternalSensors
*internal_sensors
;
135 BMP085Device
*droidsoar_v2
;
136 I2CbaroDevice
*i2cbaro
[3]; // static, pitot, tek; in any order
137 NunchuckDevice
*nunchuck
;
138 VoltageDevice
*voltage
;
143 * This clock keeps track when we need to reopen the device next
144 * time after a failure or after a timeout. It gets updated each
145 * time the failure/timeout occurs, and again after each retry.
147 PeriodClock reopen_clock
;
150 * The generic NMEA parser for this device. It may hold internal
156 * The settings that were sent to the device. This is used to check
157 * if the device is sending back the new configuration; then the
158 * device isn't actually sending a new setting, it is merely
159 * repeating the settings we sent it. This should not make XCSoar
160 * reconfigure itself.
162 ExternalSettings settings_sent
;
165 * The settings that were received from the device. This temporary
166 * buffer mirrors NMEA_INFO::settings; NMEA_INFO::settings may get
167 * cleared with ExternalSettings::EliminateRedundant(), so this one
168 * always preserves the original values from the device, without
169 * having to do a full NMEA_INFO copy.
171 ExternalSettings settings_received
;
174 * Number of port failures since the device was last reset.
176 * @param see ResetFailureCounter()
181 * Internal flag for OnSysTicker() for detecting link timeout.
186 * Internal flag for OnSysTicker() for calling Device::OnSysTicker()
187 * only every other time.
192 * True when somebody has "borrowed" the device. Link timeouts are
193 * disabled meanwhile.
195 * This attribute is only accessed from the main thread.
197 * @see CanBorrow(), Borrow()
202 DeviceDescriptor(unsigned index
);
203 ~DeviceDescriptor() {
204 assert(!IsOccupied());
207 unsigned GetIndex() const {
211 const DeviceConfig
&GetConfig() const {
215 void SetConfig(const DeviceConfig
&config
);
218 bool IsConfigured() const {
219 return config
.port_type
!= DeviceConfig::PortType::DISABLED
;
223 PortState
GetState() const;
226 * Was there a failure on the #Port object?
228 bool HasPortFailed() const {
229 return config
.IsAvailable() && config
.UsesPort() && port
== NULL
;
233 * Wrapper for Driver::HasTimeout(). This method can't be inline
234 * because the Driver struct is incomplete at this point.
236 bool ShouldReopenDriverOnTimeout() const;
239 * Should the #Port be reopened automatically when a timeout occurs?
241 bool ShouldReopenOnTimeout() const {
242 return config
.ShouldReopenOnTimeout() &&
243 ShouldReopenDriverOnTimeout();
247 * Should the #Port be reopened?
249 bool ShouldReopen() const {
250 return HasPortFailed() || (!IsAlive() && ShouldReopenOnTimeout());
254 * Returns the Device object; may be NULL if the device is not open
255 * or if the Device class is not applicable for this object.
257 * Should only be used by driver-specific code (such as the CAI 302
260 Device
*GetDevice() {
266 * Cancel the #AsyncJobRunner object if it is running.
271 * When this method fails, the caller is responsible for freeing the
275 bool OpenOnPort(Port
*port
, OperationEnvironment
&env
);
277 bool OpenInternalSensors();
279 bool OpenDroidSoarV2();
288 * To be used by OpenDeviceJob, don't call directly.
290 bool DoOpen(OperationEnvironment
&env
);
292 void ResetFailureCounter() {
297 * @param env a persistent object
299 void Open(OperationEnvironment
&env
);
304 * @param env a persistent object
306 void Reopen(OperationEnvironment
&env
);
309 * Call this periodically to auto-reopen a failed device after a
312 * @param env a persistent object
314 void AutoReopen(OperationEnvironment
&env
);
317 * Call this method after Declare(), ReadFlightList(),
318 * DownloadFlight() when you're done, to switch back to NMEA mode.
320 * Even when the driver's EnableNMEA() method fails, this method
321 * will re-enable the receive thread, to avoid false negatives due
324 bool EnableNMEA(OperationEnvironment
&env
);
326 const TCHAR
*GetDisplayName() const;
329 * Compares the driver's name.
331 bool IsDriver(const TCHAR
*name
) const;
334 bool CanDeclare() const;
337 bool IsLogger() const;
339 bool IsCondor() const {
340 return IsDriver(_T("Condor"));
343 bool IsVega() const {
344 return IsDriver(_T("Vega"));
347 bool IsNMEAOut() const;
348 bool IsManageable() const;
350 bool IsBorrowed() const {
355 * Is this device currently occupied, i.e. does somebody have
358 * May only be called from the main thread.
360 bool IsOccupied() const {
361 assert(InMainThread());
363 return IsBorrowed() || async
.IsBusy();
367 * Can this device be borrowed?
369 * May only be called from the main thread.
373 bool CanBorrow() const {
374 assert(InMainThread());
376 return device
!= NULL
&& GetState() == PortState::READY
&& !IsOccupied();
380 * "Borrow" the device. The caller gets exclusive access, e.g. to
381 * submit a task declaration. Call Return() when you are done.
383 * May only be called from the main thread.
385 * @return false if the device is already occupied and cannot be
391 * Return a borrowed device. The caller is responsible for
392 * switching the device back to NMEA mode, see EnableNMEA().
394 * May only be called from the main thread.
399 * Query the device's "alive" flag from the DeviceBlackboard.
400 * This method locks the DeviceBlackboard.
403 bool IsAlive() const;
406 bool ParseNMEA(const char *line
, struct NMEAInfo
&info
);
409 void SetMonitor(DataHandler
*_monitor
) {
413 void SetDispatcher(PortLineHandler
*_dispatcher
) {
414 dispatcher
= _dispatcher
;
418 * Write a line to the device's port if it's a NMEA out port.
420 void ForwardLine(const char *line
);
422 bool WriteNMEA(const char *line
, OperationEnvironment
&env
);
424 bool WriteNMEA(const TCHAR
*line
, OperationEnvironment
&env
);
427 bool PutMacCready(fixed mac_cready
, OperationEnvironment
&env
);
428 bool PutBugs(fixed bugs
, OperationEnvironment
&env
);
429 bool PutBallast(fixed fraction
, fixed overload
,
430 OperationEnvironment
&env
);
431 bool PutVolume(unsigned volume
, OperationEnvironment
&env
);
432 bool PutActiveFrequency(RadioFrequency frequency
,
433 OperationEnvironment
&env
);
434 bool PutStandbyFrequency(RadioFrequency frequency
,
435 OperationEnvironment
&env
);
436 bool PutQNH(const AtmosphericPressure
&pres
, OperationEnvironment
&env
);
439 * Caller is responsible for calling Borrow() and Return().
441 bool Declare(const Declaration
&declaration
, const Waypoint
*home
,
442 OperationEnvironment
&env
);
445 * Caller is responsible for calling Borrow() and Return().
447 bool ReadFlightList(RecordedFlightList
&flight_list
,
448 OperationEnvironment
&env
);
451 * Caller is responsible for calling Borrow() and Return().
453 bool DownloadFlight(const RecordedFlightInfo
&flight
, const TCHAR
*path
,
454 OperationEnvironment
&env
);
459 * Wrapper for Driver::OnSensorUpdate().
461 void OnSensorUpdate(const MoreData
&basic
);
464 * Wrapper for Driver::OnCalculatedUpdate().
466 void OnCalculatedUpdate(const MoreData
&basic
,
467 const DerivedInfo
&calculated
);
470 bool ParseLine(const char *line
);
472 /* virtual methods from class Notify */
473 virtual void OnNotification() override
;
475 /* virtual methods from DataHandler */
476 virtual void DataReceived(const void *data
, size_t length
) override
;
478 /* virtual methods from PortLineHandler */
479 virtual void LineReceived(const char *line
) override
;