Renderer, ...: use PixelRect::GetCenter()
[xcsoar.git] / src / Device / Descriptor.hpp
blob555f154ee79389eba733b199f890b5e3baa8993f
1 /*
2 Copyright_License {
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"
40 #include <assert.h>
41 #include <tchar.h>
42 #include <stdio.h>
44 struct NMEAInfo;
45 struct MoreData;
46 struct DerivedInfo;
47 struct Declaration;
48 struct Waypoint;
49 class Port;
50 class Device;
51 class AtmosphericPressure;
52 struct DeviceRegister;
53 class InternalSensors;
54 class BMP085Device;
55 class I2CbaroDevice;
56 class NunchuckDevice;
57 class VoltageDevice;
58 class RecordedFlightList;
59 struct RecordedFlightInfo;
60 class OperationEnvironment;
61 class OpenDeviceJob;
63 class DeviceDescriptor final : private Notify, private PortLineSplitter {
64 /**
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.
69 Mutex mutex;
71 /** the index of this device in the global list */
72 const unsigned index;
74 /**
75 * This device's configuration. It may differ from the instance in
76 * #SystemSettings, because overlapping devices might have been
77 * cleared.
79 DeviceConfig config;
81 /**
82 * This object runs the DoOpen() method in background to make it
83 * non-blocking.
85 AsyncJobRunner async;
87 /**
88 * The #Job that currently opens the device. NULL if the device is
89 * not currently being opened.
91 OpenDeviceJob *open_job;
93 /**
94 * The #Port used by this device. This is not applicable to some
95 * devices, and is NULL in that case.
97 Port *port;
99 /**
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
107 * other devices.
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.
125 Device *device;
127 #ifdef ANDROID
129 * A pointer to the Java object managing all Android sensors (GPS,
130 * baro sensor and others).
132 InternalSensors *internal_sensors;
134 #ifdef IOIOLIB
135 BMP085Device *droidsoar_v2;
136 I2CbaroDevice *i2cbaro[3]; // static, pitot, tek; in any order
137 NunchuckDevice *nunchuck;
138 VoltageDevice *voltage;
139 #endif
140 #endif
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
151 * state.
153 NMEAParser parser;
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()
178 unsigned n_failures;
181 * Internal flag for OnSysTicker() for detecting link timeout.
183 bool was_alive;
186 * Internal flag for OnSysTicker() for calling Device::OnSysTicker()
187 * only every other time.
189 bool ticker;
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()
199 bool borrowed;
201 public:
202 DeviceDescriptor(unsigned index);
203 ~DeviceDescriptor() {
204 assert(!IsOccupied());
207 unsigned GetIndex() const {
208 return index;
211 const DeviceConfig &GetConfig() const {
212 return config;
215 void SetConfig(const DeviceConfig &config);
216 void ClearConfig();
218 bool IsConfigured() const {
219 return config.port_type != DeviceConfig::PortType::DISABLED;
222 gcc_pure
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
258 * manager).
260 Device *GetDevice() {
261 return device;
264 private:
266 * Cancel the #AsyncJobRunner object if it is running.
268 void CancelAsync();
271 * When this method fails, the caller is responsible for freeing the
272 * Port object.
274 gcc_nonnull_all
275 bool OpenOnPort(Port *port, OperationEnvironment &env);
277 bool OpenInternalSensors();
279 bool OpenDroidSoarV2();
281 bool OpenI2Cbaro();
283 bool OpenNunchuck();
285 bool OpenVoltage();
286 public:
288 * To be used by OpenDeviceJob, don't call directly.
290 bool DoOpen(OperationEnvironment &env);
292 void ResetFailureCounter() {
293 n_failures = 0u;
297 * @param env a persistent object
299 void Open(OperationEnvironment &env);
301 void Close();
304 * @param env a persistent object
306 void Reopen(OperationEnvironment &env);
309 * Call this periodically to auto-reopen a failed device after a
310 * certain delay.
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
322 * to flaky cables.
324 bool EnableNMEA(OperationEnvironment &env);
326 const TCHAR *GetDisplayName() const;
329 * Compares the driver's name.
331 bool IsDriver(const TCHAR *name) const;
333 gcc_pure
334 bool CanDeclare() const;
336 gcc_pure
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 {
351 return borrowed;
355 * Is this device currently occupied, i.e. does somebody have
356 * exclusive access?
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.
371 * @see Borrow()
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
386 * borrowed
388 bool Borrow();
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.
396 void Return();
399 * Query the device's "alive" flag from the DeviceBlackboard.
400 * This method locks the DeviceBlackboard.
402 gcc_pure
403 bool IsAlive() const;
405 private:
406 bool ParseNMEA(const char *line, struct NMEAInfo &info);
408 public:
409 void SetMonitor(DataHandler *_monitor) {
410 monitor = _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);
423 #ifdef _UNICODE
424 bool WriteNMEA(const TCHAR *line, OperationEnvironment &env);
425 #endif
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);
456 void OnSysTicker();
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);
469 private:
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;
482 #endif