Copter: free allocations in case of allocation failure
[ardupilot.git] / libraries / AP_Frsky_Telem / AP_Frsky_Telem.cpp
blob450591a381bd37503db39b21077371a3d1741f4c
1 /*
3 Inspired by work done here
4 https://github.com/PX4/Firmware/tree/master/src/drivers/frsky_telemetry from Stefan Rado <px4@sradonia.net>
5 https://github.com/opentx/opentx/tree/2.3/radio/src/telemetry from the OpenTX team
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 /*
22 FRSKY Telemetry library
25 #include "AP_Frsky_config.h"
27 #if AP_FRSKY_TELEM_ENABLED
29 #include "AP_Frsky_Telem.h"
30 #include "AP_Frsky_Parameters.h"
32 #include <AP_SerialManager/AP_SerialManager.h>
34 #include <AP_Vehicle/AP_Vehicle.h>
36 #include "AP_Frsky_D.h"
37 #include "AP_Frsky_SPort.h"
38 #include "AP_Frsky_SPort_Passthrough.h"
40 extern const AP_HAL::HAL& hal;
42 AP_Frsky_Telem *AP_Frsky_Telem::singleton;
44 AP_Frsky_Telem::AP_Frsky_Telem()
46 singleton = this;
47 #if HAL_WITH_FRSKY_TELEM_BIDIRECTIONAL
48 _frsky_parameters = &AP::vehicle()->frsky_parameters;
49 #endif //HAL_WITH_FRSKY_TELEM_BIDIRECTIONAL
53 AP_Frsky_Telem::~AP_Frsky_Telem(void)
55 singleton = nullptr;
59 * init - perform required initialisation
61 bool AP_Frsky_Telem::init(bool use_external_data)
63 const AP_SerialManager &serial_manager = AP::serialmanager();
65 // check for protocol configured for a serial port - only the first serial port with one of these protocols will then run (cannot have FrSky on multiple serial ports)
66 AP_HAL::UARTDriver *port;
67 if ((port = serial_manager.find_serial(AP_SerialManager::SerialProtocol_FrSky_D, 0))) {
68 #if AP_FRSKY_D_TELEM_ENABLED
69 _backend = NEW_NOTHROW AP_Frsky_D(port);
70 #endif
71 } else if ((port = serial_manager.find_serial(AP_SerialManager::SerialProtocol_FrSky_SPort, 0))) {
72 #if AP_FRSKY_SPORT_TELEM_ENABLED
73 _backend = NEW_NOTHROW AP_Frsky_SPort(port);
74 #endif
75 } else if (use_external_data || (port = serial_manager.find_serial(AP_SerialManager::SerialProtocol_FrSky_SPort_Passthrough, 0))) {
76 #if AP_FRSKY_SPORT_PASSTHROUGH_ENABLED
77 _backend = NEW_NOTHROW AP_Frsky_SPort_Passthrough(port, use_external_data, _frsky_parameters);
78 #endif
81 if (_backend == nullptr) {
82 return false;
85 if (!_backend->init()) {
86 delete _backend;
87 _backend = nullptr;
88 return false;
91 return true;
94 bool AP_Frsky_Telem::_get_telem_data(AP_Frsky_Backend::sport_packet_t* packet_array, uint8_t &packet_count, const uint8_t max_size)
96 if (_backend == nullptr) {
97 return false;
99 if (packet_array == nullptr) {
100 return false;
102 return _backend->get_telem_data(packet_array, packet_count, max_size);
105 #if HAL_WITH_FRSKY_TELEM_BIDIRECTIONAL
106 bool AP_Frsky_Telem::_set_telem_data(uint8_t frame, uint16_t appid, uint32_t data)
108 if (_backend == nullptr) {
109 return false;
111 return _backend->set_telem_data(frame, appid, data);
113 #endif
115 void AP_Frsky_Telem::try_create_singleton_for_external_data()
117 // try to allocate an AP_Frsky_Telem object only if we are disarmed
118 if (!singleton && !hal.util->get_soft_armed()) {
119 NEW_NOTHROW AP_Frsky_Telem();
120 // initialize the passthrough scheduler
121 if (singleton) {
122 singleton->init(true);
128 fetch Sport data for an external transport, such as FPort
130 bool AP_Frsky_Telem::get_telem_data(AP_Frsky_Backend::sport_packet_t* packet_array, uint8_t &packet_count, const uint8_t max_size)
132 try_create_singleton_for_external_data();
133 if (singleton == nullptr) {
134 return false;
136 return singleton->_get_telem_data(packet_array, packet_count, max_size);
139 #if HAL_WITH_FRSKY_TELEM_BIDIRECTIONAL
141 allow external transports (e.g. FPort), to supply telemetry data
143 bool AP_Frsky_Telem::set_telem_data(const uint8_t frame, const uint16_t appid, const uint32_t data)
145 try_create_singleton_for_external_data();
146 if (singleton == nullptr) {
147 return false;
149 return singleton->_set_telem_data(frame, appid, data);
151 #endif
153 namespace AP
155 AP_Frsky_Telem *frsky_telem()
157 return AP_Frsky_Telem::get_singleton();
161 #endif // AP_FRSKY_TELEM_ENABLED