Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRaMac.cpp Source File

LoRaMac.cpp

00001 /**
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007     (C)2013 Semtech
00008  ___ _____ _   ___ _  _____ ___  ___  ___ ___
00009 / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
00010 \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
00011 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
00012 embedded.connectivity.solutions===============
00013 
00014 Description: LoRa MAC layer implementation
00015 
00016 License: Revised BSD License, see LICENSE.TXT file include in the project
00017 
00018 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
00019 
00020 Copyright (c) 2017, Arm Limited and affiliates.
00021 
00022 SPDX-License-Identifier: BSD-3-Clause
00023 */
00024 #include <stdlib.h>
00025 #include "LoRaMac.h"
00026 
00027 #include "mbed-trace/mbed_trace.h"
00028 #define TRACE_GROUP "LMAC"
00029 
00030 using namespace events;
00031 using namespace mbed;
00032 
00033 /*
00034  * LoRaWAN spec 6.2: AppKey is AES-128 key
00035  */
00036 #define APPKEY_KEY_LENGTH                           128
00037 
00038 /*!
00039  * Maximum length of the fOpts field
00040  */
00041 #define LORA_MAC_COMMAND_MAX_FOPTS_LENGTH           15
00042 
00043 /*!
00044  * LoRaMac duty cycle for the back-off procedure during the first hour.
00045  */
00046 #define BACKOFF_DC_1_HOUR                           100
00047 
00048 /*!
00049  * LoRaMac duty cycle for the back-off procedure during the next 10 hours.
00050  */
00051 #define BACKOFF_DC_10_HOURS                         1000
00052 
00053 /*!
00054  * LoRaMac duty cycle for the back-off procedure during the next 24 hours.
00055  */
00056 #define BACKOFF_DC_24_HOURS                         10000
00057 
00058 /*!
00059  * The frame direction definition for uplink communications.
00060  */
00061 #define UP_LINK                                     0
00062 
00063 /*!
00064  * The frame direction definition for downlink communications.
00065  */
00066 #define DOWN_LINK                                   1
00067 
00068 LoRaMac::LoRaMac()
00069     : _lora_time(),
00070       _lora_phy(NULL),
00071       _mac_commands(),
00072       _channel_plan(),
00073       _lora_crypto(),
00074       _ev_queue(NULL),
00075       _mcps_indication(),
00076       _mcps_confirmation(),
00077       _mlme_indication(),
00078       _mlme_confirmation(),
00079       _is_nwk_joined(false),
00080       _can_cancel_tx(true),
00081       _continuous_rx2_window_open(false),
00082       _device_class(CLASS_A),
00083       _prev_qos_level(LORAWAN_DEFAULT_QOS)
00084 {
00085     memset(&_params, 0, sizeof(_params));
00086     _params.keys.dev_eui = NULL;
00087     _params.keys.app_eui = NULL;
00088     _params.keys.app_key = NULL;
00089 
00090     memset(_params.keys.nwk_skey, 0, sizeof(_params.keys.nwk_skey));
00091     memset(_params.keys.app_skey, 0, sizeof(_params.keys.app_skey));
00092     memset(&_ongoing_tx_msg, 0, sizeof(_ongoing_tx_msg));
00093     memset(&_params.sys_params, 0, sizeof(_params.sys_params));
00094 
00095     _params.dev_nonce = 0;
00096     _params.net_id = 0;
00097     _params.dev_addr = 0;
00098     _params.tx_buffer_len = 0;
00099     _params.rx_buffer_len = 0;
00100     _params.ul_frame_counter = 0;
00101     _params.dl_frame_counter = 0;
00102     _params.is_ul_frame_counter_fixed = false;
00103     _params.is_rx_window_enabled = true;
00104     _params.adr_ack_counter = 0;
00105     _params.is_node_ack_requested = false;
00106     _params.is_srv_ack_requested = false;
00107     _params.ul_nb_rep_counter = 0;
00108     _params.timers.mac_init_time = 0;
00109     _params.max_ack_timeout_retries = 1;
00110     _params.ack_timeout_retry_counter = 1;
00111     _params.is_ack_retry_timeout_expired = false;
00112     _params.timers.tx_toa = 0;
00113 
00114     _params.multicast_channels = NULL;
00115 
00116 
00117     _params.sys_params.adr_on = false;
00118     _params.sys_params.max_duty_cycle = 0;
00119 
00120     reset_mcps_confirmation();
00121     reset_mlme_confirmation();
00122     reset_mcps_indication();
00123 }
00124 
00125 LoRaMac::~LoRaMac()
00126 {
00127 }
00128 
00129 /***************************************************************************
00130  * Radio event callbacks - delegated to Radio driver                       *
00131  **************************************************************************/
00132 
00133 const loramac_mcps_confirm_t  *LoRaMac::get_mcps_confirmation() const
00134 {
00135     return &_mcps_confirmation;
00136 }
00137 
00138 const loramac_mcps_indication_t  *LoRaMac::get_mcps_indication() const
00139 {
00140     return &_mcps_indication;
00141 }
00142 
00143 const loramac_mlme_confirm_t  *LoRaMac::get_mlme_confirmation() const
00144 {
00145     return &_mlme_confirmation;
00146 }
00147 
00148 const loramac_mlme_indication_t  *LoRaMac::get_mlme_indication() const
00149 {
00150     return &_mlme_indication;
00151 }
00152 
00153 void LoRaMac::post_process_mlme_request()
00154 {
00155     _mlme_confirmation.pending = false;
00156 }
00157 
00158 void LoRaMac::post_process_mcps_req()
00159 {
00160     _params.is_last_tx_join_request = false;
00161     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00162     if (_mcps_confirmation.req_type == MCPS_CONFIRMED ) {
00163         // An MCPS request for a CONFIRMED message has received an ack
00164         // in the downlink message
00165         if (_mcps_confirmation.ack_received) {
00166             _params.is_node_ack_requested = false;
00167             _mcps_confirmation.ack_received = false;
00168             _mcps_indication.is_ack_recvd = false;
00169             if (_params.is_ul_frame_counter_fixed == false) {
00170                 _params.ul_frame_counter++;
00171                 _params.adr_ack_counter++;
00172             }
00173         } else {
00174             _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00175         }
00176     } else {
00177         //UNCONFIRMED or PROPRIETARY
00178         if (_params.is_ul_frame_counter_fixed == false) {
00179             _params.ul_frame_counter++;
00180             _params.adr_ack_counter++;
00181             if (_params.sys_params.nb_trans > 1) {
00182                 _mcps_confirmation.nb_retries = _params.ul_nb_rep_counter;
00183             }
00184         }
00185     }
00186 }
00187 
00188 void LoRaMac::post_process_mcps_ind()
00189 {
00190     _mcps_indication.pending = false;
00191 }
00192 
00193 void LoRaMac::post_process_mlme_ind()
00194 {
00195     _mlme_indication.pending = false;
00196 }
00197 
00198 lorawan_time_t LoRaMac::get_current_time(void)
00199 {
00200     return _lora_time.get_current_time();
00201 }
00202 
00203 rx_slot_t  LoRaMac::get_current_slot(void)
00204 {
00205     return _params.rx_slot;
00206 }
00207 
00208 /**
00209  * This part handles incoming frames in response to Radio RX Interrupt
00210  */
00211 void LoRaMac::handle_join_accept_frame(const uint8_t *payload, uint16_t size)
00212 {
00213     uint32_t mic = 0;
00214     uint32_t mic_rx = 0;
00215 
00216     _mlme_confirmation.nb_retries = _params.join_request_trial_counter;
00217 
00218     if (0 != _lora_crypto.decrypt_join_frame(payload + 1, size - 1,
00219                                              _params.keys.app_key, APPKEY_KEY_LENGTH,
00220                                              _params.rx_buffer + 1)) {
00221         _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00222         return;
00223     }
00224 
00225     _params.rx_buffer[0] = payload[0];
00226 
00227     if (_lora_crypto.compute_join_frame_mic(_params.rx_buffer,
00228                                             size - LORAMAC_MFR_LEN,
00229                                             _params.keys.app_key,
00230                                             APPKEY_KEY_LENGTH,
00231                                             &mic) != 0) {
00232         _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00233         return;
00234     }
00235 
00236     mic_rx |= (uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN];
00237     mic_rx |= ((uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN + 1] << 8);
00238     mic_rx |= ((uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN + 2] << 16);
00239     mic_rx |= ((uint32_t) _params.rx_buffer[size - LORAMAC_MFR_LEN + 3] << 24);
00240 
00241     if (mic_rx == mic) {
00242         _lora_time.stop(_params.timers.rx_window2_timer);
00243         if (_lora_crypto.compute_skeys_for_join_frame(_params.keys.app_key,
00244                                                       APPKEY_KEY_LENGTH,
00245                                                       _params.rx_buffer + 1,
00246                                                       _params.dev_nonce,
00247                                                       _params.keys.nwk_skey,
00248                                                       _params.keys.app_skey) != 0) {
00249             _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00250             return;
00251         }
00252 
00253         _params.net_id = (uint32_t) _params.rx_buffer[4];
00254         _params.net_id |= ((uint32_t) _params.rx_buffer[5] << 8);
00255         _params.net_id |= ((uint32_t) _params.rx_buffer[6] << 16);
00256 
00257         _params.dev_addr = (uint32_t) _params.rx_buffer[7];
00258         _params.dev_addr |= ((uint32_t) _params.rx_buffer[8] << 8);
00259         _params.dev_addr |= ((uint32_t) _params.rx_buffer[9] << 16);
00260         _params.dev_addr |= ((uint32_t) _params.rx_buffer[10] << 24);
00261 
00262         _params.sys_params.rx1_dr_offset = (_params.rx_buffer[11] >> 4) & 0x07;
00263         _params.sys_params.rx2_channel.datarate = _params.rx_buffer[11] & 0x0F;
00264 
00265         _params.sys_params.recv_delay1 = (_params.rx_buffer[12] & 0x0F);
00266 
00267         if (_params.sys_params.recv_delay1 == 0) {
00268             _params.sys_params.recv_delay1 = 1;
00269         }
00270 
00271         _params.sys_params.recv_delay1 *= 1000;
00272         _params.sys_params.recv_delay2 = _params.sys_params.recv_delay1 + 1000;
00273 
00274         // Size of the regular payload is 12. Plus 1 byte MHDR and 4 bytes MIC
00275         _lora_phy->apply_cf_list(&_params.rx_buffer[13], size - 17);
00276 
00277         _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00278         _is_nwk_joined = true;
00279         // Node joined successfully
00280         _params.ul_frame_counter = 0;
00281         _params.ul_nb_rep_counter = 0;
00282         _params.adr_ack_counter = 0;
00283 
00284     } else {
00285         _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL ;
00286     }
00287 }
00288 
00289 void LoRaMac::check_frame_size(uint16_t size)
00290 {
00291     uint8_t value = _lora_phy->get_max_payload(_mcps_indication.rx_datarate,
00292                                               _params.is_repeater_supported);
00293 
00294     if (MAX(0, (int16_t)((int16_t)size - (int16_t)LORA_MAC_FRMPAYLOAD_OVERHEAD))
00295             > (int32_t) value) {
00296         tr_error("Invalid frame size");
00297     }
00298 }
00299 
00300 bool LoRaMac::message_integrity_check(const uint8_t *const payload,
00301                                       const uint16_t size,
00302                                       uint8_t *const ptr_pos,
00303                                       uint32_t address,
00304                                       uint32_t *downlink_counter,
00305                                       const uint8_t *nwk_skey)
00306 {
00307     uint32_t mic = 0;
00308     uint32_t mic_rx = 0;
00309 
00310     uint16_t sequence_counter = 0;
00311     uint16_t sequence_counter_prev = 0;
00312     uint16_t sequence_counter_diff = 0;
00313 
00314     sequence_counter = (uint16_t) payload[(*ptr_pos)++];
00315     sequence_counter |= (uint16_t) payload[(*ptr_pos)++] << 8;
00316 
00317     mic_rx |= (uint32_t) payload[size - LORAMAC_MFR_LEN];
00318     mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 1] << 8);
00319     mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 2] << 16);
00320     mic_rx |= ((uint32_t) payload[size - LORAMAC_MFR_LEN + 3] << 24);
00321 
00322     sequence_counter_prev = (uint16_t)*downlink_counter;
00323     sequence_counter_diff = sequence_counter - sequence_counter_prev;
00324     *downlink_counter += sequence_counter_diff;
00325     if (sequence_counter < sequence_counter_prev) {
00326         *downlink_counter += 0x10000;
00327     }
00328 
00329     // sizeof nws_skey must be the same as _params.keys.nwk_skey,
00330     _lora_crypto.compute_mic(payload, size - LORAMAC_MFR_LEN,
00331                              nwk_skey,
00332                              sizeof(_params.keys.nwk_skey) * 8,
00333                              address, DOWN_LINK, *downlink_counter, &mic);
00334 
00335     if (mic_rx != mic) {
00336         _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL ;
00337         return false;
00338     }
00339 
00340     if (sequence_counter_diff >= _lora_phy->get_maximum_frame_counter_gap()) {
00341         _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOST ;
00342         _mcps_indication.dl_frame_counter = *downlink_counter;
00343         return false;
00344     }
00345 
00346     return true;
00347 }
00348 
00349 void LoRaMac::extract_data_and_mac_commands(const uint8_t *payload,
00350                                             uint16_t size,
00351                                             uint8_t fopts_len,
00352                                             uint8_t *nwk_skey,
00353                                             uint8_t *app_skey,
00354                                             uint32_t address,
00355                                             uint32_t downlink_counter,
00356                                             int16_t rssi,
00357                                             int8_t snr)
00358 {
00359     uint8_t frame_len = 0;
00360     uint8_t payload_start_index = 8 + fopts_len;
00361     uint8_t port = payload[payload_start_index++];
00362     frame_len = (size - 4) - payload_start_index;
00363 
00364     _mcps_indication.port = port;
00365 
00366     // special handling of control port 0
00367     if (port == 0) {
00368         if (fopts_len == 0) {
00369             // sizeof nws_skey must be the same as _params.keys.nwk_skey,
00370             if (_lora_crypto.decrypt_payload(payload + payload_start_index,
00371                                              frame_len,
00372                                              nwk_skey,
00373                                              sizeof(_params.keys.nwk_skey) * 8,
00374                                              address,
00375                                              DOWN_LINK,
00376                                              downlink_counter,
00377                                              _params.rx_buffer) != 0) {
00378                 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00379             }
00380 
00381             if (_mac_commands.process_mac_commands(_params.rx_buffer, 0, frame_len,
00382                                                    snr, _mlme_confirmation,
00383                                                    _params.sys_params, *_lora_phy)
00384                     != LORAWAN_STATUS_OK) {
00385                 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00386                 return;
00387             }
00388 
00389             if (_mac_commands.has_sticky_mac_cmd()) {
00390                 set_mlme_schedule_ul_indication();
00391                 _mac_commands.clear_sticky_mac_cmd();
00392             }
00393 
00394             return;
00395         }
00396 
00397         _mcps_indication.pending = false;
00398         _mcps_confirmation.ack_received = false;
00399         _mcps_indication.is_ack_recvd = false;
00400 
00401         return;
00402     }
00403 
00404     // normal unicast/multicast port handling
00405     if (fopts_len > 0) {
00406         // Decode Options field MAC commands. Omit the fPort.
00407         if (_mac_commands.process_mac_commands(payload, 8,
00408                                                payload_start_index - 1,
00409                                                snr,
00410                                                _mlme_confirmation,
00411                                                _params.sys_params,
00412                                                *_lora_phy) != LORAWAN_STATUS_OK) {
00413             _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00414             return;
00415         }
00416 
00417         if (_mac_commands.has_sticky_mac_cmd()) {
00418             set_mlme_schedule_ul_indication();
00419             _mac_commands.clear_sticky_mac_cmd();
00420         }
00421     }
00422 
00423     // sizeof app_skey must be the same as _params.keys.app_skey
00424     if (_lora_crypto.decrypt_payload(payload + payload_start_index,
00425                                      frame_len,
00426                                      app_skey,
00427                                      sizeof(_params.keys.app_skey) * 8,
00428                                      address,
00429                                      DOWN_LINK,
00430                                      downlink_counter,
00431                                      _params.rx_buffer) != 0) {
00432         _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00433     } else {
00434         _mcps_indication.buffer = _params.rx_buffer;
00435         _mcps_indication.buffer_size = frame_len;
00436         _mcps_indication.is_data_recvd = true;
00437     }
00438 }
00439 
00440 void LoRaMac::extract_mac_commands_only(const uint8_t *payload,
00441                                         int8_t snr,
00442                                         uint8_t fopts_len)
00443 {
00444     uint8_t payload_start_index = 8 + fopts_len;
00445     if (fopts_len > 0) {
00446         if (_mac_commands.process_mac_commands(payload, 8, payload_start_index,
00447                                                snr, _mlme_confirmation,
00448                                                _params.sys_params, *_lora_phy)
00449                 != LORAWAN_STATUS_OK) {
00450             _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00451             return;
00452         }
00453 
00454         if (_mac_commands.has_sticky_mac_cmd()) {
00455             set_mlme_schedule_ul_indication();
00456             _mac_commands.clear_sticky_mac_cmd();
00457         }
00458     }
00459 }
00460 
00461 void LoRaMac::handle_data_frame(const uint8_t *const payload,
00462                                 const uint16_t size,
00463                                 uint8_t ptr_pos,
00464                                 uint8_t msg_type,
00465                                 int16_t rssi,
00466                                 int8_t snr)
00467 {
00468     check_frame_size(size);
00469 
00470     bool is_multicast = false;
00471     loramac_frame_ctrl_t  fctrl;
00472     multicast_params_t  *cur_multicast_params;
00473     uint32_t address = 0;
00474     uint32_t downlink_counter = 0;
00475     uint8_t app_payload_start_index = 0;
00476     uint8_t *nwk_skey = _params.keys.nwk_skey ;
00477     uint8_t *app_skey = _params.keys.app_skey;
00478 
00479     address = payload[ptr_pos++];
00480     address |= ((uint32_t) payload[ptr_pos++] << 8);
00481     address |= ((uint32_t) payload[ptr_pos++] << 16);
00482     address |= ((uint32_t) payload[ptr_pos++] << 24);
00483 
00484     if (address != _params.dev_addr) {
00485         // check if Multicast is destined for us
00486         cur_multicast_params = _params.multicast_channels;
00487 
00488         while (cur_multicast_params != NULL) {
00489             if (address == cur_multicast_params->address ) {
00490                 is_multicast = true;
00491                 nwk_skey = cur_multicast_params->nwk_skey ;
00492                 app_skey = cur_multicast_params->app_skey ;
00493                 downlink_counter = cur_multicast_params->dl_frame_counter ;
00494                 break;
00495             }
00496 
00497             cur_multicast_params = cur_multicast_params->next ;
00498         }
00499 
00500         if (!is_multicast) {
00501             // We are not the destination of this frame.
00502             _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL ;
00503             _mcps_indication.pending = false;
00504             return;
00505         }
00506     } else {
00507         is_multicast = false;
00508         nwk_skey = _params.keys.nwk_skey;
00509         app_skey = _params.keys.app_skey;
00510         downlink_counter = _params.dl_frame_counter;
00511     }
00512 
00513     fctrl.value  = payload[ptr_pos++];
00514     app_payload_start_index = 8 + fctrl.bits.fopts_len ;
00515 
00516     //perform MIC check
00517     if (!message_integrity_check(payload, size, &ptr_pos, address,
00518                                  &downlink_counter, nwk_skey)) {
00519         tr_error("MIC failed");
00520         _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL ;
00521         _mcps_indication.pending = false;
00522         return;
00523     }
00524 
00525     _mcps_confirmation.ack_received = false;
00526     _mcps_indication.is_ack_recvd = false;
00527     _mcps_indication.pending = true;
00528     _mcps_indication.is_data_recvd = false;
00529     _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00530     _mcps_indication.multicast = is_multicast;
00531     _mcps_indication.fpending_status = fctrl.bits.fpending ;
00532     _mcps_indication.buffer = NULL;
00533     _mcps_indication.buffer_size = 0;
00534     _mcps_indication.dl_frame_counter = downlink_counter;
00535     _mcps_indication.rssi = rssi;
00536     _mcps_indication.snr = snr;
00537 
00538     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00539 
00540     _params.adr_ack_counter = 0;
00541     _mac_commands.clear_repeat_buffer();
00542     _mac_commands.clear_command_buffer();
00543 
00544     if (is_multicast) {
00545         _mcps_indication.type = MCPS_MULTICAST ;
00546 
00547         // Discard if its a repeated message
00548         if ((cur_multicast_params->dl_frame_counter  == downlink_counter)
00549                 && (cur_multicast_params->dl_frame_counter  != 0)) {
00550             _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ;
00551             _mcps_indication.dl_frame_counter = downlink_counter;
00552             _mcps_indication.pending = false;
00553 
00554             return;
00555         }
00556 
00557         cur_multicast_params->dl_frame_counter  = downlink_counter;
00558 
00559     } else {
00560         if (msg_type == FRAME_TYPE_DATA_CONFIRMED_DOWN ) {
00561             _params.is_srv_ack_requested = true;
00562             _mcps_indication.type = MCPS_CONFIRMED ;
00563 
00564             if ((_params.dl_frame_counter == downlink_counter)
00565                     && (_params.dl_frame_counter != 0)) {
00566                 // Duplicated confirmed downlink. Skip indication.
00567                 // In this case, the MAC layer shall accept the MAC commands
00568                 // which are included in the downlink retransmission.
00569                 // It should not provide the same frame to the application
00570                 // layer again. The MAC layer accepts the acknowledgement.
00571                 tr_debug("Discarding duplicate frame");
00572                 _mcps_indication.pending = false;
00573                 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ;
00574 
00575                 return;
00576             }
00577         } else if (msg_type == FRAME_TYPE_DATA_UNCONFIRMED_DOWN ) {
00578             _params.is_srv_ack_requested = false;
00579             _mcps_indication.type = MCPS_UNCONFIRMED ;
00580 
00581             if ((_params.dl_frame_counter == downlink_counter)
00582                     && (_params.dl_frame_counter != 0)) {
00583                 tr_debug("Discarding duplicate frame");
00584                 _mcps_indication.pending = false;
00585                 _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ;
00586 
00587                 return;
00588             }
00589         }
00590         _params.dl_frame_counter = downlink_counter;
00591     }
00592 
00593     // message is intended for us and MIC have passed, stop RX2 Window
00594     // Spec: 3.3.4 Receiver Activity during the receive windows
00595     if (get_current_slot() == RX_SLOT_WIN_1 ) {
00596         _lora_time.stop(_params.timers.rx_window2_timer);
00597     } else {
00598         _lora_time.stop(_params.timers.rx_window1_timer);
00599         _lora_time.stop(_params.timers.rx_window2_timer);
00600     }
00601 
00602     if (_device_class == CLASS_C) {
00603          _lora_time.stop(_rx2_closure_timer_for_class_c);
00604      }
00605 
00606     if (_params.is_node_ack_requested && fctrl.bits.ack ) {
00607         _mcps_confirmation.ack_received = fctrl.bits.ack ;
00608         _mcps_indication.is_ack_recvd = fctrl.bits.ack ;
00609     }
00610 
00611     uint8_t frame_len = (size - 4) - app_payload_start_index;
00612 
00613     if (frame_len > 0) {
00614         extract_data_and_mac_commands(payload, size, fctrl.bits.fopts_len ,
00615                                       nwk_skey, app_skey, address,
00616                                       downlink_counter, rssi, snr);
00617     } else {
00618         extract_mac_commands_only(payload, snr, fctrl.bits.fopts_len );
00619     }
00620 
00621     // Handle proprietary messages.
00622     if (msg_type == FRAME_TYPE_PROPRIETARY ) {
00623         memcpy(_params.rx_buffer, &payload[ptr_pos], size);
00624 
00625         _mcps_indication.type = MCPS_PROPRIETARY ;
00626         _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00627         _mcps_indication.buffer = _params.rx_buffer;
00628         _mcps_indication.buffer_size = size - ptr_pos;
00629     }
00630 
00631     // only stop act timer, if the ack is actually recieved
00632     if (_mcps_confirmation.ack_received) {
00633         _lora_time.stop(_params.timers.ack_timeout_timer);
00634     }
00635 }
00636 
00637 void LoRaMac::set_batterylevel_callback(mbed::Callback<uint8_t(void)> battery_level)
00638 {
00639     _mac_commands.set_batterylevel_callback(battery_level);
00640 }
00641 
00642 void LoRaMac::on_radio_tx_done(lorawan_time_t timestamp)
00643 {
00644     if (_device_class == CLASS_C) {
00645         // this will open a continuous RX2 window until time==RECV_DELAY1
00646         open_rx2_window();
00647     } else {
00648         _lora_phy->put_radio_to_sleep();
00649     }
00650 
00651     if ((_mcps_confirmation.req_type == MCPS_UNCONFIRMED )
00652             && (_params.sys_params.nb_trans > 1)) {
00653         _params.ul_nb_rep_counter++;
00654         MBED_ASSERT(_params.ul_nb_rep_counter <= _params.sys_params.nb_trans);
00655     }
00656 
00657     if (_params.is_rx_window_enabled == true) {
00658         lorawan_time_t time_diff = _lora_time.get_current_time() - timestamp;
00659         // start timer after which rx1_window will get opened
00660         _lora_time.start(_params.timers.rx_window1_timer,
00661                          _params.rx_window1_delay - time_diff);
00662 
00663         // start timer after which rx2_window will get opened
00664         _lora_time.start(_params.timers.rx_window2_timer,
00665                          _params.rx_window2_delay - time_diff);
00666 
00667         // If class C and an Unconfirmed messgae is outgoing,
00668         // this will start a timer which will invoke rx2 would be
00669         // closure handler
00670         if (get_device_class() == CLASS_C) {
00671             _lora_time.start(_rx2_closure_timer_for_class_c,
00672                              (_params.rx_window2_delay - time_diff) +
00673                              _params.rx_window2_config.window_timeout);
00674         }
00675 
00676         // start timer after which ack wait will timeout (for Confirmed messages)
00677         if (_params.is_node_ack_requested) {
00678             _lora_time.start(_params.timers.ack_timeout_timer,
00679                              (_params.rx_window2_delay - time_diff) +
00680                              _lora_phy->get_ack_timeout());
00681         }
00682     } else {
00683         _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_OK ;
00684         _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ;
00685     }
00686 
00687     _params.last_channel_idx = _params.channel;
00688 
00689     _lora_phy->set_last_tx_done(_params.channel, _is_nwk_joined, timestamp);
00690 
00691     _params.timers.aggregated_last_tx_time = timestamp;
00692 
00693     _mac_commands.clear_command_buffer();
00694 }
00695 
00696 void LoRaMac::on_radio_rx_done(const uint8_t *const payload, uint16_t size,
00697                                int16_t rssi, int8_t snr)
00698 {
00699     if (_device_class == CLASS_C && !_continuous_rx2_window_open) {
00700         _lora_time.stop(_rx2_closure_timer_for_class_c);
00701         open_rx2_window();
00702     } else if (_device_class != CLASS_C){
00703         _lora_time.stop(_params.timers.rx_window1_timer);
00704         _lora_phy->put_radio_to_sleep();
00705     }
00706 
00707     loramac_mhdr_t  mac_hdr;
00708     uint8_t pos = 0;
00709     mac_hdr.value  = payload[pos++];
00710 
00711     switch (mac_hdr.bits.mtype ) {
00712 
00713         case FRAME_TYPE_JOIN_ACCEPT :
00714 
00715             if (nwk_joined()) {
00716                 _mlme_confirmation.pending = false;
00717                 return;
00718             } else {
00719                 handle_join_accept_frame(payload, size);
00720                 _mlme_confirmation.pending = true;
00721             }
00722 
00723             break;
00724 
00725         case FRAME_TYPE_DATA_UNCONFIRMED_DOWN :
00726         case FRAME_TYPE_DATA_CONFIRMED_DOWN :
00727         case FRAME_TYPE_PROPRIETARY :
00728 
00729             handle_data_frame(payload, size, pos, mac_hdr.bits.mtype , rssi, snr);
00730 
00731             break;
00732 
00733         default:
00734             break;
00735     }
00736 }
00737 
00738 void LoRaMac::on_radio_tx_timeout(void)
00739 {
00740     _lora_time.stop(_params.timers.rx_window1_timer);
00741     _lora_time.stop(_params.timers.rx_window2_timer);
00742     _lora_time.stop(_rx2_closure_timer_for_class_c);
00743     _lora_time.stop(_params.timers.ack_timeout_timer);
00744 
00745     if (_device_class == CLASS_C) {
00746         open_rx2_window();
00747     } else {
00748         _lora_phy->put_radio_to_sleep();
00749     }
00750 
00751     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ;
00752     _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ;
00753 
00754     _mac_commands.clear_command_buffer();
00755 
00756     if (_mcps_confirmation.req_type == MCPS_CONFIRMED ) {
00757         _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter;
00758     } else {
00759         _mcps_confirmation.nb_retries = _params.ul_nb_rep_counter;
00760     }
00761 
00762     _mcps_confirmation.ack_received = false;
00763     _mcps_confirmation.tx_toa = 0;
00764 }
00765 
00766 void LoRaMac::on_radio_rx_timeout(bool is_timeout)
00767 {
00768     if (_device_class == CLASS_A) {
00769         _lora_phy->put_radio_to_sleep();
00770     }
00771 
00772     if (_params.rx_slot == RX_SLOT_WIN_1 ) {
00773         if (_params.is_node_ack_requested == true) {
00774             _mcps_confirmation.status = is_timeout ?
00775                                         LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT  :
00776                                         LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ;
00777         }
00778         _mlme_confirmation.status = is_timeout ?
00779                                     LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT  :
00780                                     LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ;
00781 
00782         if (_device_class != CLASS_C) {
00783             if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) {
00784                 _lora_time.stop(_params.timers.rx_window2_timer);
00785             }
00786         }
00787     } else {
00788         if (_params.is_node_ack_requested == true) {
00789             _mcps_confirmation.status = is_timeout ?
00790                                         LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT  :
00791                                         LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ;
00792         }
00793 
00794         _mlme_confirmation.status = is_timeout ?
00795                                     LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT  :
00796                                     LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ;
00797     }
00798 }
00799 
00800 bool LoRaMac::continue_joining_process()
00801 {
00802     if (_params.join_request_trial_counter >= _params.max_join_request_trials) {
00803         return false;
00804     }
00805 
00806     // Schedule a retry
00807     if (handle_retransmission() != LORAWAN_STATUS_CONNECT_IN_PROGRESS) {
00808         return false;
00809     }
00810 
00811     return true;
00812 }
00813 
00814 bool LoRaMac::continue_sending_process()
00815 {
00816     if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) {
00817         _lora_time.stop(_params.timers.ack_timeout_timer);
00818         return false;
00819     }
00820 
00821     // retransmission will be handled in on_ack_timeout() whence the ACK timeout
00822     // gets fired
00823     return true;
00824 }
00825 
00826 lorawan_status_t LoRaMac::send_join_request()
00827 {
00828     lorawan_status_t status = LORAWAN_STATUS_OK;
00829     loramac_mhdr_t  mac_hdr;
00830     loramac_frame_ctrl_t  fctrl;
00831 
00832     _params.sys_params.channel_data_rate =
00833         _lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1);
00834 
00835     mac_hdr.value  = 0;
00836     mac_hdr.bits.mtype  = FRAME_TYPE_JOIN_REQ ;
00837 
00838     fctrl.value  = 0;
00839     fctrl.bits.adr  = _params.sys_params.adr_on;
00840     _params.is_last_tx_join_request = true;
00841 
00842     /* In case of join request retransmissions, the stack must prepare
00843      * the frame again, because the network server keeps track of the random
00844      * LoRaMacDevNonce values to prevent reply attacks. */
00845     status = prepare_frame(&mac_hdr, &fctrl, 0, NULL, 0);
00846 
00847     if (status == LORAWAN_STATUS_OK) {
00848         if (schedule_tx() == LORAWAN_STATUS_OK) {
00849             status = LORAWAN_STATUS_CONNECT_IN_PROGRESS;
00850         }
00851     } else {
00852         tr_error("Couldn't send a JoinRequest: error %d", status);
00853     }
00854 
00855     return status;
00856 }
00857 
00858 /**
00859  * This function handles retransmission of failed or unacknowledged
00860  * outgoing traffic
00861  */
00862 lorawan_status_t LoRaMac::handle_retransmission()
00863 {
00864     if (!nwk_joined() && (_mlme_confirmation.req_type == MLME_JOIN )) {
00865         return send_join_request();
00866     }
00867 
00868     return schedule_tx();
00869 }
00870 
00871 /**
00872  * This function is called when the backoff_timer gets fired.
00873  * It is used for re-scheduling an unsent packet in the pipe. This packet
00874  * can be a Join Request or any other data packet.
00875  */
00876 void LoRaMac::on_backoff_timer_expiry(void)
00877 {
00878     Lock lock(*this);
00879 
00880     _lora_time.stop(_params.timers.backoff_timer);
00881 
00882     if ((schedule_tx() != LORAWAN_STATUS_OK) && nwk_joined()) {
00883         _scheduling_failure_handler.call();
00884     }
00885 }
00886 
00887 void LoRaMac::open_rx1_window(void)
00888 {
00889     Lock lock(*this);
00890     _continuous_rx2_window_open = false;
00891     _lora_time.stop(_params.timers.rx_window1_timer);
00892     _params.rx_slot = RX_SLOT_WIN_1 ;
00893 
00894     _params.rx_window1_config.channel = _params.channel;
00895     _params.rx_window1_config.dr_offset = _params.sys_params.rx1_dr_offset;
00896     _params.rx_window1_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
00897     _params.rx_window1_config.is_repeater_supported = _params.is_repeater_supported;
00898     _params.rx_window1_config.is_rx_continuous = false;
00899     _params.rx_window1_config.rx_slot = _params.rx_slot;
00900 
00901     if (_device_class == CLASS_C) {
00902         _lora_phy->put_radio_to_standby();
00903     }
00904 
00905     _mcps_indication.rx_datarate = _params.rx_window1_config.datarate;
00906 
00907     _lora_phy->rx_config(&_params.rx_window1_config);
00908     _lora_phy->handle_receive();
00909 
00910     tr_debug("RX1 slot open, Freq = %lu", _params.rx_window1_config.frequency);
00911 }
00912 
00913 void LoRaMac::open_rx2_window()
00914 {
00915     Lock lock(*this);
00916     _continuous_rx2_window_open = true;
00917     _lora_time.stop(_params.timers.rx_window2_timer);
00918 
00919     _params.rx_window2_config.channel = _params.channel;
00920     _params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency;
00921     _params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
00922     _params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported;
00923 
00924     if (get_device_class() == CLASS_C) {
00925         _params.rx_window2_config.is_rx_continuous = true;
00926     } else {
00927         _params.rx_window2_config.is_rx_continuous = false;
00928     }
00929 
00930     _params.rx_window2_config.rx_slot = _params.rx_window2_config.is_rx_continuous ?
00931                                         RX_SLOT_WIN_CLASS_C  : RX_SLOT_WIN_2 ;
00932 
00933     _mcps_indication.rx_datarate = _params.rx_window2_config.datarate;
00934 
00935     _lora_phy->rx_config(&_params.rx_window2_config);
00936     _lora_phy->handle_receive();
00937     _params.rx_slot = _params.rx_window2_config.rx_slot;
00938 
00939     tr_debug("RX2 slot open, Freq = %lu", _params.rx_window2_config.frequency);
00940 }
00941 
00942 void LoRaMac::on_ack_timeout_timer_event(void)
00943 {
00944     Lock lock(*this);
00945 
00946     if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) {
00947         return;
00948     }
00949 
00950     tr_debug("ACK_TIMEOUT Elapses, Retrying ...");
00951     _lora_time.stop(_params.timers.ack_timeout_timer);
00952 
00953     // reduce data rate on every 2nd attempt if and only if the
00954     // ADR is on
00955     if ((_params.ack_timeout_retry_counter % 2)
00956             && (_params.sys_params.adr_on)) {
00957         tr_debug("Trading datarate for range");
00958         _params.sys_params.channel_data_rate = _lora_phy->get_next_lower_tx_datarate(_params.sys_params.channel_data_rate);
00959     }
00960 
00961     _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter;
00962 
00963 
00964     // Schedule a retry
00965     lorawan_status_t status = handle_retransmission();
00966 
00967     if (status == LORAWAN_STATUS_NO_CHANNEL_FOUND ||
00968             status == LORAWAN_STATUS_NO_FREE_CHANNEL_FOUND) {
00969         // In a case when enabled channels are not found, PHY layer
00970         // resorts to default channels. Next attempt should go forward as the
00971         // default channels are always available if there is a base station in the
00972         // vicinity. Otherwise something is wrong with the stack, we should assert
00973         // here
00974         _mac_commands.clear_command_buffer();
00975         _params.is_node_ack_requested = false;
00976         _mcps_confirmation.ack_received = false;
00977         _mcps_confirmation.nb_retries = _params.ack_timeout_retry_counter;
00978 
00979         // For the next attempt we need to make sure that we do not incur length error
00980         // which would mean that the datarate changed during retransmissions and
00981         // the original packet doesn't fit into allowed payload buffer anymore.
00982         status = handle_retransmission();
00983 
00984         if (status == LORAWAN_STATUS_LENGTH_ERROR) {
00985             _scheduling_failure_handler.call();
00986             return;
00987         }
00988 
00989         // if we did not incur a length error and still the status is not OK,
00990         // it is a critical failure
00991         status = handle_retransmission();
00992         MBED_ASSERT(status == LORAWAN_STATUS_OK);
00993         (void) status;
00994     } else if (status != LORAWAN_STATUS_OK) {
00995         _scheduling_failure_handler.call();
00996         return;
00997     }
00998 
00999     _params.ack_timeout_retry_counter++;
01000 }
01001 
01002 bool LoRaMac::validate_payload_length(uint16_t length,
01003                                       int8_t datarate,
01004                                       uint8_t fopts_len)
01005 {
01006     uint16_t max_value = 0;
01007     uint16_t payloadSize = 0;
01008 
01009     max_value = _lora_phy->get_max_payload(datarate, _params.is_repeater_supported);
01010 
01011     // Calculate the resulting payload size
01012     payloadSize = (length + fopts_len);
01013 
01014     // Validation of the application payload size
01015     if ((payloadSize <= max_value) &&
01016             (payloadSize <= LORAMAC_PHY_MAXPAYLOAD)) {
01017         return true;
01018     }
01019     return false;
01020 }
01021 
01022 void LoRaMac::set_mlme_schedule_ul_indication(void)
01023 {
01024     _mlme_indication.indication_type = MLME_SCHEDULE_UPLINK ;
01025     _mlme_indication.pending = true;
01026 }
01027 
01028 // This is not actual transmission. It just schedules a message in response
01029 // to MCPS request
01030 lorawan_status_t LoRaMac::send(loramac_mhdr_t  *machdr, const uint8_t fport,
01031                                const void *fbuffer, uint16_t fbuffer_size)
01032 {
01033     loramac_frame_ctrl_t  fctrl;
01034 
01035     fctrl.value  = 0;
01036     fctrl.bits.fopts_len  = 0;
01037     fctrl.bits.fpending  = 0;
01038     fctrl.bits.ack  = false;
01039     fctrl.bits.adr_ack_req  = false;
01040     fctrl.bits.adr  = _params.sys_params.adr_on;
01041 
01042     lorawan_status_t status = prepare_frame(machdr, &fctrl, fport, fbuffer,
01043                                             fbuffer_size);
01044 
01045     if (status != LORAWAN_STATUS_OK) {
01046         return status;
01047     }
01048 
01049     // Reset confirm parameters
01050     _mcps_confirmation.nb_retries = 0;
01051     _mcps_confirmation.ack_received = false;
01052     _mcps_confirmation.ul_frame_counter = _params.ul_frame_counter;
01053 
01054     status = schedule_tx();
01055 
01056     return status;
01057 }
01058 
01059 int LoRaMac::get_backoff_timer_event_id(void)
01060 {
01061     return _params.timers.backoff_timer.timer_id;
01062 }
01063 
01064 lorawan_status_t LoRaMac::clear_tx_pipe(void)
01065 {
01066     if (!_can_cancel_tx) {
01067         return LORAWAN_STATUS_BUSY;
01068     }
01069 
01070     // check if the event is not already queued
01071     const int id = get_backoff_timer_event_id();
01072 
01073     if (id == 0) {
01074         // No queued send request
01075         return LORAWAN_STATUS_NO_OP;
01076     }
01077 
01078     if (_ev_queue->time_left(id) > 0) {
01079         _lora_time.stop(_params.timers.backoff_timer);
01080         _lora_time.stop(_params.timers.ack_timeout_timer);
01081         memset(_params.tx_buffer, 0, sizeof _params.tx_buffer);
01082         _params.tx_buffer_len = 0;
01083         reset_ongoing_tx(true);
01084         tr_debug("Sending Cancelled");
01085         return LORAWAN_STATUS_OK;
01086     } else {
01087         // Event is already being dispatched so it cannot be cancelled
01088         return LORAWAN_STATUS_BUSY;
01089     }
01090 }
01091 
01092 lorawan_status_t LoRaMac::schedule_tx()
01093 {
01094     channel_selection_params_t next_channel;
01095     lorawan_time_t backoff_time = 0;
01096     uint8_t fopts_len = 0;
01097 
01098     if (_params.sys_params.max_duty_cycle == 255) {
01099         return LORAWAN_STATUS_DEVICE_OFF;
01100     }
01101 
01102     if (_params.sys_params.max_duty_cycle == 0) {
01103         _params.timers.aggregated_timeoff = 0;
01104     }
01105 
01106     if (MBED_CONF_LORA_DUTY_CYCLE_ON && _lora_phy->verify_duty_cycle(true)) {
01107         _params.is_dutycycle_on = true;
01108     } else {
01109         _params.is_dutycycle_on = false;
01110     }
01111 
01112     calculate_backOff(_params.last_channel_idx);
01113 
01114     next_channel.aggregate_timeoff = _params.timers.aggregated_timeoff;
01115     next_channel.current_datarate = _params.sys_params.channel_data_rate;
01116     next_channel.dc_enabled = _params.is_dutycycle_on;
01117     next_channel.joined = _is_nwk_joined;
01118     next_channel.last_aggregate_tx_time = _params.timers.aggregated_last_tx_time;
01119 
01120     lorawan_status_t status = _lora_phy->set_next_channel(&next_channel,
01121                                                          &_params.channel,
01122                                                          &backoff_time,
01123                                                          &_params.timers.aggregated_timeoff);
01124 
01125     switch (status) {
01126         case LORAWAN_STATUS_NO_CHANNEL_FOUND:
01127         case LORAWAN_STATUS_NO_FREE_CHANNEL_FOUND:
01128             _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01129             return status;
01130         case LORAWAN_STATUS_DUTYCYCLE_RESTRICTED:
01131             if (backoff_time != 0) {
01132                 tr_debug("DC enforced: Transmitting in %lu ms", backoff_time);
01133                 _can_cancel_tx = true;
01134                 _lora_time.start(_params.timers.backoff_timer, backoff_time);
01135             }
01136             return LORAWAN_STATUS_OK;
01137         default:
01138             break;
01139     }
01140 
01141     uint8_t rx1_dr = _lora_phy->apply_DR_offset(_params.sys_params.channel_data_rate,
01142                                                   _params.sys_params.rx1_dr_offset);
01143 
01144     tr_debug("TX: Channel=%d, TX DR=%d, RX1 DR=%d",
01145              _params.channel, _params.sys_params.channel_data_rate, rx1_dr);
01146 
01147 
01148     _lora_phy->compute_rx_win_params(rx1_dr, MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH,
01149                                     MBED_CONF_LORA_MAX_SYS_RX_ERROR,
01150                                     &_params.rx_window1_config);
01151 
01152     _lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate,
01153                                     MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH,
01154                                     MBED_CONF_LORA_MAX_SYS_RX_ERROR,
01155                                     &_params.rx_window2_config);
01156 
01157     if (!_is_nwk_joined) {
01158         _params.rx_window1_delay = _params.sys_params.join_accept_delay1
01159                                    + _params.rx_window1_config.window_offset;
01160         _params.rx_window2_delay = _params.sys_params.join_accept_delay2
01161                                    + _params.rx_window2_config.window_offset;
01162     } else {
01163 
01164         // if the outgoing message is a proprietary message, it doesn't include any
01165         // standard message formatting except port and MHDR.
01166         if (_ongoing_tx_msg.type == MCPS_PROPRIETARY ) {
01167             fopts_len = 0;
01168         } else {
01169             fopts_len = _mac_commands.get_mac_cmd_length() + _mac_commands.get_repeat_commands_length();
01170         }
01171 
01172         // A check was performed for validity of FRMPayload in ::prepare_ongoing_tx() API.
01173         // However, owing to the asynch nature of the send() API, we should check the
01174         // validity again, as datarate may have changed since we last attempted to transmit.
01175         if (validate_payload_length(_ongoing_tx_msg.f_buffer_size,
01176                                     _params.sys_params.channel_data_rate,
01177                                     fopts_len) == false) {
01178             tr_error("Allowed FRMPayload = %d, FRMPayload = %d, MAC commands pending = %d",
01179                      _lora_phy->get_max_payload(_params.sys_params.channel_data_rate,
01180                                                _params.is_repeater_supported),
01181                                                _ongoing_tx_msg.f_buffer_size, fopts_len);
01182             return LORAWAN_STATUS_LENGTH_ERROR;
01183         }
01184         _params.rx_window1_delay = _params.sys_params.recv_delay1
01185                                    + _params.rx_window1_config.window_offset;
01186         _params.rx_window2_delay = _params.sys_params.recv_delay2
01187                                    + _params.rx_window2_config.window_offset;
01188     }
01189 
01190     // handle the ack to the server here so that if the sending was cancelled
01191     // by the user in the backoff period, we would still ack the previous frame.
01192     if (_params.is_srv_ack_requested) {
01193         _params.is_srv_ack_requested = false;
01194     }
01195 
01196     _can_cancel_tx = false;
01197     return send_frame_on_channel(_params.channel);
01198 }
01199 
01200 void LoRaMac::calculate_backOff(uint8_t channel)
01201 {
01202     lorawan_time_t elapsed_time = _lora_time.get_elapsed_time(_params.timers.mac_init_time);
01203     _lora_phy->calculate_backoff(_is_nwk_joined, _params.is_last_tx_join_request, _params.is_dutycycle_on,
01204                                 channel, elapsed_time, _params.timers.tx_toa);
01205 
01206     // Update aggregated time-off. This must be an assignment and no incremental
01207     // update as we do only calculate the time-off based on the last transmission
01208     _params.timers.aggregated_timeoff = (_params.timers.tx_toa * _params.sys_params.aggregated_duty_cycle
01209                                          - _params.timers.tx_toa);
01210 }
01211 
01212 void LoRaMac::reset_mac_parameters(void)
01213 {
01214     _is_nwk_joined = false;
01215 
01216     _params.ul_frame_counter = 0;
01217     _params.dl_frame_counter = 0;
01218     _params.adr_ack_counter = 0;
01219 
01220     _params.ul_nb_rep_counter = 0;
01221 
01222     _params.max_ack_timeout_retries = 1;
01223     _params.ack_timeout_retry_counter = 1;
01224     _params.is_ack_retry_timeout_expired = false;
01225 
01226     _params.sys_params.max_duty_cycle = 0;
01227     _params.sys_params.aggregated_duty_cycle = 1;
01228 
01229     _mac_commands.clear_command_buffer();
01230     _mac_commands.clear_repeat_buffer();
01231 
01232     _params.is_rx_window_enabled = true;
01233 
01234     _lora_phy->reset_to_default_values(&_params, false);
01235 
01236     _params.is_node_ack_requested = false;
01237     _params.is_srv_ack_requested = false;
01238 
01239     multicast_params_t  *cur = _params.multicast_channels;
01240     while (cur != NULL) {
01241         cur->dl_frame_counter  = 0;
01242         cur = cur->next ;
01243     }
01244     _params.channel = 0;
01245     _params.last_channel_idx = _params.channel;
01246 }
01247 
01248 uint8_t LoRaMac::get_default_tx_datarate()
01249 {
01250     return _lora_phy->get_default_tx_datarate();
01251 }
01252 
01253 void LoRaMac::enable_adaptive_datarate(bool adr_enabled)
01254 {
01255     _params.sys_params.adr_on = adr_enabled;
01256 }
01257 
01258 lorawan_status_t LoRaMac::set_channel_data_rate(uint8_t data_rate)
01259 {
01260     if (_params.sys_params.adr_on) {
01261         tr_error("Cannot set data rate. Please turn off ADR first.");
01262         return LORAWAN_STATUS_PARAMETER_INVALID;
01263     }
01264 
01265     if (_lora_phy->verify_tx_datarate(data_rate, false) == true) {
01266         _params.sys_params.channel_data_rate = data_rate;
01267     } else {
01268         return LORAWAN_STATUS_PARAMETER_INVALID;
01269     }
01270 
01271     return LORAWAN_STATUS_OK;
01272 }
01273 
01274 bool LoRaMac::tx_ongoing()
01275 {
01276     return _ongoing_tx_msg.tx_ongoing;
01277 }
01278 
01279 void LoRaMac::set_tx_ongoing(bool ongoing)
01280 {
01281     _can_cancel_tx = true;
01282     _ongoing_tx_msg.tx_ongoing = ongoing;
01283 }
01284 
01285 void LoRaMac::reset_ongoing_tx(bool reset_pending)
01286 {
01287     _ongoing_tx_msg.tx_ongoing = false;
01288     memset(_ongoing_tx_msg.f_buffer, 0, MBED_CONF_LORA_TX_MAX_SIZE);
01289     _ongoing_tx_msg.f_buffer_size = 0;
01290     if (reset_pending) {
01291         _ongoing_tx_msg.pending_size = 0;
01292     }
01293 }
01294 
01295 int16_t LoRaMac::prepare_ongoing_tx(const uint8_t port,
01296                                     const uint8_t *const data,
01297                                     uint16_t length,
01298                                     uint8_t flags,
01299                                     uint8_t num_retries)
01300 {
01301     _ongoing_tx_msg.port = port;
01302     uint8_t max_possible_size = 0;
01303     uint8_t fopts_len = _mac_commands.get_mac_cmd_length()
01304             + _mac_commands.get_repeat_commands_length();
01305 
01306     // Handles unconfirmed messages
01307     if (flags & MSG_UNCONFIRMED_FLAG) {
01308         _ongoing_tx_msg.type = MCPS_UNCONFIRMED ;
01309         _ongoing_tx_msg.fport = port;
01310         _ongoing_tx_msg.nb_trials = 1;
01311     }
01312 
01313     // Handles confirmed messages
01314     if (flags & MSG_CONFIRMED_FLAG) {
01315         _ongoing_tx_msg.type = MCPS_CONFIRMED ;
01316         _ongoing_tx_msg.fport = port;
01317         _ongoing_tx_msg.nb_trials = num_retries;
01318     }
01319 
01320     // Handles proprietary messages
01321     if (flags & MSG_PROPRIETARY_FLAG) {
01322         _ongoing_tx_msg.type = MCPS_PROPRIETARY ;
01323         _ongoing_tx_msg.fport = port;
01324         _ongoing_tx_msg.nb_trials = _params.sys_params.nb_trans;
01325         // a proprietary frame only includes an MHDR field which contains MTYPE field.
01326         // Everything else is at the discretion of the implementer
01327         fopts_len = 0;
01328     }
01329 
01330     max_possible_size = get_max_possible_tx_size(fopts_len);
01331 
01332     if (max_possible_size > MBED_CONF_LORA_TX_MAX_SIZE) {
01333         max_possible_size = MBED_CONF_LORA_TX_MAX_SIZE;
01334     }
01335 
01336     if (max_possible_size < length) {
01337         tr_info("Cannot transmit %d bytes. Possible TX Size is %d bytes",
01338                 length, max_possible_size);
01339 
01340         _ongoing_tx_msg.pending_size = length - max_possible_size;
01341         _ongoing_tx_msg.f_buffer_size = max_possible_size;
01342         memcpy(_ongoing_tx_msg.f_buffer, data, _ongoing_tx_msg.f_buffer_size);
01343     } else {
01344         _ongoing_tx_msg.f_buffer_size = length;
01345         _ongoing_tx_msg.pending_size = 0;
01346         if (length > 0) {
01347             memcpy(_ongoing_tx_msg.f_buffer, data, length);
01348         }
01349     }
01350 
01351     tr_info("RTS = %u bytes, PEND = %u, Port: %u",
01352             _ongoing_tx_msg.f_buffer_size, _ongoing_tx_msg.pending_size,
01353             _ongoing_tx_msg.fport);
01354 
01355     return _ongoing_tx_msg.f_buffer_size;
01356 }
01357 
01358 lorawan_status_t LoRaMac::send_ongoing_tx()
01359 {
01360     lorawan_status_t status;
01361     _params.is_last_tx_join_request = false;
01362     int8_t datarate = _params.sys_params.channel_data_rate;
01363 
01364     // This prohibits the data rate going below the minimum value.
01365     datarate = MAX(datarate, (int8_t)_lora_phy->get_minimum_tx_datarate());
01366 
01367     loramac_mhdr_t  machdr;
01368     machdr.value  = 0;
01369 
01370     reset_mcps_confirmation();
01371 
01372     _params.ack_timeout_retry_counter = 1;
01373     _params.max_ack_timeout_retries = 1;
01374 
01375     if (MCPS_UNCONFIRMED  == _ongoing_tx_msg.type) {
01376         machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP ;
01377     } else if (_ongoing_tx_msg.type == MCPS_CONFIRMED ) {
01378         machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP ;
01379         _params.max_ack_timeout_retries = _ongoing_tx_msg.nb_trials;
01380     } else if (_ongoing_tx_msg.type == MCPS_PROPRIETARY ) {
01381         machdr.bits.mtype = FRAME_TYPE_PROPRIETARY ;
01382     } else {
01383         return LORAWAN_STATUS_SERVICE_UNKNOWN;
01384     }
01385 
01386     if (_params.sys_params.adr_on == false) {
01387         if (_lora_phy->verify_tx_datarate(datarate, false) == true) {
01388             _params.sys_params.channel_data_rate = datarate;
01389         } else {
01390             return LORAWAN_STATUS_PARAMETER_INVALID;
01391         }
01392     }
01393 
01394     status = send(&machdr, _ongoing_tx_msg.fport, _ongoing_tx_msg.f_buffer,
01395                   _ongoing_tx_msg.f_buffer_size);
01396     if (status == LORAWAN_STATUS_OK) {
01397         _mcps_confirmation.req_type = _ongoing_tx_msg.type;
01398     }
01399 
01400     return status;
01401 }
01402 
01403 device_class_t LoRaMac::get_device_class() const
01404 {
01405     return _device_class;
01406 }
01407 
01408 void LoRaMac::set_device_class(const device_class_t &device_class,
01409                                mbed::Callback<void(void)>rx2_would_be_closure_handler)
01410 {
01411     _device_class = device_class;
01412     _rx2_would_be_closure_for_class_c = rx2_would_be_closure_handler;
01413 
01414     _lora_time.init(_rx2_closure_timer_for_class_c, _rx2_would_be_closure_for_class_c);
01415 
01416     if (CLASS_A == _device_class) {
01417         tr_debug("Changing device class to -> CLASS_A");
01418         _lora_phy->put_radio_to_sleep();
01419     } else if (CLASS_C == _device_class) {
01420         _params.is_node_ack_requested = false;
01421         _lora_phy->put_radio_to_sleep();
01422         _lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate,
01423                                         MBED_CONF_LORA_DOWNLINK_PREAMBLE_LENGTH,
01424                                         MBED_CONF_LORA_MAX_SYS_RX_ERROR,
01425                                         &_params.rx_window2_config);
01426     }
01427 
01428     if (CLASS_C == _device_class) {
01429         tr_debug("Changing device class to -> CLASS_C");
01430         open_rx2_window();
01431     }
01432 }
01433 
01434 void LoRaMac::setup_link_check_request()
01435 {
01436     reset_mlme_confirmation();
01437 
01438     _mlme_confirmation.req_type = MLME_LINK_CHECK ;
01439     _mlme_confirmation.pending = true;
01440     _mac_commands.add_link_check_req();
01441 }
01442 
01443 lorawan_status_t LoRaMac::prepare_join(const lorawan_connect_t *params, bool is_otaa)
01444 {
01445     if (params) {
01446         if (is_otaa) {
01447             if ((params->connection_u.otaa.dev_eui == NULL)
01448                     || (params->connection_u.otaa.app_eui == NULL)
01449                     || (params->connection_u.otaa.app_key == NULL)
01450                     || (params->connection_u.otaa.nb_trials == 0)) {
01451                 return LORAWAN_STATUS_PARAMETER_INVALID;
01452             }
01453             _params.keys.dev_eui = params->connection_u.otaa.dev_eui;
01454             _params.keys.app_eui = params->connection_u.otaa.app_eui;
01455             _params.keys.app_key = params->connection_u.otaa.app_key;
01456             _params.max_join_request_trials = params->connection_u.otaa.nb_trials;
01457 
01458             if (!_lora_phy->verify_nb_join_trials(params->connection_u.otaa.nb_trials)) {
01459                 // Value not supported, get default
01460                 _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS;
01461             }
01462             // Reset variable JoinRequestTrials
01463             _params.join_request_trial_counter = 0;
01464 
01465             reset_mac_parameters();
01466 
01467             _params.sys_params.channel_data_rate =
01468                 _lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1);
01469         } else {
01470             if ((params->connection_u.abp.dev_addr == 0)
01471                     || (params->connection_u.abp.nwk_id == 0)
01472                     || (params->connection_u.abp.nwk_skey == NULL)
01473                     || (params->connection_u.abp.app_skey == NULL)) {
01474                 return LORAWAN_STATUS_PARAMETER_INVALID;
01475             }
01476 
01477             _params.net_id = params->connection_u.abp.nwk_id;
01478             _params.dev_addr = params->connection_u.abp.dev_addr;
01479 
01480             memcpy(_params.keys.nwk_skey, params->connection_u.abp.nwk_skey,
01481                    sizeof(_params.keys.nwk_skey));
01482 
01483             memcpy(_params.keys.app_skey, params->connection_u.abp.app_skey,
01484                    sizeof(_params.keys.app_skey));
01485         }
01486     } else {
01487 #if MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION
01488         const static uint8_t dev_eui[] = MBED_CONF_LORA_DEVICE_EUI;
01489         const static uint8_t app_eui[] = MBED_CONF_LORA_APPLICATION_EUI;
01490         const static uint8_t app_key[] = MBED_CONF_LORA_APPLICATION_KEY;
01491 
01492         _params.keys.app_eui = const_cast<uint8_t *>(app_eui);
01493         _params.keys.dev_eui = const_cast<uint8_t *>(dev_eui);
01494         _params.keys.app_key = const_cast<uint8_t *>(app_key);
01495         _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS;
01496 
01497         // Reset variable JoinRequestTrials
01498         _params.join_request_trial_counter = 0;
01499 
01500         reset_mac_parameters();
01501 
01502         _params.sys_params.channel_data_rate =
01503             _lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1);
01504 
01505 #else
01506         const static uint8_t nwk_skey[] = MBED_CONF_LORA_NWKSKEY;
01507         const static uint8_t app_skey[] = MBED_CONF_LORA_APPSKEY;
01508 
01509         _params.net_id = (MBED_CONF_LORA_DEVICE_ADDRESS & LORAWAN_NETWORK_ID_MASK) >> 25;
01510         _params.dev_addr = MBED_CONF_LORA_DEVICE_ADDRESS;
01511 
01512         memcpy(_params.keys.nwk_skey, nwk_skey, sizeof(_params.keys.nwk_skey));
01513 
01514         memcpy(_params.keys.app_skey, app_skey, sizeof(_params.keys.app_skey));
01515 #endif
01516     }
01517 
01518     return LORAWAN_STATUS_OK;
01519 }
01520 
01521 lorawan_status_t LoRaMac::join(bool is_otaa)
01522 {
01523     if (!is_otaa) {
01524         set_nwk_joined(true);
01525         return LORAWAN_STATUS_OK;
01526     }
01527 
01528     reset_mlme_confirmation();
01529     _mlme_confirmation.req_type = MLME_JOIN ;
01530 
01531     return send_join_request();
01532 }
01533 
01534 static void memcpy_convert_endianess(uint8_t *dst,
01535                                      const uint8_t *src,
01536                                      uint16_t size)
01537 {
01538     dst = dst + (size - 1);
01539     while (size--) {
01540         *dst-- = *src++;
01541     }
01542 }
01543 
01544 lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t  *machdr,
01545                                         loramac_frame_ctrl_t  *fctrl,
01546                                         const uint8_t fport,
01547                                         const void *fbuffer,
01548                                         uint16_t fbuffer_size)
01549 {
01550     uint16_t i;
01551     uint8_t pkt_header_len = 0;
01552     uint32_t mic = 0;
01553     const void *payload = fbuffer;
01554     uint8_t frame_port = fport;
01555     lorawan_status_t status = LORAWAN_STATUS_OK;
01556 
01557     _params.tx_buffer_len = 0;
01558 
01559     _params.is_node_ack_requested = false;
01560 
01561     if (fbuffer == NULL) {
01562         fbuffer_size = 0;
01563     }
01564 
01565     _params.tx_buffer_len = fbuffer_size;
01566 
01567     _params.tx_buffer[pkt_header_len++] = machdr->value ;
01568 
01569     switch (machdr->bits.mtype ) {
01570 
01571         case FRAME_TYPE_JOIN_REQ :
01572 
01573             _params.tx_buffer_len = pkt_header_len;
01574             memcpy_convert_endianess(_params.tx_buffer + _params.tx_buffer_len,
01575                                      _params.keys.app_eui, 8);
01576             _params.tx_buffer_len += 8;
01577             memcpy_convert_endianess(_params.tx_buffer + _params.tx_buffer_len,
01578                                      _params.keys.dev_eui, 8);
01579             _params.tx_buffer_len += 8;
01580 
01581             _params.dev_nonce = _lora_phy->get_radio_rng();
01582 
01583             _params.tx_buffer[_params.tx_buffer_len++] = _params.dev_nonce & 0xFF;
01584             _params.tx_buffer[_params.tx_buffer_len++] = (_params.dev_nonce >> 8) & 0xFF;
01585 
01586             if (0 != _lora_crypto.compute_join_frame_mic(_params.tx_buffer,
01587                                                          _params.tx_buffer_len & 0xFF,
01588                                                          _params.keys.app_key,
01589                                                          APPKEY_KEY_LENGTH,
01590                                                          &mic)) {
01591                 return LORAWAN_STATUS_CRYPTO_FAIL;
01592             }
01593 
01594             _params.tx_buffer[_params.tx_buffer_len++] = mic & 0xFF;
01595             _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 8) & 0xFF;
01596             _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 16) & 0xFF;
01597             _params.tx_buffer[_params.tx_buffer_len++] = (mic >> 24) & 0xFF;
01598 
01599             break;
01600         case FRAME_TYPE_DATA_CONFIRMED_UP :
01601             _params.is_node_ack_requested = true;
01602         //Intentional fallthrough
01603         case FRAME_TYPE_DATA_UNCONFIRMED_UP : {
01604             if (!_is_nwk_joined) {
01605                 return LORAWAN_STATUS_NO_NETWORK_JOINED;
01606             }
01607 
01608             if (_params.sys_params.adr_on) {
01609                 if (_lora_phy->get_next_ADR(true,
01610                                            _params.sys_params.channel_data_rate,
01611                                            _params.sys_params.channel_tx_power,
01612                                            _params.adr_ack_counter)) {
01613                     fctrl->bits.adr_ack_req  = 1;
01614                 }
01615             }
01616 
01617             if (_params.is_srv_ack_requested == true) {
01618                 tr_debug("Acking to NS");
01619                 fctrl->bits.ack  = 1;
01620             }
01621 
01622             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr) & 0xFF;
01623             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 8) & 0xFF;
01624             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 16) & 0xFF;
01625             _params.tx_buffer[pkt_header_len++] = (_params.dev_addr >> 24) & 0xFF;
01626 
01627             _params.tx_buffer[pkt_header_len++] = fctrl->value ;
01628 
01629             _params.tx_buffer[pkt_header_len++] = _params.ul_frame_counter & 0xFF;
01630             _params.tx_buffer[pkt_header_len++] = (_params.ul_frame_counter >> 8)
01631                                                   & 0xFF;
01632 
01633             _mac_commands.copy_repeat_commands_to_buffer();
01634 
01635             const uint8_t mac_commands_len = _mac_commands.get_mac_cmd_length();
01636 
01637             if ((payload != NULL) && (_params.tx_buffer_len > 0)) {
01638                 if (mac_commands_len <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH) {
01639                     fctrl->bits.fopts_len  += mac_commands_len;
01640 
01641                     // Update FCtrl field with new value of OptionsLength
01642                     _params.tx_buffer[0x05] = fctrl->value ;
01643 
01644                     const uint8_t *buffer = _mac_commands.get_mac_commands_buffer();
01645                     for (i = 0; i < mac_commands_len; i++) {
01646                         _params.tx_buffer[pkt_header_len++] = buffer[i];
01647                     }
01648                 } else {
01649                     _params.tx_buffer_len = mac_commands_len;
01650                     payload = _mac_commands.get_mac_commands_buffer();
01651                     frame_port = 0;
01652                 }
01653             } else {
01654                 if (mac_commands_len > 0) {
01655                     _params.tx_buffer_len = mac_commands_len;
01656                     payload = _mac_commands.get_mac_commands_buffer();
01657                     frame_port = 0;
01658                 }
01659             }
01660 
01661             _mac_commands.parse_mac_commands_to_repeat();
01662 
01663             // We always add Port Field. Spec leaves it optional.
01664             _params.tx_buffer[pkt_header_len++] = frame_port;
01665 
01666             if ((payload != NULL) && (_params.tx_buffer_len > 0)) {
01667 
01668                 uint8_t *key = _params.keys.app_skey;
01669                 uint32_t key_length = sizeof(_params.keys.app_skey) * 8;
01670                 if (frame_port == 0) {
01671                     key = _params.keys.nwk_skey;
01672                     key_length = sizeof(_params.keys.nwk_skey) * 8;
01673                 }
01674                 if (0 != _lora_crypto.encrypt_payload((uint8_t *) payload, _params.tx_buffer_len,
01675                                                       key, key_length,
01676                                                       _params.dev_addr, UP_LINK,
01677                                                       _params.ul_frame_counter,
01678                                                       &_params.tx_buffer[pkt_header_len])) {
01679                     status = LORAWAN_STATUS_CRYPTO_FAIL;
01680                 }
01681             }
01682 
01683             _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len;
01684 
01685             if (0 != _lora_crypto.compute_mic(_params.tx_buffer, _params.tx_buffer_len,
01686                                               _params.keys.nwk_skey, sizeof(_params.keys.nwk_skey) * 8,
01687                                               _params.dev_addr,
01688                                               UP_LINK, _params.ul_frame_counter, &mic)) {
01689                 status = LORAWAN_STATUS_CRYPTO_FAIL;
01690             }
01691 
01692             _params.tx_buffer[_params.tx_buffer_len + 0] = mic & 0xFF;
01693             _params.tx_buffer[_params.tx_buffer_len + 1] = (mic >> 8) & 0xFF;
01694             _params.tx_buffer[_params.tx_buffer_len + 2] = (mic >> 16) & 0xFF;
01695             _params.tx_buffer[_params.tx_buffer_len + 3] = (mic >> 24) & 0xFF;
01696 
01697             _params.tx_buffer_len += LORAMAC_MFR_LEN;
01698         }
01699             break;
01700         case FRAME_TYPE_PROPRIETARY :
01701             if ((fbuffer != NULL) && (_params.tx_buffer_len > 0)) {
01702                 memcpy(_params.tx_buffer + pkt_header_len, (uint8_t *) fbuffer,
01703                        _params.tx_buffer_len);
01704                 _params.tx_buffer_len = pkt_header_len + _params.tx_buffer_len;
01705             }
01706             break;
01707         default:
01708             status = LORAWAN_STATUS_SERVICE_UNKNOWN;
01709     }
01710 
01711     tr_debug("Frame prepared to send at port %u", frame_port);
01712 
01713     return status;
01714 }
01715 
01716 lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel)
01717 {
01718     tx_config_params_t tx_config;
01719     int8_t tx_power = 0;
01720 
01721     tx_config.channel = channel;
01722     tx_config.datarate = _params.sys_params.channel_data_rate;
01723     tx_config.tx_power = _params.sys_params.channel_tx_power;
01724     tx_config.max_eirp = _params.sys_params.max_eirp;
01725     tx_config.antenna_gain = _params.sys_params.antenna_gain;
01726     tx_config.pkt_len = _params.tx_buffer_len;
01727 
01728     _lora_phy->tx_config(&tx_config, &tx_power, &_params.timers.tx_toa);
01729 
01730     _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01731 
01732     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01733     _mcps_confirmation.data_rate = _params.sys_params.channel_data_rate;
01734     _mcps_confirmation.tx_power = tx_power;
01735     _mcps_confirmation.channel = channel;
01736 
01737     _mcps_confirmation.tx_toa = _params.timers.tx_toa;
01738     _mlme_confirmation.tx_toa = _params.timers.tx_toa;
01739 
01740     if (!_is_nwk_joined) {
01741         _params.join_request_trial_counter++;
01742     }
01743 
01744     _lora_phy->handle_send(_params.tx_buffer, _params.tx_buffer_len);
01745 
01746     return LORAWAN_STATUS_OK;
01747 }
01748 
01749 void LoRaMac::reset_mcps_confirmation()
01750 {
01751     memset((uint8_t *) &_mcps_confirmation, 0, sizeof(_mcps_confirmation));
01752     _mcps_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01753 }
01754 
01755 void LoRaMac::reset_mlme_confirmation()
01756 {
01757     memset((uint8_t *) &_mlme_confirmation, 0, sizeof(_mlme_confirmation));
01758     _mlme_confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01759 }
01760 
01761 void LoRaMac::reset_mcps_indication()
01762 {
01763     memset((uint8_t *) &_mcps_indication, 0, sizeof(_mcps_indication));
01764     _mcps_indication.status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01765 }
01766 
01767 lorawan_status_t LoRaMac::initialize(EventQueue *queue,
01768                                      mbed::Callback<void(void)>scheduling_failure_handler)
01769 {
01770     _lora_time.activate_timer_subsystem(queue);
01771     _lora_phy->initialize(&_lora_time);
01772 
01773     _ev_queue = queue;
01774     _scheduling_failure_handler = scheduling_failure_handler;
01775     _rx2_closure_timer_for_class_c.callback = NULL;
01776     _rx2_closure_timer_for_class_c.timer_id = -1;
01777 
01778     _channel_plan.activate_channelplan_subsystem(_lora_phy);
01779 
01780     _device_class = CLASS_A;
01781 
01782     _params.join_request_trial_counter = 0;
01783     _params.max_join_request_trials = 1;
01784     _params.is_repeater_supported = false;
01785 
01786     _params.timers.aggregated_last_tx_time = 0;
01787     _params.timers.aggregated_timeoff = 0;
01788 
01789     _lora_phy->reset_to_default_values(&_params, true);
01790     _params.sys_params.nb_trans = 1;
01791 
01792     reset_mac_parameters();
01793 
01794     srand(_lora_phy->get_radio_rng());
01795 
01796     _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK;
01797     _lora_phy->setup_public_network_mode(_params.is_nwk_public);
01798     _lora_phy->put_radio_to_sleep();
01799 
01800     _lora_time.init(_params.timers.backoff_timer,
01801                     mbed::callback(this, &LoRaMac::on_backoff_timer_expiry));
01802     _lora_time.init(_params.timers.rx_window1_timer,
01803                     mbed::callback(this, &LoRaMac::open_rx1_window));
01804     _lora_time.init(_params.timers.rx_window2_timer,
01805                     mbed::callback(this, &LoRaMac::open_rx2_window));
01806     _lora_time.init(_params.timers.ack_timeout_timer,
01807                     mbed::callback(this, &LoRaMac::on_ack_timeout_timer_event));
01808 
01809     _params.timers.mac_init_time = _lora_time.get_current_time();
01810 
01811     _params.sys_params.adr_on = MBED_CONF_LORA_ADR_ON;
01812     _params.sys_params.channel_data_rate = _lora_phy->get_default_max_tx_datarate();
01813 
01814     return LORAWAN_STATUS_OK;
01815 }
01816 
01817 void LoRaMac::disconnect()
01818 {
01819     _lora_time.stop(_params.timers.backoff_timer);
01820     _lora_time.stop(_params.timers.rx_window1_timer);
01821     _lora_time.stop(_params.timers.rx_window2_timer);
01822     _lora_time.stop(_params.timers.ack_timeout_timer);
01823 
01824     _lora_phy->put_radio_to_sleep();
01825 
01826     _is_nwk_joined = false;
01827     _params.is_ack_retry_timeout_expired = false;
01828     _params.is_rx_window_enabled = true;
01829     _params.is_node_ack_requested = false;
01830     _params.is_srv_ack_requested = false;
01831 
01832     _mac_commands.clear_command_buffer();
01833     _mac_commands.clear_repeat_buffer();
01834 
01835     reset_mcps_confirmation();
01836     reset_mlme_confirmation();
01837     reset_mcps_indication();
01838 }
01839 
01840 uint8_t LoRaMac::get_max_possible_tx_size(uint8_t fopts_len)
01841 {
01842     uint8_t max_possible_payload_size = 0;
01843     uint8_t allowed_frm_payload_size = 0;
01844 
01845     int8_t datarate = _params.sys_params.channel_data_rate;
01846     int8_t tx_power = _params.sys_params.channel_tx_power;
01847     uint32_t adr_ack_counter = _params.adr_ack_counter;
01848 
01849     if (_params.sys_params.adr_on) {
01850         // Just query the information. We do not want to apply them into use
01851         // at this point.
01852         _lora_phy->get_next_ADR(false, datarate, tx_power, adr_ack_counter);
01853     }
01854 
01855     allowed_frm_payload_size = _lora_phy->get_max_payload(datarate,
01856                                                           _params.is_repeater_supported);
01857 
01858     if (allowed_frm_payload_size >= fopts_len) {
01859         max_possible_payload_size = allowed_frm_payload_size - fopts_len;
01860     } else {
01861         max_possible_payload_size = allowed_frm_payload_size;
01862         _mac_commands.clear_command_buffer();
01863         _mac_commands.clear_repeat_buffer();
01864     }
01865 
01866     return max_possible_payload_size;
01867 }
01868 
01869 bool LoRaMac::nwk_joined()
01870 {
01871     return _is_nwk_joined;
01872 }
01873 
01874 void LoRaMac::set_nwk_joined(bool joined)
01875 {
01876     _is_nwk_joined = joined;
01877 }
01878 
01879 lorawan_status_t LoRaMac::add_channel_plan(const lorawan_channelplan_t &plan)
01880 {
01881     if (tx_ongoing()) {
01882         return LORAWAN_STATUS_BUSY;
01883     }
01884 
01885     return _channel_plan.set_plan(plan);
01886 }
01887 
01888 lorawan_status_t LoRaMac::remove_channel_plan()
01889 {
01890     if (tx_ongoing()) {
01891         return LORAWAN_STATUS_BUSY;
01892     }
01893 
01894     return _channel_plan.remove_plan();
01895 }
01896 
01897 lorawan_status_t LoRaMac::get_channel_plan(lorawan_channelplan_t &plan)
01898 {
01899     return _channel_plan.get_plan(plan, _lora_phy->get_phy_channels());
01900 }
01901 
01902 lorawan_status_t LoRaMac::remove_single_channel(uint8_t id)
01903 {
01904     if (tx_ongoing()) {
01905         return LORAWAN_STATUS_BUSY;
01906     }
01907 
01908     return _channel_plan.remove_single_channel(id);
01909 }
01910 
01911 lorawan_status_t LoRaMac::multicast_channel_link(multicast_params_t  *channel_param)
01912 {
01913     if (channel_param == NULL) {
01914         return LORAWAN_STATUS_PARAMETER_INVALID;
01915     }
01916     if (tx_ongoing()) {
01917         return LORAWAN_STATUS_BUSY;
01918     }
01919 
01920     channel_param->dl_frame_counter  = 0;
01921 
01922     if (_params.multicast_channels == NULL) {
01923         _params.multicast_channels = channel_param;
01924     } else {
01925         multicast_params_t  *cur = _params.multicast_channels;
01926         while (cur->next  != NULL) {
01927             cur = cur->next ;
01928         }
01929         cur->next  = channel_param;
01930     }
01931 
01932     return LORAWAN_STATUS_OK;
01933 }
01934 
01935 lorawan_status_t LoRaMac::multicast_channel_unlink(multicast_params_t  *channel_param)
01936 {
01937     if (channel_param == NULL) {
01938         return LORAWAN_STATUS_PARAMETER_INVALID;
01939     }
01940 
01941     if (tx_ongoing()) {
01942         return LORAWAN_STATUS_BUSY;
01943     }
01944 
01945     if (_params.multicast_channels != NULL) {
01946         if (_params.multicast_channels == channel_param) {
01947             _params.multicast_channels = channel_param->next ;
01948         } else {
01949             multicast_params_t  *cur = _params.multicast_channels;
01950 
01951             while (cur->next  && cur->next  != channel_param) {
01952                 cur = cur->next ;
01953             }
01954 
01955             if (cur->next ) {
01956                 cur->next  = channel_param->next ;
01957             }
01958         }
01959         channel_param->next  = NULL;
01960     }
01961 
01962     return LORAWAN_STATUS_OK;
01963 }
01964 
01965 void LoRaMac::bind_phy(LoRaPHY &phy)
01966 {
01967     _lora_phy = &phy;
01968 }
01969 
01970 uint8_t LoRaMac::get_QOS_level()
01971 {
01972     if (_prev_qos_level != _params.sys_params.nb_trans) {
01973         _prev_qos_level = _params.sys_params.nb_trans;
01974     }
01975 
01976     return _params.sys_params.nb_trans;
01977 }
01978 
01979 uint8_t LoRaMac::get_prev_QOS_level()
01980 {
01981     return _prev_qos_level;
01982 }
01983