diff --git a/features/lorawan/lorastack/mac/LoRaMac.cpp b/features/lorawan/lorastack/mac/LoRaMac.cpp index fd65ef5c2f..e4bfd0caf3 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.cpp +++ b/features/lorawan/lorastack/mac/LoRaMac.cpp @@ -24,6 +24,8 @@ SPDX-License-Identifier: BSD-3-Clause #include #include #include "LoRaMac.h" +#include "LoRaMacClassBInterface.h" + #include "mbed-trace/mbed_trace.h" #define TRACE_GROUP "LMAC" @@ -817,7 +819,7 @@ void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp) } else { _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK; // Resume Class B reception slots - LoRaMacClassB::Resume(); + LoRaMacClassBInterface::resume(); } _params.last_channel_idx = _params.channel; @@ -852,7 +854,7 @@ void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size, // Class B handling rx_slot_t rx_slot = get_current_slot(); - LoRaMacClassB::Handle_rx(rx_slot, payload, size, rx_timestamp); + LoRaMacClassBInterface::handle_rx(rx_slot, payload, size, rx_timestamp); if (rx_slot == RX_SLOT_WIN_BEACON) { return; } @@ -898,7 +900,7 @@ void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size, } // Resume Class B reception slots - LoRaMacClassB::Resume(); + LoRaMacClassBInterface::resume(); } void LoRaMac::on_radio_tx_timeout(void) @@ -928,7 +930,7 @@ void LoRaMac::on_radio_tx_timeout(void) _mcps_confirmation.tx_toa = 0; // Resume Class B reception slots - LoRaMacClassB::Resume(); + LoRaMacClassBInterface::resume(); } void LoRaMac::on_radio_rx_timeout(bool is_timeout) @@ -943,7 +945,7 @@ void LoRaMac::on_radio_rx_timeout(bool is_timeout) } // Class B Rx timeout notification - LoRaMacClassB::Handle_rx_timeout(_params.rx_slot); + LoRaMacClassBInterface::handle_rx_timeout(_params.rx_slot); if (_params.rx_slot == RX_SLOT_WIN_1) { if (_params.is_node_ack_requested == true) { @@ -953,7 +955,7 @@ void LoRaMac::on_radio_rx_timeout(bool is_timeout) if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) { _lora_time.stop(_params.timers.rx_window2_timer); // Resume Class B reception slots - LoRaMacClassB::Resume(); + LoRaMacClassBInterface::resume(); } } } else if (_params.rx_slot == RX_SLOT_WIN_2) { @@ -961,7 +963,7 @@ void LoRaMac::on_radio_rx_timeout(bool is_timeout) _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR; } // Resume Class B reception slots - LoRaMacClassB::Resume(); + LoRaMacClassBInterface::resume(); } } @@ -1135,14 +1137,14 @@ bool LoRaMac::set_rx_slot(rx_slot_t rx_slot) if (_demod_ongoing) { /* rx_slot_t is ordered from high to low priority. Class A receive windows being highest - * priority then class C followed by beacon, multicast ping slot and coming in last - * is unicast ping slot. + * priority then class C followed by beacon, multicast ping slot and coming in last + * is unicast ping slot. */ - if(rx_slot <= _params.rx_slot){ + if (rx_slot <= _params.rx_slot) { _lora_phy->put_radio_to_sleep(); _params.rx_slot = rx_slot; return true; - } else{ + } else { tr_info("%s Demodulation ongoing, skip %s window opening", get_rx_slot_string(rx_slot), get_rx_slot_string(get_current_slot())); return false; @@ -1698,14 +1700,14 @@ lorawan_status_t LoRaMac::set_device_class(const device_class_t &device_class, _lora_time.init(_rx2_closure_timer_for_class_c, _rx2_would_be_closure_for_class_c); if (CLASS_B == _device_class) { - LoRaMacClassB::Disable(); + LoRaMacClassBInterface::disable(); } if (CLASS_A == device_class) { tr_debug("Changing device class to -> CLASS_A"); _lora_phy->put_radio_to_sleep(); } else if (CLASS_B == device_class) { - status = LoRaMacClassB::Enable(); + status = LoRaMacClassBInterface::enable(); if (status == LORAWAN_STATUS_OK) { tr_debug("Changing device class to -> CLASS_B"); _lora_phy->put_radio_to_sleep(); @@ -2170,7 +2172,7 @@ lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel) tx_config.antenna_gain = _params.sys_params.antenna_gain; tx_config.pkt_len = _params.tx_buffer_len; - LoRaMacClassB::Pause(); + LoRaMacClassBInterface::pause(); _demod_ongoing = false; _lora_phy->tx_config(&tx_config, &tx_power, &_params.timers.tx_toa); @@ -2256,9 +2258,9 @@ lorawan_status_t LoRaMac::initialize(EventQueue *queue, _params.sys_params.adr_on = MBED_CONF_LORA_ADR_ON; _params.sys_params.channel_data_rate = _lora_phy->get_default_max_tx_datarate(); - LoRaMacClassB::Initialize(&_lora_time, _lora_phy, &_lora_crypto, - &_params, mbed::callback(this, &LoRaMac::open_rx_window), - mbed::callback(this, &LoRaMac::close_rx_window)); + LoRaMacClassBInterface::initialize(&_lora_time, _lora_phy, &_lora_crypto, + &_params, mbed::callback(this, &LoRaMac::open_rx_window), + mbed::callback(this, &LoRaMac::close_rx_window)); return LORAWAN_STATUS_OK; @@ -2512,10 +2514,10 @@ lorawan_status_t LoRaMac::add_ping_slot_info_req() lorawan_status_t LoRaMac::enable_beacon_acquisition(mbed::Callbackbeacon_event_cb) { - return LoRaMacClassB::Enable_beacon_acquisition(beacon_event_cb); + return LoRaMacClassBInterface::enable_beacon_acquisition(beacon_event_cb); } lorawan_status_t LoRaMac::get_last_rx_beacon(loramac_beacon_t &beacon) { - return LoRaMacClassB::Get_last_rx_beacon(beacon); + return LoRaMacClassBInterface::get_last_rx_beacon(beacon); } diff --git a/features/lorawan/lorastack/mac/LoRaMac.h b/features/lorawan/lorastack/mac/LoRaMac.h index 9736bef8c0..4594f91e20 100644 --- a/features/lorawan/lorastack/mac/LoRaMac.h +++ b/features/lorawan/lorastack/mac/LoRaMac.h @@ -47,7 +47,6 @@ #include "system/LoRaWANTimer.h" #include "system/lorawan_data_structures.h" -#include "LoRaMacClassB.h" #include "LoRaMacChannelPlan.h" #include "LoRaMacCommand.h" #include "LoRaMacCrypto.h" diff --git a/features/lorawan/lorastack/mac/LoRaMacClassB.cpp b/features/lorawan/lorastack/mac/LoRaMacClassB.cpp index 767295226a..ff54b5e311 100644 --- a/features/lorawan/lorastack/mac/LoRaMacClassB.cpp +++ b/features/lorawan/lorastack/mac/LoRaMacClassB.cpp @@ -30,10 +30,6 @@ SPDX-License-Identifier: BSD-3-Clause #include "mbed-trace/mbed_trace.h" #define TRACE_GROUP "LMAC" -#ifdef LORA_CLASS_B_ENABLED - -LoRaMacClassB LoRaMacClassB::_loramac_class_b; - /*! * Limit ping slot mbed tracing to once per this period in millis */ @@ -50,7 +46,7 @@ LoRaMacClassB LoRaMacClassB::_loramac_class_b; #define CLASSB_PING_SLOT_WINDOW 30 /*! - * Invalid slot length time in ms + * Invalid ping slot */ #define LORAMAC_INVALID_PING_SLOT -1 @@ -74,11 +70,14 @@ LoRaMacClassB::LoRaMacClassB() memset(&_opstatus, 0, sizeof(_opstatus)); } -void LoRaMacClassB::initialize(LoRaWANTimeHandler *lora_time, LoRaPHY *lora_phy, - LoRaMacCrypto *lora_crypto, loramac_protocol_params *params, - mbed::Callback open_window, - mbed::Callback close_window) +lorawan_status_t LoRaMacClassB::initialize(LoRaWANTimeHandler *lora_time, LoRaPHY *lora_phy, + LoRaMacCrypto *lora_crypto, loramac_protocol_params *params, + mbed::Callback open_window, + mbed::Callback close_window) { + // Initialization should not be called more than once + MBED_ASSERT(!_opstatus.initialized); + if (!_opstatus.initialized) { MBED_ASSERT(lora_time); MBED_ASSERT(lora_crypto); @@ -115,6 +114,8 @@ void LoRaMacClassB::initialize(LoRaWANTimeHandler *lora_time, LoRaPHY *lora_phy, _opstatus.initialized = 1; } + + return LORAWAN_STATUS_OK; } lorawan_status_t LoRaMacClassB::enable(void) @@ -223,7 +224,7 @@ bool LoRaMacClassB::schedule_beacon_window(void) _lora_time->start(_beacon_timer, delay); } - tr_debug("Next beacon time = %llu in %ld ms", next_beacon_time/1000, delay); + tr_debug("Next beacon time = %llu in %ld ms", next_beacon_time / 1000, delay); } return true; @@ -692,6 +693,4 @@ void LoRaMacClassB::remove_multicast_address(uint32_t address) _ping.slot[i].address = 0; } } -} - -#endif //#if MBED_CONF_LORA_CLASS_B_SUPPORT \ No newline at end of file +} \ No newline at end of file diff --git a/features/lorawan/lorastack/mac/LoRaMacClassB.h b/features/lorawan/lorastack/mac/LoRaMacClassB.h index 2f022e1f33..ecfbb11f2a 100644 --- a/features/lorawan/lorastack/mac/LoRaMacClassB.h +++ b/features/lorawan/lorastack/mac/LoRaMacClassB.h @@ -17,10 +17,6 @@ * limitations under the License. */ -#if (MBED_CONF_LORA_VERSION >= 01) && (MBED_CONF_LORA_CLASS_B == true) -#define LORA_CLASS_B_ENABLED -#endif - #include "system/lorawan_data_structures.h" #include "lorastack/phy/LoRaPHY.h" #include "lorastack/mac/LoRaMacCrypto.h" @@ -30,7 +26,20 @@ #endif class LoRaMacClassB { -public: +protected: + + // LoRaWANClassBInterface provides the public interface + friend class LoRaMacClassBInterface; + + /** + * Constructor + */ + LoRaMacClassB(); + + /** + * Destructor + */ + ~LoRaMacClassB() {}; /** * Initialize Class B system @@ -40,75 +49,50 @@ public: * @param [in] lora_crypto * @param [in] params * @param [in] open_rx_window LoRaMac open rx window callback - * @param [in] close_rx_window LoRaMac close rx window callback + * @param [in] close_rx_window LoRaMac close rx window callback * @return LORAWAN_STATUS_OK or a negative error return code */ - inline static lorawan_status_t Initialize(LoRaWANTimeHandler *lora_time, - LoRaPHY *lora_phy, - LoRaMacCrypto *lora_crypto, - loramac_protocol_params *params, - mbed::Callback open_rx_window, - mbed::Callback close_rx_window) - { - _loramac_class_b.initialize(lora_time, lora_phy, lora_crypto, params, - open_rx_window, close_rx_window); - return LORAWAN_STATUS_OK; - } + lorawan_status_t initialize(LoRaWANTimeHandler *lora_time, + LoRaPHY *lora_phy, + LoRaMacCrypto *lora_crypto, + loramac_protocol_params *params, + mbed::Callback open_rx_window, + mbed::Callback close_rx_window); /** * Enable beacon acquisition and tracking * * @return LORAWAN_STATUS_OK or a negative error return code */ - inline static lorawan_status_t Enable_beacon_acquisition(mbed::Callback beacon_event_cb) - { - return _loramac_class_b.enable_beacon_acquisition(beacon_event_cb); - } + lorawan_status_t enable_beacon_acquisition(mbed::Callback beacon_event_cb); /** - * Enable Class B mode. Called after successful beacon acquisition + * Enable Class B mode. Called after successful beacon acquisition to enable B ping slots * @return LORAWAN_STATUS_OK or a negative error return code */ - inline static lorawan_status_t Enable(void) - { - return _loramac_class_b.enable(); - } + lorawan_status_t enable(void); /** - * Disables Class B beacon and ping slot scheduling + * Disable Class B */ - inline static lorawan_status_t Disable(void) - { - return _loramac_class_b.disable(); - } + lorawan_status_t disable(void); /** - * Pause class b operation. Called prior to class A uplink + * Temporarily pause Class B operation during class A uplink & rx windows */ - inline static void Pause(void) - { - _loramac_class_b.pause(); - } + void pause(void); /** - * Resume class b operation. Called after class A receive windows + * Resume class b operation after pause. To be called after class A receive windows */ - inline static void Resume(void) - { - _loramac_class_b.resume(); - } + void resume(void); /** * Handle radio receive timeout event * @param [in] rx_slot The receive window type */ - inline static void Handle_rx_timeout(rx_slot_t rx_slot) - { - if (is_operational()) { - _loramac_class_b.handle_rx_timeout(rx_slot); - } - } + void handle_rx_timeout(rx_slot_t rx_slot); /** * Handle radio receive event @@ -117,46 +101,42 @@ public: * @param [in] size * @param [in] rx_timestamp */ - inline static void Handle_rx(rx_slot_t rx_slot, const uint8_t *const data, uint16_t size, uint32_t rx_timestamp) - { - if (is_operational()) { - return _loramac_class_b.handle_rx(rx_slot, data, size, rx_timestamp); - } - } + void handle_rx(rx_slot_t rx_slot, const uint8_t *const data, uint16_t size, uint32_t rx_timestamp); /** * Returns last received beacon info */ - inline static lorawan_status_t Get_last_rx_beacon(loramac_beacon_t &beacon) - { - return _loramac_class_b.get_last_rx_beacon(beacon); - } + lorawan_status_t get_last_rx_beacon(loramac_beacon_t &beacon); /** * Add ping slot multicast address + * @param [in] address Multicast address */ - inline static bool Add_multicast_address(uint32_t address) - { - return _loramac_class_b.add_multicast_address(address); - - } + bool add_multicast_address(uint32_t address); /** * Remove ping slot multicast address + * @param [in] address Multicast address */ - inline static void Remove_multicast_address(uint32_t address) + void remove_multicast_address(uint32_t address); + + /** + * @brief Return gps time + */ + inline lorawan_gps_time_t get_gps_time(void) { - return _loramac_class_b.remove_multicast_address(address); + return _lora_time->get_gps_time(); } /** - * Returns True if class B beacon window scheduling is enabled + * Returns True if beacon acquisition/tracking is enabled */ - inline static bool is_operational(void) + inline bool is_operational(void) { - return (_loramac_class_b._opstatus.beacon_on); + return _opstatus.beacon_on; } +public: /** * These locks trample through to the upper layers and make * the stack thread safe. @@ -175,72 +155,7 @@ public: void unlock(void) { } #endif - /** - * Constructor - */ - LoRaMacClassB(); - - /** - * Destructor - */ - ~LoRaMacClassB() {}; - -protected: - - /** - * Initialize class b system - * @param [in] lora_time - * @param [in] lora_phy - * @param [in] lora_crypto - * @param [in] open_rx_window function to open rx widnow - * @param [in] close_rx_window function to close rx widnow - */ - void initialize(LoRaWANTimeHandler *lora_time, LoRaPHY *lora_phy, - LoRaMacCrypto *lora_crypto, loramac_protocol_params *params, - mbed::Callback open_rx_window, - mbed::Callback close_rx_window); - - /** - * Enable beacon acquisition - * @param [in] beacon_event_cb - stack beacon event callback - */ - lorawan_status_t enable_beacon_acquisition(mbed::Callback beacon_event_cb); - /** - * @brief Enables class b mode - * @return[out] LORAWAN_STATUS_OK or negative error code - */ - lorawan_status_t enable(void); - - /** - * @brief Disables class b mode - */ - lorawan_status_t disable(void); - - /** - * @brief Pause class b mode - */ - void pause(void); - - /** - * @brief Resume class b mode - */ - void resume(void); - - /** - * @brief RX window timeout handler - * @param [in] rx_slot - */ - void handle_rx_timeout(rx_slot_t rx_slot) ; - - /** - * @brief RX window reception handler - * @param [in] rx_slot receive window - * @param [in] data received data - * @param [in] size data size in bytes - * @param [in] rx_timestamp radio receive time - */ - void handle_rx(rx_slot_t rx_slot, const uint8_t *const data, uint16_t size, uint32_t rx_timestamp); +private: /** * @brief Process frame received in beacon window @@ -337,19 +252,6 @@ protected: uint32_t address, uint16_t ping_slot_offset, uint16_t &next_slot_nb, rx_config_params_t &rx_config); - /** - * @brief Return precise device time - */ - inline lorawan_gps_time_t get_gps_time(void) - { - return _lora_time->get_gps_time(); - } - - /** - * Return last received beacon - */ - lorawan_status_t get_last_rx_beacon(loramac_beacon_t &beacon); - /** * Send beacon miss indication */ @@ -364,17 +266,6 @@ protected: return _protocol_params; } - /** - * @brief Adds multicast address to ping slots scheduling - */ - bool add_multicast_address(uint32_t address); - - - /** - * @brief Remove multicast address ping slot scheduling - */ - void remove_multicast_address(uint32_t address); - /** * Class B Window Expansion */ @@ -449,72 +340,10 @@ protected: mbed::Callback _close_rx_window; // loramac close rx window function mbed::Callback _beacon_event_cb; // beacon event callback - static LoRaMacClassB _loramac_class_b; - #if MBED_CONF_RTOS_PRESENT rtos::Mutex _mutex; #endif typedef mbed::ScopedLock Lock; + }; -#else -class LoRaMacClassB { - -public: - - inline static lorawan_status_t Initialize(LoRaWANTimeHandler *lora_time, - LoRaPHY *lora_phy, LoRaMacCrypto *lora_crypto, - loramac_protocol_params *params, - mbed::Callback open_rx_window, - mbed::Callback close_rx_window) - { - return LORAWAN_STATUS_UNSUPPORTED; - } - - inline static lorawan_status_t Enable_beacon_acquisition(mbed::Callback beacon_event_cb) - { - return LORAWAN_STATUS_UNSUPPORTED; - } - - inline static lorawan_status_t Enable(void) - { - return LORAWAN_STATUS_UNSUPPORTED; - } - - inline static lorawan_status_t Disable(void) - { - return LORAWAN_STATUS_UNSUPPORTED; - } - - inline static void Pause(void) - { - } - - inline static void Resume(void) - { - } - - inline static void Handle_rx_timeout(rx_slot_t rx_slot) - { - } - - inline static void Handle_rx(rx_slot_t rx_slot, const uint8_t *const data, uint16_t size, uint32_t rx_timestamp) - { - } - - inline static lorawan_status_t Get_last_rx_beacon(loramac_beacon_t &beacon) - { - return LORAWAN_STATUS_NO_BEACON_FOUND; - } - - inline static bool Add_multicast_address(uint32_t address) - { - return false; - } - - inline static void Remove_multicast_address(uint32_t address) - { - } -}; -#endif // #if LORA_CLASS_B_ENABLED #endif // #ifndef MBED_LORAWAN_LORAMACCLASSB_H_ \ No newline at end of file diff --git a/features/lorawan/lorastack/mac/LoRaMacClassBInterface.cpp b/features/lorawan/lorastack/mac/LoRaMacClassBInterface.cpp new file mode 100644 index 0000000000..38d6e612a7 --- /dev/null +++ b/features/lorawan/lorastack/mac/LoRaMacClassBInterface.cpp @@ -0,0 +1,5 @@ +#include "LoRaMacClassBInterface.h" + +#ifdef LORA_CLASS_B_ENABLED +LoRaMacClassB LoRaMacClassBInterface::_class_b; +#endif \ No newline at end of file diff --git a/features/lorawan/lorastack/mac/LoRaMacClassBInterface.h b/features/lorawan/lorastack/mac/LoRaMacClassBInterface.h new file mode 100644 index 0000000000..43956de8b0 --- /dev/null +++ b/features/lorawan/lorastack/mac/LoRaMacClassBInterface.h @@ -0,0 +1,161 @@ +#ifndef MBED_LORAWAN_LORAMACCLASSB_INTERFACE_H_ +#define MBED_LORAWAN_LORAMACCLASSB_INTERFACE_H_ +/** + * Copyright (c) 2017, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LoRaMacClassB.h" + +#if (MBED_CONF_LORA_VERSION >= 01) && (MBED_CONF_LORA_CLASS_B == true) +#define LORA_CLASS_B_ENABLED +#endif + +#ifdef LORA_CLASS_B_ENABLED + +/** LoRaWANClassBInterface provides the public interface to the + * LoRaMac Class B implementation + */ +class LoRaMacClassBInterface { + +public: + + inline static lorawan_status_t initialize(LoRaWANTimeHandler *lora_time, + LoRaPHY *lora_phy, LoRaMacCrypto *lora_crypto, + loramac_protocol_params *params, + mbed::Callback open_rx_window, + mbed::Callback close_rx_window) + { + return _class_b.initialize(lora_time, lora_phy, lora_crypto, params, open_rx_window, close_rx_window); + } + + inline static lorawan_status_t enable_beacon_acquisition(mbed::Callback beacon_event_cb) + { + return _class_b.enable_beacon_acquisition(beacon_event_cb); + } + + inline static lorawan_status_t enable(void) + { + return _class_b.enable(); + } + + inline static lorawan_status_t disable(void) + { + return _class_b.disable(); + } + + inline static void pause(void) + { + _class_b.pause(); + } + + inline static void resume(void) + { + _class_b.resume(); + } + + inline static void handle_rx_timeout(rx_slot_t rx_slot) + { + _class_b.handle_rx_timeout(rx_slot); + } + + inline static void handle_rx(rx_slot_t rx_slot, const uint8_t *const data, uint16_t size, uint32_t rx_timestamp) + { + _class_b.handle_rx(rx_slot, data, size, rx_timestamp); + } + + inline static lorawan_status_t get_last_rx_beacon(loramac_beacon_t &beacon) + { + return _class_b.get_last_rx_beacon(beacon); + } + + inline static bool add_multicast_address(uint32_t address) + { + return _class_b.add_multicast_address(address); + } + + inline static void remove_multicast_address(uint32_t address) + { + _class_b.remove_multicast_address(address); + } + + static LoRaMacClassB _class_b; +}; + +#else + +class LoRaMacClassBInterface { + +public: + + inline static lorawan_status_t initialize(LoRaWANTimeHandler *lora_time, + LoRaPHY *lora_phy, LoRaMacCrypto *lora_crypto, + loramac_protocol_params *params, + mbed::Callback open_rx_window, + mbed::Callback close_rx_window) + { + return LORAWAN_STATUS_UNSUPPORTED; + } + + inline static lorawan_status_t enable_beacon_acquisition(mbed::Callback beacon_event_cb) + { + return LORAWAN_STATUS_UNSUPPORTED; + } + + inline static lorawan_status_t enable(void) + { + return LORAWAN_STATUS_UNSUPPORTED; + } + + inline static lorawan_status_t disable(void) + { + return LORAWAN_STATUS_UNSUPPORTED; + } + + inline static void pause(void) + { + } + + inline static void resume(void) + { + } + + inline static void handle_rx_timeout(rx_slot_t rx_slot) + { + } + + inline static void handle_rx(rx_slot_t rx_slot, const uint8_t *const data, uint16_t size, uint32_t rx_timestamp) + { + } + + inline static lorawan_status_t get_last_rx_beacon(loramac_beacon_t &beacon) + { + return LORAWAN_STATUS_NO_BEACON_FOUND; + } + + inline static bool add_multicast_address(uint32_t address) + { + return false; + } + + inline static void remove_multicast_address(uint32_t address) + { + } +}; + +#endif // #if LORA_CLASS_B_ENABLED +#endif // #ifndef MBED_LORAWAN_LORAMACCLASSB_INTERFACE_H_ \ No newline at end of file