wang yaguang / Mbed OS Nucleo_rtos_basic
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 #include "LoRaMacCrypto.h"
00027 
00028 #if defined(FEATURE_COMMON_PAL)
00029 #include "mbed_trace.h"
00030 #define TRACE_GROUP "LMAC"
00031 #else
00032 #define tr_debug(...) (void(0)) //dummies if feature common pal is not added
00033 #define tr_info(...)  (void(0)) //dummies if feature common pal is not added
00034 #define tr_error(...) (void(0)) //dummies if feature common pal is not added
00035 #endif //defined(FEATURE_COMMON_PAL)
00036 
00037 using namespace events;
00038 
00039 /*!
00040  * Maximum length of the fOpts field
00041  */
00042 #define LORA_MAC_COMMAND_MAX_FOPTS_LENGTH           15
00043 
00044 /*!
00045  * LoRaMac duty cycle for the back-off procedure during the first hour.
00046  */
00047 #define BACKOFF_DC_1_HOUR                           100
00048 
00049 /*!
00050  * LoRaMac duty cycle for the back-off procedure during the next 10 hours.
00051  */
00052 #define BACKOFF_DC_10_HOURS                         1000
00053 
00054 /*!
00055  * LoRaMac duty cycle for the back-off procedure during the next 24 hours.
00056  */
00057 #define BACKOFF_DC_24_HOURS                         10000
00058 
00059 /*!
00060  * Check the MAC layer state every MAC_STATE_CHECK_TIMEOUT in ms.
00061  */
00062 #define MAC_STATE_CHECK_TIMEOUT                     1000
00063 
00064 /*!
00065  * The maximum number of times the MAC layer tries to get an acknowledge.
00066  */
00067 #define MAX_ACK_RETRIES                             8
00068 
00069 /*!
00070  * The frame direction definition for uplink communications.
00071  */
00072 #define UP_LINK                                     0
00073 
00074 /*!
00075  * The frame direction definition for downlink communications.
00076  */
00077 #define DOWN_LINK                                   1
00078 
00079 
00080 LoRaMac::LoRaMac(LoRaWANTimeHandler &lora_time)
00081     : mac_commands(), _lora_time(lora_time)
00082 {
00083     lora_phy = NULL;
00084     //radio_events_t RadioEvents;
00085     _params.keys.dev_eui = NULL;
00086     _params.keys.app_eui = NULL;
00087     _params.keys.app_key = NULL;
00088 
00089     memset(_params.keys.nwk_skey, 0, sizeof(_params.keys.nwk_skey));
00090     memset(_params.keys.app_skey, 0, sizeof(_params.keys.app_skey));
00091 
00092     _params.dev_nonce = 0;
00093     _params.net_id = 0;
00094     _params.dev_addr = 0;
00095     _params.buffer_pkt_len = 0;
00096     _params.payload_length = 0;
00097     _params.ul_frame_counter = 0;
00098     _params.dl_frame_counter = 0;
00099     _params.is_ul_frame_counter_fixed = false;
00100     _params.is_rx_window_enabled = true;
00101     _params.is_nwk_joined = false;
00102     _params.adr_ack_counter = 0;
00103     _params.is_node_ack_requested = false;
00104     _params.is_srv_ack_requested = false;
00105     _params.ul_nb_rep_counter = 0;
00106     _params.timers.mac_init_time = 0;
00107     _params.mac_state = LORAMAC_IDLE;
00108     _params.max_ack_timeout_retries = 1;
00109     _params.ack_timeout_retry_counter = 1;
00110     _params.is_ack_retry_timeout_expired = false;
00111     _params.timers.tx_toa = 0;
00112 
00113     _params.multicast_channels = NULL;
00114 
00115     _params.sys_params.adr_on = false;
00116     _params.sys_params.max_duty_cycle = 0;
00117 
00118     mac_primitives = NULL;
00119     ev_queue = NULL;
00120 }
00121 
00122 LoRaMac::~LoRaMac()
00123 {
00124 }
00125 
00126 
00127 /***************************************************************************
00128  * ISRs - Handlers                                                         *
00129  **************************************************************************/
00130 void LoRaMac::handle_tx_done(void)
00131 {
00132     const int ret = ev_queue->call(this, &LoRaMac::on_radio_tx_done);
00133     MBED_ASSERT(ret != 0);
00134     (void)ret;
00135 }
00136 
00137 void LoRaMac::handle_rx_done(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
00138 {
00139     const int ret = ev_queue->call(this, &LoRaMac::on_radio_rx_done, payload, size, rssi, snr);
00140     MBED_ASSERT(ret != 0);
00141     (void)ret;
00142 }
00143 
00144 void LoRaMac::handle_rx_error(void)
00145 {
00146     const int ret = ev_queue->call(this, &LoRaMac::on_radio_rx_error);
00147     MBED_ASSERT(ret != 0);
00148     (void)ret;
00149 }
00150 
00151 void LoRaMac::handle_rx_timeout(void)
00152 {
00153     const int ret = ev_queue->call(this, &LoRaMac::on_radio_rx_timeout);
00154     MBED_ASSERT(ret != 0);
00155     (void)ret;
00156 }
00157 
00158 void LoRaMac::handle_tx_timeout(void)
00159 {
00160     const int ret = ev_queue->call(this, &LoRaMac::on_radio_tx_timeout);
00161     MBED_ASSERT(ret != 0);
00162     (void)ret;
00163 }
00164 
00165 void LoRaMac::handle_cad_done(bool cad)
00166 {
00167     //TODO Not implemented yet
00168     //const int ret = ev_queue->call(this, &LoRaMac::OnRadioCadDone, cad);
00169     //MBED_ASSERT(ret != 0);
00170     //(void)ret;
00171 }
00172 
00173 void LoRaMac::handle_fhss_change_channel(uint8_t cur_channel)
00174 {
00175     // TODO Not implemented yet
00176     //const int ret = ev_queue->call(this, &LoRaMac::OnRadioFHSSChangeChannel, cur_channel);
00177     //MBED_ASSERT(ret != 0);
00178     //(void)ret;
00179 }
00180 
00181 void LoRaMac::handle_mac_state_check_timer_event(void)
00182 {
00183     const int ret = ev_queue->call(this, &LoRaMac::on_mac_state_check_timer_event);
00184     MBED_ASSERT(ret != 0);
00185     (void)ret;
00186 }
00187 
00188 void LoRaMac::handle_delayed_tx_timer_event(void)
00189 {
00190     const int ret = ev_queue->call(this, &LoRaMac::on_tx_delayed_timer_event);
00191     MBED_ASSERT(ret != 0);
00192     (void)ret;
00193 }
00194 
00195 void LoRaMac::handle_ack_timeout()
00196 {
00197     const int ret = ev_queue->call(this, &LoRaMac::on_ack_timeout_timer_event);
00198     MBED_ASSERT(ret != 0);
00199     (void)ret;
00200 }
00201 
00202 void LoRaMac::handle_rx1_timer_event(void)
00203 {
00204     const int ret = ev_queue->call(this, &LoRaMac::on_rx_window1_timer_event);
00205     MBED_ASSERT(ret != 0);
00206     (void)ret;
00207 }
00208 
00209 void LoRaMac::handle_rx2_timer_event(void)
00210 {
00211     const int ret = ev_queue->call(this, &LoRaMac::on_rx_window2_timer_event);
00212     MBED_ASSERT(ret != 0);
00213     (void)ret;
00214 }
00215 
00216 /***************************************************************************
00217  * Radio event callbacks - delegated to Radio driver                       *
00218  **************************************************************************/
00219 void LoRaMac::on_radio_tx_done( void )
00220 {
00221     set_band_txdone_params_t tx_done_params;
00222     lorawan_time_t cur_time = _lora_time.get_current_time( );
00223     loramac_mlme_confirm_t  mlme_confirm = mlme.get_confirmation();
00224 
00225     if (_params.dev_class != CLASS_C ) {
00226         lora_phy->put_radio_to_sleep();
00227     } else {
00228         open_continuous_rx2_window();
00229     }
00230 
00231     // Setup timers
00232     if(_params.is_rx_window_enabled == true) {
00233         _lora_time.start(_params.timers.rx_window1_timer, _params.rx_window1_delay);
00234 
00235         if (_params.dev_class != CLASS_C ) {
00236             _lora_time.start(_params.timers.rx_window2_timer, _params.rx_window2_delay);
00237         }
00238 
00239         if ((_params.dev_class == CLASS_C  ) ||
00240             (_params.is_node_ack_requested == true)) {
00241             _lora_time.start(_params.timers.ack_timeout_timer,
00242                              _params.rx_window2_delay + lora_phy->get_ack_timeout());
00243         }
00244     } else {
00245         mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK ;
00246         mlme_confirm.status  = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ;
00247 
00248         if (_params.flags.value == 0) {
00249             _params.flags.bits.mcps_req = 1;
00250         }
00251 
00252         _params.flags.bits.mac_done = 1;
00253     }
00254 
00255     // Verify if the last uplink was a join request
00256     if ((_params.flags.bits.mlme_req == 1) &&
00257         (mlme_confirm.req_type  == MLME_JOIN )) {
00258         _params.is_last_tx_join_request = true;
00259     } else {
00260         _params.is_last_tx_join_request = false;
00261     }
00262 
00263     // Store last Tx channel
00264     _params.last_channel_idx = _params.channel;
00265 
00266     // Update last tx done time for the current channel
00267     tx_done_params.channel = _params.channel;
00268     tx_done_params.joined = _params.is_nwk_joined;
00269     tx_done_params.last_tx_done_time = cur_time;
00270     lora_phy->set_last_tx_done(&tx_done_params);
00271 
00272     // Update Aggregated last tx done time
00273     _params.timers.aggregated_last_tx_time = cur_time;
00274 
00275     if (_params.is_node_ack_requested == false) {
00276         mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK ;
00277         _params.ul_nb_rep_counter++;
00278     }
00279 }
00280 
00281 void LoRaMac::prepare_rx_done_abort(void)
00282 {
00283     _params.mac_state |= LORAMAC_RX_ABORT;
00284 
00285     if (_params.is_node_ack_requested) {
00286         handle_ack_timeout();
00287     }
00288 
00289     _params.flags.bits.mcps_ind = 1;
00290     _params.flags.bits.mac_done = 1;
00291 
00292     // Trigger MAC state check event timer as soon as possible
00293     _lora_time.start(_params.timers.mac_state_check_timer, 1);
00294 }
00295 
00296 void LoRaMac::on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
00297                                int8_t snr)
00298 {
00299     loramac_mhdr_t  mac_hdr;
00300     loramac_frame_ctrl_t  fctrl;
00301     cflist_params_t cflist;
00302     bool skip_indication = false;
00303 
00304     uint8_t pkt_header_len = 0;
00305     uint32_t address = 0;
00306     uint8_t app_payload_start_index = 0;
00307     uint8_t frame_len = 0;
00308     uint32_t mic = 0;
00309     uint32_t mic_rx = 0;
00310 
00311     uint16_t sequence_counter = 0;
00312     uint16_t sequence_counter_prev = 0;
00313     uint16_t sequence_counter_diff = 0;
00314     uint32_t downlink_counter = 0;
00315 
00316     multicast_params_t  *cur_multicast_params = NULL;
00317     uint8_t *nwk_skey = _params.keys.nwk_skey;
00318     uint8_t *app_skey = _params.keys.app_skey;
00319 
00320     uint8_t multicast = 0;
00321 
00322     bool is_mic_ok = false;
00323 
00324     mcps.get_confirmation().ack_received = false;
00325     mcps.get_indication().rssi = rssi;
00326     mcps.get_indication().snr = snr;
00327     mcps.get_indication().rx_slot = _params.rx_slot;
00328     mcps.get_indication().port = 0;
00329     mcps.get_indication().multicast = 0;
00330     mcps.get_indication().fpending_status = 0;
00331     mcps.get_indication().buffer = NULL;
00332     mcps.get_indication().buffer_size = 0;
00333     mcps.get_indication().is_data_recvd = false;
00334     mcps.get_indication().is_ack_recvd = false;
00335     mcps.get_indication().dl_frame_counter = 0;
00336     mcps.get_indication().type = MCPS_UNCONFIRMED ;
00337 
00338     lora_phy->put_radio_to_sleep();
00339 
00340     _lora_time.stop( _params.timers.rx_window2_timer );
00341 
00342     mac_hdr.value  = payload[pkt_header_len++];
00343 
00344     switch (mac_hdr.bits.mtype ) {
00345 
00346         case FRAME_TYPE_JOIN_ACCEPT :
00347             if (_params.is_nwk_joined == true) {
00348                 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00349                 prepare_rx_done_abort();
00350                 return;
00351             }
00352 
00353             if (0 != decrypt_join_frame(payload + 1, size - 1,
00354                                         _params.keys.app_key,
00355                                         _params.payload + 1)) {
00356                 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00357                 return;
00358             }
00359 
00360             _params.payload[0] = mac_hdr.value ;
00361 
00362             if (0 != compute_join_frame_mic(_params.payload, size - LORAMAC_MFR_LEN,
00363                                            _params.keys.app_key, &mic)) {
00364                 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00365                 return;
00366             }
00367 
00368             mic_rx |= (uint32_t) _params.payload[size - LORAMAC_MFR_LEN];
00369             mic_rx |= ((uint32_t) _params.payload[size - LORAMAC_MFR_LEN + 1] << 8);
00370             mic_rx |= ((uint32_t) _params.payload[size - LORAMAC_MFR_LEN + 2] << 16);
00371             mic_rx |= ((uint32_t) _params.payload[size - LORAMAC_MFR_LEN + 3] << 24);
00372 
00373             if (mic_rx == mic) {
00374 
00375                 if (0 != compute_skeys_for_join_frame(_params.keys.app_key,
00376                                                  _params.payload + 1,
00377                                                  _params.dev_nonce,
00378                                                  _params.keys.nwk_skey,
00379                                                  _params.keys.app_skey)) {
00380                     mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00381                     return;
00382                 }
00383 
00384                 _params.net_id = (uint32_t) _params.payload[4];
00385                 _params.net_id |= ((uint32_t) _params.payload[5] << 8);
00386                 _params.net_id |= ((uint32_t) _params.payload[6] << 16);
00387 
00388                 _params.dev_addr = (uint32_t) _params.payload[7];
00389                 _params.dev_addr |= ((uint32_t) _params.payload[8] << 8);
00390                 _params.dev_addr |= ((uint32_t) _params.payload[9] << 16);
00391                 _params.dev_addr |= ((uint32_t) _params.payload[10] << 24);
00392 
00393                 // DLSettings
00394                 _params.sys_params.rx1_dr_offset = (_params.payload[11] >> 4) & 0x07;
00395                 _params.sys_params.rx2_channel.datarate = _params.payload[11] & 0x0F;
00396 
00397                 // RxDelay
00398                 _params.sys_params.recv_delay1 = (_params.payload[12] & 0x0F);
00399 
00400                 if (_params.sys_params.recv_delay1 == 0) {
00401                     _params.sys_params.recv_delay1 = 1;
00402                 }
00403 
00404                 _params.sys_params.recv_delay1 *= 1000;
00405                 _params.sys_params.recv_delay2 = _params.sys_params.recv_delay1 + 1000;
00406 
00407                 // Apply CF list
00408                 cflist.payload = &_params.payload[13];
00409                 // Size of the regular payload is 12. Plus 1 byte MHDR and 4 bytes MIC
00410                 cflist.size = size - 17;
00411 
00412                 lora_phy->apply_cf_list(&cflist);
00413 
00414                 mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK ;
00415                 _params.is_nwk_joined = true;
00416             } else {
00417                 mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL ;
00418             }
00419 
00420             break;
00421 
00422         case FRAME_TYPE_DATA_CONFIRMED_DOWN :
00423         case FRAME_TYPE_DATA_UNCONFIRMED_DOWN :
00424             {
00425                 uint8_t value = lora_phy->get_max_payload(mcps.get_indication().rx_datarate, _params.is_repeater_supported);
00426 
00427                 if (MAX(0, (int16_t) ((int16_t)size - (int16_t)LORA_MAC_FRMPAYLOAD_OVERHEAD )) > (int32_t)value) {
00428                     mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00429                     prepare_rx_done_abort();
00430                     return;
00431                 }
00432 
00433                 address = payload[pkt_header_len++];
00434                 address |= ((uint32_t)payload[pkt_header_len++] << 8);
00435                 address |= ((uint32_t)payload[pkt_header_len++] << 16);
00436                 address |= ((uint32_t)payload[pkt_header_len++] << 24);
00437 
00438                 if (address != _params.dev_addr) {
00439 
00440                     cur_multicast_params = _params.multicast_channels;
00441 
00442                     while (cur_multicast_params != NULL) {
00443 
00444                         if (address == cur_multicast_params->address ) {
00445                             multicast = 1;
00446                             nwk_skey = cur_multicast_params->nwk_skey ;
00447                             app_skey = cur_multicast_params->app_skey ;
00448                             downlink_counter = cur_multicast_params->dl_frame_counter ;
00449                             break;
00450                         }
00451 
00452                         cur_multicast_params = cur_multicast_params->next ;
00453                     }
00454 
00455                     if (multicast == 0) {
00456                         // We are not the destination of this frame.
00457                         mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL ;
00458                         prepare_rx_done_abort();
00459                         return;
00460                     }
00461                 } else {
00462                     multicast = 0;
00463                     nwk_skey = _params.keys.nwk_skey;
00464                     app_skey = _params.keys.app_skey;
00465                     downlink_counter = _params.dl_frame_counter;
00466                 }
00467 
00468                 fctrl.value  = payload[pkt_header_len++];
00469 
00470                 sequence_counter = (uint16_t )payload[pkt_header_len++];
00471                 sequence_counter |= (uint16_t)payload[pkt_header_len++] << 8;
00472 
00473                 app_payload_start_index = 8 + fctrl.bits.fopts_len ;
00474 
00475                 mic_rx |= (uint32_t)payload[size - LORAMAC_MFR_LEN];
00476                 mic_rx |= ((uint32_t)payload[size - LORAMAC_MFR_LEN + 1] << 8);
00477                 mic_rx |= ((uint32_t)payload[size - LORAMAC_MFR_LEN + 2] << 16);
00478                 mic_rx |= ((uint32_t)payload[size - LORAMAC_MFR_LEN + 3] << 24);
00479 
00480                 sequence_counter_prev = (uint16_t)downlink_counter;
00481                 sequence_counter_diff = (sequence_counter - sequence_counter_prev);
00482 
00483                 if (sequence_counter_diff < (1 << 15)) {
00484 
00485                     downlink_counter += sequence_counter_diff;
00486                     compute_mic(payload, size - LORAMAC_MFR_LEN, nwk_skey,
00487                                       address, DOWN_LINK, downlink_counter, &mic);
00488                     if (mic_rx == mic) {
00489                         is_mic_ok = true;
00490                     }
00491 
00492                 } else {
00493                     // check for sequence roll-over
00494                     uint32_t  downlink_counter_tmp = downlink_counter + 0x10000 + (int16_t)sequence_counter_diff;
00495                     compute_mic(payload, size - LORAMAC_MFR_LEN, nwk_skey,
00496                                       address, DOWN_LINK, downlink_counter_tmp, &mic);
00497 
00498                     if (mic_rx == mic ) {
00499                         is_mic_ok = true;
00500                         downlink_counter = downlink_counter_tmp;
00501                     }
00502                 }
00503 
00504                 if (sequence_counter_diff >= lora_phy->get_maximum_frame_counter_gap()) {
00505                     mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS ;
00506                     mcps.get_indication().dl_frame_counter = downlink_counter;
00507                     prepare_rx_done_abort( );
00508                     return;
00509                 }
00510 
00511                 if (is_mic_ok == true) {
00512                     mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_OK ;
00513                     mcps.get_indication().multicast = multicast;
00514                     mcps.get_indication().fpending_status = fctrl.bits.fpending ;
00515                     mcps.get_indication().buffer = NULL;
00516                     mcps.get_indication().buffer_size = 0;
00517                     mcps.get_indication().dl_frame_counter = downlink_counter;
00518 
00519                     mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_OK ;
00520 
00521                     _params.adr_ack_counter = 0;
00522                     mac_commands.clear_repeat_buffer();
00523 
00524                     // Update 32 bits downlink counter
00525                     if (multicast == 1) {
00526                         mcps.get_indication().type = MCPS_MULTICAST ;
00527 
00528                         if ((cur_multicast_params->dl_frame_counter  == downlink_counter) &&
00529                             (cur_multicast_params->dl_frame_counter  != 0)) {
00530 
00531                             mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ;
00532                             mcps.get_indication().dl_frame_counter = downlink_counter;
00533                             prepare_rx_done_abort();
00534 
00535                             return;
00536                         }
00537 
00538                         cur_multicast_params->dl_frame_counter  = downlink_counter;
00539 
00540                     } else {
00541 
00542                         if (mac_hdr.bits.mtype  == FRAME_TYPE_DATA_CONFIRMED_DOWN ) {
00543                             _params.is_srv_ack_requested = true;
00544                             mcps.get_indication().type = MCPS_CONFIRMED ;
00545 
00546                             if ((_params.dl_frame_counter == downlink_counter ) &&
00547                                 (_params.dl_frame_counter != 0)) {
00548                                 // Duplicated confirmed downlink. Skip indication.
00549                                 // In this case, the MAC layer shall accept the MAC commands
00550                                 // which are included in the downlink retransmission.
00551                                 // It should not provide the same frame to the application
00552                                 // layer again.
00553                                 skip_indication = true;
00554                             }
00555                         } else {
00556                             _params.is_srv_ack_requested = false;
00557                             mcps.get_indication().type = MCPS_UNCONFIRMED ;
00558 
00559                             if ((_params.dl_frame_counter == downlink_counter) &&
00560                                 (_params.dl_frame_counter != 0)) {
00561                                 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ;
00562                                 mcps.get_indication().dl_frame_counter = downlink_counter;
00563                                 prepare_rx_done_abort();
00564                                 return;
00565                             }
00566                         }
00567                         _params.dl_frame_counter = downlink_counter;
00568                     }
00569 
00570                     // This must be done before parsing the payload and the MAC commands.
00571                     // We need to reset the MacCommandsBufferIndex here, since we need
00572                     // to take retransmissions and repetitions into account. Error cases
00573                     // will be handled in function OnMacStateCheckTimerEvent.
00574                     if (mcps.get_confirmation().req_type == MCPS_CONFIRMED ) {
00575                         if (fctrl.bits.ack  == 1) {
00576                             // Reset MacCommandsBufferIndex when we have received an ACK.
00577                             mac_commands.clear_command_buffer();
00578                         }
00579                     } else {
00580                         // Reset the variable if we have received any valid frame.
00581                         mac_commands.clear_command_buffer();
00582                     }
00583 
00584                     // Process payload and MAC commands
00585                     if (((size - 4) - app_payload_start_index) > 0) {
00586                         uint8_t port = payload[app_payload_start_index++];
00587                         frame_len = (size - 4) - app_payload_start_index;
00588 
00589                         mcps.get_indication().port = port;
00590 
00591                         if (port == 0) {
00592                             // Only allow frames which do not have fOpts
00593                             if (fctrl.bits.fopts_len  == 0) {
00594                                 if (0 != decrypt_payload(payload + app_payload_start_index,
00595                                                                frame_len,
00596                                                                nwk_skey,
00597                                                                address,
00598                                                                DOWN_LINK,
00599                                                                downlink_counter,
00600                                                                _params.payload)) {
00601                                     mcps.get_indication().status =  LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00602                                 }
00603 
00604                                 // Decode frame payload MAC commands
00605                                 if (LORAWAN_STATUS_OK != mac_commands.process_mac_commands(
00606                                             _params.payload, 0, frame_len, snr,
00607                                             mlme.get_confirmation(), _params.sys_params, *lora_phy)) {
00608                                     mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00609                                 } else if (mac_commands.has_sticky_mac_cmd()) {
00610                                     set_mlme_schedule_ul_indication();
00611                                     mac_commands.clear_sticky_mac_cmd();
00612                                 }
00613                             } else {
00614                                 skip_indication = true;
00615                             }
00616                         } else {
00617                             if (fctrl.bits.fopts_len  > 0) {
00618                                 // Decode Options field MAC commands. Omit the fPort.
00619                                 if (LORAWAN_STATUS_OK != mac_commands.process_mac_commands(
00620                                             payload, 8, app_payload_start_index - 1, snr,
00621                                             mlme.get_confirmation(), _params.sys_params, *lora_phy )) {
00622                                     mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00623                                 } else if (mac_commands.has_sticky_mac_cmd()) {
00624                                     set_mlme_schedule_ul_indication();
00625                                     mac_commands.clear_sticky_mac_cmd();
00626                                 }
00627                             }
00628 
00629                             if (0 != decrypt_payload(payload + app_payload_start_index,
00630                                                            frame_len,
00631                                                            app_skey,
00632                                                            address,
00633                                                            DOWN_LINK,
00634                                                            downlink_counter,
00635                                                            _params.payload)) {
00636                                 mcps.get_indication().status =  LORAMAC_EVENT_INFO_STATUS_CRYPTO_FAIL ;
00637                             }
00638 
00639                             if (skip_indication == false) {
00640                                 mcps.get_indication().buffer = _params.payload;
00641                                 mcps.get_indication().buffer_size = frame_len;
00642                                 mcps.get_indication().is_data_recvd = true;
00643                             }
00644                         }
00645                     } else {
00646                         if (fctrl.bits.fopts_len  > 0) {
00647                             // Decode Options field MAC commands
00648                             if (LORAWAN_STATUS_OK != mac_commands.process_mac_commands(
00649                                         payload, 8, app_payload_start_index, snr,
00650                                         mlme.get_confirmation(),
00651                                         _params.sys_params, *lora_phy)) {
00652                                 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00653                             } else if (mac_commands.has_sticky_mac_cmd()) {
00654                                 set_mlme_schedule_ul_indication();
00655                                 mac_commands.clear_sticky_mac_cmd();
00656                             }
00657                         }
00658                     }
00659 
00660                     if (skip_indication == false) {
00661                         // Check if the frame is an acknowledgement
00662                         if (fctrl.bits.ack  == 1) {
00663                             mcps.get_confirmation().ack_received = true;
00664                             mcps.get_indication().is_ack_recvd = true;
00665 
00666                             // Stop the AckTimeout timer as no more retransmissions
00667                             // are needed.
00668                             _lora_time.stop(_params.timers.ack_timeout_timer);
00669                         } else {
00670                             mcps.get_confirmation().ack_received = false;
00671 
00672                             if (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries) {
00673                                 // Stop the AckTimeout timer as no more retransmissions
00674                                 // are needed.
00675                                 _lora_time.stop( _params.timers.ack_timeout_timer );
00676                             }
00677                         }
00678                     }
00679                     // Provide always an indication, skip the callback to the user application,
00680                     // in case of a confirmed downlink retransmission.
00681                     _params.flags.bits.mcps_ind = 1;
00682                     _params.flags.bits.mcps_ind_skip = skip_indication;
00683                 } else {
00684                     mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL ;
00685 
00686                     prepare_rx_done_abort( );
00687                     return;
00688                 }
00689             }
00690 
00691             break;
00692 
00693         case FRAME_TYPE_PROPRIETARY :
00694             {
00695                 memcpy(_params.payload, &payload[pkt_header_len], size);
00696 
00697                 mcps.get_indication().type = MCPS_PROPRIETARY ;
00698                 mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_OK ;
00699                 mcps.get_indication().buffer = _params.payload;
00700                 mcps.get_indication().buffer_size = size - pkt_header_len;
00701 
00702                 _params.flags.bits.mcps_ind = 1;
00703                 break;
00704             }
00705         default:
00706             mcps.get_indication().status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
00707             prepare_rx_done_abort();
00708             break;
00709     }
00710     _params.flags.bits.mac_done = 1;
00711 
00712     _lora_time.start(_params.timers.mac_state_check_timer, 1);
00713 }
00714 
00715 void LoRaMac::on_radio_tx_timeout( void )
00716 {
00717     if (_params.dev_class != CLASS_C ) {
00718         lora_phy->put_radio_to_sleep();
00719     } else {
00720         open_continuous_rx2_window();
00721     }
00722 
00723     mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ;
00724 
00725     mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ;
00726 
00727     _params.flags.bits.mac_done = 1;
00728 }
00729 
00730 void LoRaMac::on_radio_rx_error( void )
00731 {
00732     if (_params.dev_class != CLASS_C ) {
00733         lora_phy->put_radio_to_sleep();
00734     } else {
00735         open_continuous_rx2_window();
00736     }
00737 
00738     if (_params.rx_slot == RX_SLOT_WIN_1 ) {
00739         if (_params.is_node_ack_requested == true) {
00740             mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ;
00741         }
00742 
00743         mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX1_ERROR ;
00744 
00745         if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time) >= _params.rx_window2_delay) {
00746             _lora_time.stop(_params.timers.rx_window2_timer);
00747             _params.flags.bits.mac_done = 1;
00748         }
00749 
00750     } else {
00751 
00752         if (_params.is_node_ack_requested == true) {
00753             mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ;
00754         }
00755 
00756         mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ;
00757 
00758         _params.flags.bits.mac_done = 1;
00759     }
00760 }
00761 
00762 void LoRaMac::on_radio_rx_timeout(void)
00763 {
00764     if (_params.dev_class != CLASS_C ) {
00765         lora_phy->put_radio_to_sleep();
00766     } else {
00767         open_continuous_rx2_window();
00768     }
00769 
00770     if (_params.rx_slot == RX_SLOT_WIN_1 ) {
00771         if (_params.is_node_ack_requested == true) {
00772             mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT ;
00773         }
00774         mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX1_TIMEOUT ;
00775 
00776         if (_lora_time.get_elapsed_time(_params.timers.aggregated_last_tx_time ) >= _params.rx_window2_delay) {
00777             _lora_time.stop(_params.timers.rx_window2_timer);
00778             _params.flags.bits.mac_done = 1;
00779         }
00780 
00781     } else {
00782 
00783         if (_params.is_node_ack_requested == true) {
00784             mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ;
00785         }
00786 
00787         mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ;
00788 
00789         if (_params.dev_class != CLASS_C ) {
00790             _params.flags.bits.mac_done = 1;
00791         }
00792     }
00793 }
00794 
00795 /***************************************************************************
00796  * Timer event callbacks - deliberated locally                             *
00797  **************************************************************************/
00798 void LoRaMac::on_mac_state_check_timer_event(void)
00799 {
00800     bool tx_timeout = false;
00801 
00802     _lora_time.stop(_params.timers.mac_state_check_timer);
00803 
00804     if (_params.flags.bits.mac_done == 1) {
00805 
00806         if ((_params.mac_state & LORAMAC_RX_ABORT) == LORAMAC_RX_ABORT) {
00807             _params.mac_state &= ~LORAMAC_RX_ABORT;
00808             _params.mac_state &= ~LORAMAC_TX_RUNNING;
00809         }
00810 
00811         if ((_params.flags.bits.mlme_req == 1) || (_params.flags.bits.mcps_req == 1)) {
00812 
00813             if ((mcps.get_confirmation().status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) ||
00814                 ( mlme.get_confirmation().status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT )) {
00815                 // Stop transmit cycle due to tx timeout.
00816                 _params.mac_state &= ~LORAMAC_TX_RUNNING;
00817                 mac_commands.clear_command_buffer();
00818                 mcps.get_confirmation().nb_retries = _params.ack_timeout_retry_counter;
00819                 mcps.get_confirmation().ack_received = false;
00820                 mcps.get_confirmation().tx_toa = 0;
00821                 tx_timeout = true;
00822             }
00823         }
00824 
00825         if ((_params.is_node_ack_requested == false) && (tx_timeout == false)) {
00826             if ((_params.flags.bits.mlme_req == 1) || ((_params.flags.bits.mcps_req == 1))) {
00827                 if ((_params.flags.bits.mlme_req == 1) && (mlme.get_confirmation().req_type == MLME_JOIN )) {
00828                     // Procedure for the join request
00829                     mlme.get_confirmation().nb_retries = _params.join_request_trial_counter;
00830 
00831                     if (mlme.get_confirmation().status == LORAMAC_EVENT_INFO_STATUS_OK ) {
00832                         // Node joined successfully
00833                         _params.ul_frame_counter = 0;
00834                         _params.ul_nb_rep_counter = 0;
00835                         _params.mac_state &= ~LORAMAC_TX_RUNNING;
00836                     } else {
00837                         if (_params.join_request_trial_counter >= _params.max_join_request_trials) {
00838                             _params.mac_state &= ~LORAMAC_TX_RUNNING;
00839                         } else {
00840                             _params.flags.bits.mac_done = 0;
00841                             // Sends the same frame again
00842                             handle_delayed_tx_timer_event();
00843                         }
00844                     }
00845                 } else {
00846                     // Procedure for all other frames
00847                     if ((_params.ul_nb_rep_counter >= _params.sys_params.retry_num) ||
00848                         (_params.flags.bits.mcps_ind == 1)) {
00849                         if (_params.flags.bits.mcps_ind == 0) {
00850                             // Maximum repetitions without downlink. Reset MacCommandsBufferIndex. Increase ADR Ack counter.
00851                             // Only process the case when the MAC did not receive a downlink.
00852                             mac_commands.clear_command_buffer();
00853                             _params.adr_ack_counter++;
00854                         }
00855 
00856                         _params.ul_nb_rep_counter = 0;
00857 
00858                         if (_params.is_ul_frame_counter_fixed == false) {
00859                             _params.ul_frame_counter++;
00860                         }
00861 
00862                         _params.mac_state &= ~LORAMAC_TX_RUNNING;
00863                     } else {
00864                         _params.flags.bits.mac_done = 0;
00865                         // Sends the same frame again
00866                         handle_delayed_tx_timer_event();
00867                     }
00868                 }
00869             }
00870         }
00871 
00872         if (_params.flags.bits.mcps_ind == 1) {
00873             // Procedure if we received a frame
00874             if ((mcps.get_confirmation().ack_received == true) ||
00875                 (_params.ack_timeout_retry_counter > _params.max_ack_timeout_retries)) {
00876                 _params.is_ack_retry_timeout_expired = false;
00877                 _params.is_node_ack_requested = false;
00878                 if (_params.is_ul_frame_counter_fixed == false) {
00879                     _params.ul_frame_counter++;
00880                 }
00881                 mcps.get_confirmation().nb_retries = _params.ack_timeout_retry_counter;
00882 
00883                 _params.mac_state &= ~LORAMAC_TX_RUNNING;
00884             }
00885         }
00886 
00887         if ((_params.is_ack_retry_timeout_expired == true) &&
00888             ((_params.mac_state & LORAMAC_TX_DELAYED) == 0)) {
00889 
00890             // Retransmissions procedure for confirmed uplinks
00891             _params.is_ack_retry_timeout_expired = false;
00892             if ((_params.ack_timeout_retry_counter < _params.max_ack_timeout_retries) &&
00893                 (_params.ack_timeout_retry_counter <= MAX_ACK_RETRIES)) {
00894 
00895                 _params.ack_timeout_retry_counter++;
00896 
00897                 if ((_params.ack_timeout_retry_counter % 2) == 1) {
00898                     _params.sys_params.channel_data_rate = lora_phy->get_next_lower_tx_datarate(
00899                                                            _params.sys_params.channel_data_rate);
00900                 }
00901 
00902                 // Try to send the frame again
00903                 if (schedule_tx() == LORAWAN_STATUS_OK) {
00904                     _params.flags.bits.mac_done = 0;
00905                 } else {
00906                     // The DR is not applicable for the payload size
00907                     mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_TX_DR_PAYLOAD_SIZE_ERROR ;
00908 
00909                     mac_commands.clear_command_buffer();
00910                     _params.mac_state &= ~LORAMAC_TX_RUNNING;
00911                     _params.is_node_ack_requested = false;
00912                     mcps.get_confirmation().ack_received = false;
00913                     mcps.get_confirmation().nb_retries = _params.ack_timeout_retry_counter;
00914                     mcps.get_confirmation().data_rate = _params.sys_params.channel_data_rate;
00915 
00916                     if (_params.is_ul_frame_counter_fixed == false) {
00917                         _params.ul_frame_counter++;
00918                     }
00919                 }
00920             } else {
00921                 lora_phy->restore_default_channels();
00922 
00923                 _params.mac_state &= ~LORAMAC_TX_RUNNING;
00924 
00925                 mac_commands.clear_command_buffer();
00926                 _params.is_node_ack_requested = false;
00927                 mcps.get_confirmation().ack_received = false;
00928                 mcps.get_confirmation().nb_retries = _params.ack_timeout_retry_counter;
00929 
00930                 if (_params.is_ul_frame_counter_fixed == false) {
00931                     _params.ul_frame_counter++;
00932                 }
00933             }
00934         }
00935     }
00936 
00937     // Handle reception for Class B and Class C
00938     if ((_params.mac_state & LORAMAC_RX) == LORAMAC_RX) {
00939         _params.mac_state &= ~LORAMAC_RX;
00940     }
00941 
00942     if (_params.mac_state == LORAMAC_IDLE) {
00943         if (_params.flags.bits.mcps_req == 1) {
00944             _params.flags.bits.mcps_req = 0;
00945             mac_primitives->mcps_confirm(&mcps.get_confirmation());
00946         }
00947 
00948         if (_params.flags.bits.mlme_req == 1) {
00949             _params.flags.bits.mlme_req = 0;
00950             mac_primitives->mlme_confirm(&mlme.get_confirmation());
00951         }
00952 
00953         // Verify if sticky MAC commands are pending or not
00954         if (mac_commands.is_sticky_mac_command_pending() == true) {
00955             // Setup MLME indication
00956             set_mlme_schedule_ul_indication();
00957         }
00958 
00959         // Procedure done. Reset variables.
00960         _params.flags.bits.mac_done = 0;
00961     } else {
00962         // Operation not finished restart timer
00963         _lora_time.start(_params.timers.mac_state_check_timer, MAC_STATE_CHECK_TIMEOUT);
00964     }
00965 
00966     // Handle MCPS indication
00967     if (_params.flags.bits.mcps_ind == 1) {
00968         _params.flags.bits.mcps_ind = 0;
00969 
00970         if (_params.dev_class== CLASS_C ) {
00971             // Activate RX2 window for Class C
00972             open_continuous_rx2_window();
00973         }
00974 
00975         if (_params.flags.bits.mcps_ind_skip == 0) {
00976             mac_primitives->mcps_indication(&mcps.get_indication());
00977         }
00978 
00979         _params.flags.bits.mcps_ind_skip = 0;
00980     }
00981 
00982     // Handle MLME indication
00983     if (_params.flags.bits.mlme_ind == 1) {
00984         _params.flags.bits.mlme_ind = 0;
00985         mac_primitives->mlme_indication(&mlme.get_indication());
00986     }
00987 }
00988 
00989 void LoRaMac::on_tx_delayed_timer_event(void)
00990 {
00991     loramac_mhdr_t  mac_hdr;
00992     loramac_frame_ctrl_t  fctrl;
00993 
00994     lorawan_status_t status = LORAWAN_STATUS_OK;
00995 
00996     _lora_time.stop(_params.timers.tx_delayed_timer);
00997     _params.mac_state &= ~LORAMAC_TX_DELAYED;
00998 
00999     if ((_params.flags.bits.mlme_req == 1 ) &&
01000         (mlme.get_confirmation().req_type == MLME_JOIN )) {
01001 
01002         reset_mac_parameters();
01003 
01004         _params.sys_params.channel_data_rate = lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1);
01005 
01006         mac_hdr.value  = 0;
01007         mac_hdr.bits.mtype  = FRAME_TYPE_JOIN_REQ ;
01008 
01009         fctrl.value  = 0;
01010         fctrl.bits.adr  = _params.sys_params.adr_on;
01011 
01012         /* In case of join request retransmissions, the stack must prepare
01013          * the frame again, because the network server keeps track of the random
01014          * LoRaMacDevNonce values to prevent reply attacks. */
01015         status = prepare_frame(&mac_hdr, &fctrl, 0, NULL, 0);
01016     }
01017 
01018     if (status == LORAWAN_STATUS_OK) {
01019         schedule_tx();
01020     } else {
01021         tr_error("Delayed TX: PrepareFrame returned error %d", status);
01022     }
01023 }
01024 
01025 void LoRaMac::on_rx_window1_timer_event(void)
01026 {
01027     _lora_time.stop(_params.timers.rx_window1_timer);
01028     _params.rx_slot = RX_SLOT_WIN_1 ;
01029 
01030     _params.rx_window1_config.channel = _params.channel;
01031     _params.rx_window1_config.dr_offset = _params.sys_params.rx1_dr_offset;
01032     _params.rx_window1_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
01033     _params.rx_window1_config.is_repeater_supported = _params.is_repeater_supported;
01034     _params.rx_window1_config.is_rx_continuous = false;
01035     _params.rx_window1_config.rx_slot = _params.rx_slot;
01036 
01037     if (_params.dev_class == CLASS_C ) {
01038         lora_phy->put_radio_to_standby();
01039     }
01040 
01041     lora_phy->rx_config(&_params.rx_window1_config,
01042                         (int8_t*) &mcps.get_indication().rx_datarate);
01043 
01044     rx_window_setup(_params.rx_window1_config.is_rx_continuous,
01045                     _params.sys_params.max_rx_win_time);
01046 }
01047 
01048 void LoRaMac::on_rx_window2_timer_event(void)
01049 {
01050     _lora_time.stop(_params.timers.rx_window2_timer);
01051 
01052     _params.rx_window2_config.channel = _params.channel;
01053     _params.rx_window2_config.frequency = _params.sys_params.rx2_channel.frequency;
01054     _params.rx_window2_config.dl_dwell_time = _params.sys_params.downlink_dwell_time;
01055     _params.rx_window2_config.is_repeater_supported = _params.is_repeater_supported;
01056     _params.rx_window2_config.rx_slot = RX_SLOT_WIN_2 ;
01057 
01058     if (_params.dev_class != CLASS_C ) {
01059         _params.rx_window2_config.is_rx_continuous = false;
01060     } else {
01061         // Setup continuous listening for class c
01062         _params.rx_window2_config.is_rx_continuous = true;
01063     }
01064 
01065     if (lora_phy->rx_config(&_params.rx_window2_config,
01066                             (int8_t*) &mcps.get_indication().rx_datarate) == true) {
01067 
01068         rx_window_setup(_params.rx_window2_config.is_rx_continuous,
01069                         _params.sys_params.max_rx_win_time);
01070 
01071         _params.rx_slot = RX_SLOT_WIN_2 ;
01072     }
01073 }
01074 
01075 void LoRaMac::on_ack_timeout_timer_event(void)
01076 {
01077     _lora_time.stop(_params.timers.ack_timeout_timer);
01078 
01079     if (_params.is_node_ack_requested == true) {
01080         _params.is_ack_retry_timeout_expired = true;
01081         _params.mac_state &= ~LORAMAC_ACK_REQ;
01082     }
01083     if (_params.dev_class == CLASS_C ) {
01084         _params.flags.bits.mac_done = 1;
01085     }
01086 }
01087 
01088 void LoRaMac::rx_window_setup(bool rx_continuous, uint32_t max_rx_window_time)
01089 {
01090     lora_phy->setup_rx_window(rx_continuous, max_rx_window_time);
01091 }
01092 
01093 bool LoRaMac::validate_payload_length(uint8_t length, int8_t datarate,
01094                                       uint8_t fopts_len)
01095 {
01096     uint16_t max_value = 0;
01097     uint16_t payloadSize = 0;
01098 
01099     max_value = lora_phy->get_max_payload(datarate, _params.is_repeater_supported);
01100 
01101     // Calculate the resulting payload size
01102     payloadSize = (length + fopts_len);
01103 
01104     // Validation of the application payload size
01105     if ((payloadSize <= max_value) &&
01106         (payloadSize <= LORAMAC_PHY_MAXPAYLOAD)) {
01107         return true;
01108     }
01109     return false;
01110 }
01111 
01112 void LoRaMac::set_mlme_schedule_ul_indication(void)
01113 {
01114     mlme.get_indication().indication_type = MLME_SCHEDULE_UPLINK ;
01115     _params.flags.bits.mlme_ind = 1;
01116 }
01117 
01118 // This is not actual transmission. It just schedules a message in response
01119 // to MCPS request
01120 lorawan_status_t LoRaMac::send(loramac_mhdr_t  *machdr, uint8_t fport,
01121                                void *fbuffer, uint16_t fbuffer_size)
01122 {
01123     loramac_frame_ctrl_t  fctrl;
01124 
01125     fctrl.value  = 0;
01126     fctrl.bits.fopts_len  = 0;
01127     fctrl.bits.fpending  = 0;
01128     fctrl.bits.ack  = false;
01129     fctrl.bits.adr_ack_req  = false;
01130     fctrl.bits.adr  = _params.sys_params.adr_on;
01131 
01132     // Prepare the frame
01133     lorawan_status_t status = prepare_frame(machdr, &fctrl, fport, fbuffer,
01134                                             fbuffer_size);
01135 
01136     // Validate status
01137     if (status != LORAWAN_STATUS_OK) {
01138         return status;
01139     }
01140 
01141     // Reset confirm parameters
01142     mcps.get_confirmation().nb_retries = 0;
01143     mcps.get_confirmation().ack_received = false;
01144     mcps.get_confirmation().ul_frame_counter = _params.ul_frame_counter;
01145 
01146     status = schedule_tx();
01147 
01148     return status;
01149 }
01150 
01151 lorawan_status_t LoRaMac::schedule_tx(void)
01152 {
01153     lorawan_time_t dutyCycleTimeOff = 0;
01154     channel_selection_params_t nextChan;
01155 
01156     // Check if the device is off
01157     if (_params.sys_params.max_duty_cycle == 255) {
01158         return LORAWAN_STATUS_DEVICE_OFF;
01159     }
01160 
01161     if (_params.sys_params.max_duty_cycle == 0) {
01162         _params.timers.aggregated_timeoff = 0;
01163     }
01164 
01165     // Update Backoff
01166     calculate_backOff(_params.last_channel_idx);
01167 
01168     nextChan.aggregate_timeoff = _params.timers.aggregated_timeoff;
01169     nextChan.current_datarate = _params.sys_params.channel_data_rate;
01170     _params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON;
01171     nextChan.dc_enabled = _params.is_dutycycle_on;
01172     nextChan.joined = _params.is_nwk_joined;
01173     nextChan.last_aggregate_tx_time = _params.timers.aggregated_last_tx_time;
01174 
01175     // Select channel
01176     while (lora_phy->set_next_channel(&nextChan, &_params.channel,
01177                                       &dutyCycleTimeOff,
01178                                       &_params.timers.aggregated_timeoff) == false) {
01179         _params.sys_params.channel_data_rate = lora_phy->get_default_tx_datarate();
01180         // Update datarate in the function parameters
01181         nextChan.current_datarate = _params.sys_params.channel_data_rate;
01182     }
01183 
01184     tr_debug("Next Channel Idx=%d, DR=%d", _params.channel, nextChan.current_datarate);
01185 
01186     // Compute Rx1 windows parameters
01187     uint8_t dr_offset = lora_phy->apply_DR_offset(_params.sys_params.channel_data_rate,
01188                                                   _params.sys_params.rx1_dr_offset);
01189 
01190     lora_phy->compute_rx_win_params(dr_offset, _params.sys_params.min_rx_symb,
01191                                     _params.sys_params.max_sys_rx_error,
01192                                     &_params.rx_window1_config);
01193 
01194     // Compute Rx2 windows parameters
01195     lora_phy->compute_rx_win_params(_params.sys_params.rx2_channel.datarate,
01196                                     _params.sys_params.min_rx_symb,
01197                                     _params.sys_params.max_sys_rx_error,
01198                                     &_params.rx_window2_config);
01199 
01200     if (_params.is_nwk_joined == false) {
01201         _params.rx_window1_delay = _params.sys_params.join_accept_delay1
01202                 + _params.rx_window1_config.window_offset;
01203         _params.rx_window2_delay = _params.sys_params.join_accept_delay2
01204                 + _params.rx_window2_config.window_offset;
01205     } else {
01206         if (validate_payload_length(_params.payload_length,
01207                                     _params.sys_params.channel_data_rate,
01208                                     mac_commands.get_mac_cmd_length()) == false) {
01209             return LORAWAN_STATUS_LENGTH_ERROR;
01210         }
01211         _params.rx_window1_delay = _params.sys_params.recv_delay1
01212                 + _params.rx_window1_config.window_offset;
01213         _params.rx_window2_delay = _params.sys_params.recv_delay2
01214                 + _params.rx_window2_config.window_offset;
01215     }
01216 
01217     // Schedule transmission of frame
01218     if (dutyCycleTimeOff == 0) {
01219         // Try to send now
01220         return send_frame_on_channel(_params.channel);
01221     } else {
01222         // Send later - prepare timer
01223         _params.mac_state |= LORAMAC_TX_DELAYED;
01224         tr_debug("Next Transmission in %lu ms", dutyCycleTimeOff);
01225 
01226         _lora_time.start(_params.timers.tx_delayed_timer, dutyCycleTimeOff);
01227 
01228         return LORAWAN_STATUS_OK;
01229     }
01230 }
01231 
01232 void LoRaMac::calculate_backOff(uint8_t channel)
01233 {
01234     backoff_params_t  backoff_params;
01235 
01236     backoff_params.joined = _params.is_nwk_joined;
01237     _params.is_dutycycle_on = MBED_CONF_LORA_DUTY_CYCLE_ON;
01238     backoff_params.dc_enabled = _params.is_dutycycle_on;
01239     backoff_params.channel = channel;
01240     backoff_params.elapsed_time = _lora_time.get_elapsed_time(_params.timers.mac_init_time);
01241     backoff_params.tx_toa = _params.timers.tx_toa;
01242     backoff_params.last_tx_was_join_req = _params.is_last_tx_join_request;
01243 
01244     // Update regional back-off
01245     lora_phy->calculate_backoff(&backoff_params);
01246 
01247     // Update aggregated time-off
01248     _params.timers.aggregated_timeoff = _params.timers.aggregated_timeoff
01249             + (_params.timers.tx_toa * _params.sys_params.aggregated_duty_cycle
01250             - _params.timers.tx_toa);
01251 }
01252 
01253 void LoRaMac::reset_mac_parameters(void)
01254 {
01255     _params.is_nwk_joined = false;
01256 
01257     // Counters
01258     _params.ul_frame_counter = 0;
01259     _params.dl_frame_counter = 0;
01260     _params.adr_ack_counter = 0;
01261 
01262     _params.ul_nb_rep_counter = 0;
01263 
01264     _params.max_ack_timeout_retries = 1;
01265     _params.ack_timeout_retry_counter = 1;
01266     _params.is_ack_retry_timeout_expired = false;
01267 
01268     _params.sys_params.max_duty_cycle = 0;
01269     _params.sys_params.aggregated_duty_cycle = 1;
01270 
01271     mac_commands.clear_command_buffer();
01272     mac_commands.clear_repeat_buffer();
01273     mac_commands.clear_mac_commands_in_next_tx();
01274 
01275     _params.is_rx_window_enabled = true;
01276 
01277     lora_phy->reset_to_default_values(&_params, false);
01278 
01279     _params.is_node_ack_requested = false;
01280     _params.is_srv_ack_requested = false;
01281 
01282     // Reset Multicast downlink counters
01283     multicast_params_t  *cur = _params.multicast_channels;
01284     while (cur != NULL) {
01285         cur->dl_frame_counter  = 0;
01286         cur = cur->next ;
01287     }
01288 
01289     // Initialize channel index.
01290     _params.channel = 0;
01291     _params.last_channel_idx = _params.channel;
01292 }
01293 
01294 bool LoRaMac::is_fPort_allowed (uint8_t fPort)
01295 {
01296     if ((fPort == 0) || (fPort > 224)) {
01297         return false;
01298     }
01299     return true;
01300 }
01301 
01302 void LoRaMac::open_continuous_rx2_window (void)
01303 {
01304     handle_rx2_timer_event();
01305     _params.rx_slot = RX_SLOT_WIN_CLASS_C ;
01306 }
01307 
01308 static void memcpy_convert_endianess(uint8_t *dst, const uint8_t *src,
01309                                      uint16_t size)
01310 {
01311     dst = dst + (size - 1);
01312     while (size--) {
01313         *dst-- = *src++;
01314     }
01315 }
01316 
01317 lorawan_status_t LoRaMac::prepare_frame(loramac_mhdr_t  *machdr,
01318                                         loramac_frame_ctrl_t  *fctrl,
01319                                         uint8_t fport, void *fbuffer,
01320                                         uint16_t fbuffer_size)
01321 {
01322     uint16_t i;
01323     uint8_t pkt_header_len = 0;
01324     uint32_t mic = 0;
01325     const void* payload = fbuffer;
01326     uint8_t frame_port = fport;
01327     lorawan_status_t status = LORAWAN_STATUS_OK;
01328 
01329     _params.buffer_pkt_len = 0;
01330 
01331     _params.is_node_ack_requested = false;
01332 
01333     if (fbuffer == NULL) {
01334         fbuffer_size = 0;
01335     }
01336 
01337     _params.payload_length = fbuffer_size;
01338 
01339     _params.buffer[pkt_header_len++] = machdr->value ;
01340 
01341     switch (machdr->bits.mtype ) {
01342 
01343         case FRAME_TYPE_JOIN_REQ :
01344 
01345             _params.buffer_pkt_len = pkt_header_len;
01346             memcpy_convert_endianess(_params.buffer + _params.buffer_pkt_len,
01347                                      _params.keys.app_eui, 8);
01348             _params.buffer_pkt_len += 8;
01349             memcpy_convert_endianess(_params.buffer + _params.buffer_pkt_len,
01350                                      _params.keys.dev_eui, 8);
01351             _params.buffer_pkt_len += 8;
01352 
01353             _params.dev_nonce = lora_phy->get_radio_rng();
01354 
01355             _params.buffer[_params.buffer_pkt_len++] = _params.dev_nonce & 0xFF;
01356             _params.buffer[_params.buffer_pkt_len++] = (_params.dev_nonce >> 8) & 0xFF;
01357 
01358             if (0 != compute_join_frame_mic(_params.buffer,
01359                                            _params.buffer_pkt_len & 0xFF,
01360                                            _params.keys.app_key, &mic)) {
01361                 return LORAWAN_STATUS_CRYPTO_FAIL;
01362             }
01363 
01364             _params.buffer[_params.buffer_pkt_len++] = mic & 0xFF;
01365             _params.buffer[_params.buffer_pkt_len++] = (mic >> 8) & 0xFF;
01366             _params.buffer[_params.buffer_pkt_len++] = (mic >> 16) & 0xFF;
01367             _params.buffer[_params.buffer_pkt_len++] = (mic >> 24) & 0xFF;
01368 
01369             break;
01370         case FRAME_TYPE_DATA_CONFIRMED_UP :
01371             _params.is_node_ack_requested = true;
01372             //Intentional fallthrough
01373         case FRAME_TYPE_DATA_UNCONFIRMED_UP : {
01374             if (_params.is_nwk_joined == false) {
01375                 // No network has been joined yet
01376                 return LORAWAN_STATUS_NO_NETWORK_JOINED;
01377             }
01378 
01379             if (_params.sys_params.adr_on) {
01380                 if (lora_phy->get_next_ADR(true,
01381                                            _params.sys_params.channel_data_rate,
01382                                            _params.sys_params.channel_tx_power,
01383                                            _params.adr_ack_counter)) {
01384                     fctrl->bits.adr_ack_req  = 1;
01385                 }
01386             }
01387 
01388             if (_params.is_srv_ack_requested == true) {
01389                 _params.is_srv_ack_requested = false;
01390                 fctrl->bits.ack  = 1;
01391             }
01392 
01393             _params.buffer[pkt_header_len++] = (_params.dev_addr) & 0xFF;
01394             _params.buffer[pkt_header_len++] = (_params.dev_addr >> 8) & 0xFF;
01395             _params.buffer[pkt_header_len++] = (_params.dev_addr >> 16) & 0xFF;
01396             _params.buffer[pkt_header_len++] = (_params.dev_addr >> 24) & 0xFF;
01397 
01398             _params.buffer[pkt_header_len++] = fctrl->value ;
01399 
01400             _params.buffer[pkt_header_len++] = _params.ul_frame_counter & 0xFF;
01401             _params.buffer[pkt_header_len++] = (_params.ul_frame_counter >> 8)
01402                     & 0xFF;
01403 
01404             // Copy the MAC commands which must be re-send into the MAC command buffer
01405             mac_commands.copy_repeat_commands_to_buffer();
01406 
01407             const uint8_t mac_commands_len = mac_commands.get_mac_cmd_length();
01408 
01409             if ((payload != NULL) && (_params.payload_length > 0)) {
01410                 if (mac_commands.is_mac_command_in_next_tx() == true) {
01411                     if (mac_commands_len <= LORA_MAC_COMMAND_MAX_FOPTS_LENGTH) {
01412                         fctrl->bits.fopts_len  += mac_commands_len;
01413 
01414                         // Update FCtrl field with new value of OptionsLength
01415                         _params.buffer[0x05] = fctrl->value ;
01416 
01417                         const uint8_t *buffer =
01418                                 mac_commands.get_mac_commands_buffer();
01419                         for (i = 0; i < mac_commands_len; i++) {
01420                             _params.buffer[pkt_header_len++] = buffer[i];
01421                         }
01422                     } else {
01423                         _params.payload_length  = mac_commands_len;
01424                         payload = mac_commands.get_mac_commands_buffer();
01425                         frame_port = 0;
01426                     }
01427                 }
01428             } else {
01429                 if ((mac_commands_len > 0)
01430                         && (mac_commands.is_mac_command_in_next_tx() == true)) {
01431                     _params.payload_length = mac_commands_len;
01432                     payload = mac_commands.get_mac_commands_buffer();
01433                     frame_port = 0;
01434                 }
01435             }
01436 
01437             // Store MAC commands which must be re-send in case the device does not receive a downlink anymore
01438             mac_commands.parse_mac_commands_to_repeat();
01439 
01440             if ((payload != NULL) && (_params.payload_length > 0)) {
01441                 _params.buffer[pkt_header_len++] = frame_port;
01442 
01443                 if (frame_port == 0) {
01444                     // Reset buffer index as the mac commands are being sent on port 0
01445                     mac_commands.clear_command_buffer();
01446                     if (0 != encrypt_payload((uint8_t*) payload, _params.payload_length,
01447                                                    _params.keys.nwk_skey, _params.dev_addr,
01448                                                    UP_LINK,
01449                                                    _params.ul_frame_counter,
01450                                                    &_params.buffer[pkt_header_len])) {
01451                         status = LORAWAN_STATUS_CRYPTO_FAIL;
01452                     }
01453                 } else {
01454                     if (0 != encrypt_payload((uint8_t*) payload, _params.payload_length,
01455                                                    _params.keys.app_skey, _params.dev_addr,
01456                                                    UP_LINK,
01457                                                    _params.ul_frame_counter,
01458                                                    &_params.buffer[pkt_header_len])) {
01459                         status = LORAWAN_STATUS_CRYPTO_FAIL;
01460                     }
01461                 }
01462             }
01463 
01464             _params.buffer_pkt_len = pkt_header_len + _params.payload_length;
01465 
01466             if (0 != compute_mic(_params.buffer, _params.buffer_pkt_len,
01467                                        _params.keys.nwk_skey,
01468                                        _params.dev_addr,
01469                                        UP_LINK,
01470                                        _params.ul_frame_counter, &mic)) {
01471                 status = LORAWAN_STATUS_CRYPTO_FAIL;
01472             }
01473 
01474             _params.buffer[_params.buffer_pkt_len + 0] = mic & 0xFF;
01475             _params.buffer[_params.buffer_pkt_len + 1] = (mic >> 8) & 0xFF;
01476             _params.buffer[_params.buffer_pkt_len + 2] = (mic >> 16) & 0xFF;
01477             _params.buffer[_params.buffer_pkt_len + 3] = (mic >> 24) & 0xFF;
01478 
01479             _params.buffer_pkt_len += LORAMAC_MFR_LEN;
01480         }
01481             break;
01482         case FRAME_TYPE_PROPRIETARY :
01483             if ((fbuffer != NULL) && (_params.payload_length > 0)) {
01484                 memcpy(_params.buffer + pkt_header_len, (uint8_t*) fbuffer,
01485                        _params.payload_length);
01486                 _params.buffer_pkt_len = pkt_header_len + _params.payload_length;
01487             }
01488             break;
01489         default:
01490             status = LORAWAN_STATUS_SERVICE_UNKNOWN;
01491     }
01492 
01493     return status;
01494 }
01495 
01496 lorawan_status_t LoRaMac::send_frame_on_channel(uint8_t channel)
01497 {
01498     tx_config_params_t tx_config;
01499     int8_t tx_power = 0;
01500 
01501     tx_config.channel = channel;
01502     tx_config.datarate = _params.sys_params.channel_data_rate;
01503     tx_config.tx_power = _params.sys_params.channel_tx_power;
01504     tx_config.max_eirp = _params.sys_params.max_eirp;
01505     tx_config.antenna_gain = _params.sys_params.antenna_gain;
01506     tx_config.pkt_len = _params.buffer_pkt_len;
01507 
01508     lora_phy->tx_config(&tx_config, &tx_power, &_params.timers.tx_toa);
01509 
01510     mlme.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01511 
01512     mcps.get_confirmation().status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01513     mcps.get_confirmation().data_rate = _params.sys_params.channel_data_rate;
01514     mcps.get_confirmation().tx_power = tx_power;
01515 
01516     // Store the time on air
01517     mcps.get_confirmation().tx_toa = _params.timers.tx_toa;
01518     mlme.get_confirmation().tx_toa = _params.timers.tx_toa;
01519 
01520     // Starts the MAC layer status check timer
01521     _lora_time.start(_params.timers.mac_state_check_timer,
01522                      MAC_STATE_CHECK_TIMEOUT);
01523 
01524     if (_params.is_nwk_joined == false) {
01525         _params.join_request_trial_counter++;
01526     }
01527 
01528     // Send now
01529     lora_phy->handle_send(_params.buffer, _params.buffer_pkt_len);
01530 
01531     _params.mac_state |= LORAMAC_TX_RUNNING;
01532 
01533     return LORAWAN_STATUS_OK;
01534 }
01535 
01536 //lorawan_status_t LoRaMac::set_tx_continuous_wave(uint16_t timeout)
01537 //{
01538 //    cw_mode_params_t continuous_wave;
01539 
01540 //    continuous_wave.channel = _params.channel;
01541 //    continuous_wave.datarate = _params.sys_params.channel_data_rate;
01542 //    continuous_wave.tx_power = _params.sys_params.channel_tx_power;
01543 //    continuous_wave.max_eirp = _params.sys_params.max_eirp;
01544 //    continuous_wave.antenna_gain = _params.sys_params.antenna_gain;
01545 //    continuous_wave.timeout = timeout;
01546 
01547 //    lora_phy->set_tx_cont_mode(&continuous_wave);
01548 
01549 //    // Starts the MAC layer status check timer
01550 //    _lora_time.start(_params.timers.mac_state_check_timer,
01551 //                     MAC_STATE_CHECK_TIMEOUT);
01552 
01553 //    _params.mac_state |= LORAMAC_TX_RUNNING;
01554 
01555 //    return LORAWAN_STATUS_OK;
01556 //}
01557 
01558 //lorawan_status_t LoRaMac::set_tx_continuous_wave1(uint16_t timeout,
01559 //                                                  uint32_t frequency,
01560 //                                                  uint8_t power)
01561 //{
01562 //    cw_mode_params_t continuous_wave;
01563 
01564 //    continuous_wave.channel = 0;
01565 //    continuous_wave.datarate = 0;
01566 //    continuous_wave.tx_power = power;
01567 //    continuous_wave.max_eirp = 0;
01568 //    continuous_wave.antenna_gain = 0;
01569 //    continuous_wave.timeout = timeout;
01570 
01571 //    lora_phy->set_tx_cont_mode(&continuous_wave);
01572 
01573 //    // Starts the MAC layer status check timer
01574 //    _lora_time.start(_params.timers.mac_state_check_timer,
01575 //                     MAC_STATE_CHECK_TIMEOUT);
01576 
01577 //    _params.mac_state |= LORAMAC_TX_RUNNING;
01578 
01579 //    return LORAWAN_STATUS_OK;
01580 //}
01581 
01582 lorawan_status_t LoRaMac::initialize(loramac_primitives_t  *primitives,
01583                                      LoRaPHY *phy, EventQueue *queue)
01584 {
01585     //store event queue pointer
01586     ev_queue = queue;
01587 
01588     if (!primitives) {
01589         return LORAWAN_STATUS_PARAMETER_INVALID;
01590     }
01591 
01592     lora_phy = phy;
01593 
01594     // Activate MLME subsystem
01595     mlme.activate_mlme_subsystem(lora_phy);
01596 
01597     // Activate MCPS subsystem
01598     mcps.activate_mcps_subsystem();
01599 
01600     // Activate MIB subsystem
01601     mib.activate_mib_subsystem(lora_phy);
01602 
01603     // Activate channel planning subsystem
01604     channel_plan.activate_channelplan_subsystem(lora_phy);
01605 
01606     mac_primitives = primitives;
01607 
01608     _params.flags.value = 0;
01609 
01610     _params.dev_class = CLASS_A ;
01611     _params.mac_state = LORAMAC_IDLE;
01612 
01613     _params.join_request_trial_counter = 0;
01614     _params.max_join_request_trials = 1;
01615     _params.is_repeater_supported = false;
01616 
01617     // Reset duty cycle times
01618     _params.timers.aggregated_last_tx_time = 0;
01619     _params.timers.aggregated_timeoff = 0;
01620 
01621     lora_phy->reset_to_default_values(&_params, true);
01622 
01623     // Init parameters which are not set in function ResetMacParameters
01624     _params.sys_params.max_sys_rx_error = 10;
01625     _params.sys_params.min_rx_symb = 6;
01626     _params.sys_params.retry_num = 1;
01627 
01628     reset_mac_parameters();
01629 
01630     // Random seed initialization
01631     srand(lora_phy->get_radio_rng());
01632 
01633     _params.is_nwk_public = MBED_CONF_LORA_PUBLIC_NETWORK;
01634     lora_phy->setup_public_network_mode(_params.is_nwk_public);
01635     lora_phy->put_radio_to_sleep();
01636 
01637     // Initialize timers
01638     _lora_time.init(_params.timers.mac_state_check_timer,
01639                     mbed::callback(this, &LoRaMac::handle_mac_state_check_timer_event));
01640     _lora_time.init(_params.timers.tx_delayed_timer,
01641                     mbed::callback(this, &LoRaMac::handle_delayed_tx_timer_event));
01642     _lora_time.init(_params.timers.rx_window1_timer,
01643                     mbed::callback(this, &LoRaMac::handle_rx1_timer_event));
01644     _lora_time.init(_params.timers.rx_window2_timer,
01645                     mbed::callback(this, &LoRaMac::handle_rx2_timer_event));
01646     _lora_time.init(_params.timers.ack_timeout_timer,
01647                     mbed::callback(this, &LoRaMac::handle_ack_timeout));
01648 
01649     // Store the current initialization time
01650     _params.timers.mac_init_time = _lora_time.get_current_time();
01651 
01652     return LORAWAN_STATUS_OK;
01653 }
01654 
01655 void LoRaMac::disconnect()
01656 {
01657     // Cancel all timers
01658     _lora_time.stop(_params.timers.mac_state_check_timer);
01659     _lora_time.stop(_params.timers.tx_delayed_timer);
01660     _lora_time.stop(_params.timers.rx_window1_timer);
01661     _lora_time.stop(_params.timers.rx_window2_timer);
01662     _lora_time.stop(_params.timers.ack_timeout_timer);
01663 
01664     // Put radio to sleep
01665     lora_phy->put_radio_to_sleep();
01666 
01667     // Reset internal state
01668     _params.is_nwk_joined = false;
01669     _params.is_ack_retry_timeout_expired = false;
01670     _params.is_rx_window_enabled = true;
01671     _params.is_node_ack_requested = false;
01672     _params.is_srv_ack_requested = false;
01673     _params.flags.value = 0;
01674     _params.mac_state = 0;
01675 
01676     // Clear MAC commands
01677     mac_commands.clear_command_buffer();
01678     mac_commands.clear_repeat_buffer();
01679     mac_commands.clear_mac_commands_in_next_tx();
01680 
01681     // Set internal state to idle.
01682     _params.mac_state = LORAMAC_IDLE;
01683 }
01684 
01685 lorawan_status_t LoRaMac::query_tx_possible(uint8_t size,
01686                                             loramac_tx_info_t * tx_info)
01687 {
01688     uint8_t fopt_len = mac_commands.get_mac_cmd_length()
01689             + mac_commands.get_repeat_commands_length();
01690 
01691     if (tx_info == NULL) {
01692         return LORAWAN_STATUS_PARAMETER_INVALID;
01693     }
01694 
01695     // if applicaion has turned on ADR, we want to opt it out
01696     if (_params.sys_params.adr_on) {
01697         lora_phy->get_next_ADR(false, _params.sys_params.channel_data_rate,
01698                                _params.sys_params.channel_tx_power,
01699                                _params.adr_ack_counter);
01700     }
01701 
01702     tx_info->current_payload_size  = lora_phy->get_max_payload(_params.sys_params.channel_data_rate, _params.is_repeater_supported);
01703 
01704 
01705     // Verify if the fOpts fit into the maximum payload
01706     if (tx_info->current_payload_size  >= fopt_len) {
01707         tx_info->max_possible_payload_size  = tx_info->current_payload_size  - fopt_len;
01708     } else {
01709         tx_info->max_possible_payload_size  = tx_info->current_payload_size ;
01710         // The fOpts don't fit into the maximum payload. Omit the MAC commands to
01711         // ensure that another uplink is possible.
01712         fopt_len = 0;
01713         mac_commands.clear_command_buffer();
01714         mac_commands.clear_repeat_buffer();
01715     }
01716 
01717     // Verify if the fOpts and the payload fit into the maximum payload
01718     if (validate_payload_length(size, _params.sys_params.channel_data_rate,
01719                                 fopt_len) == false) {
01720         return LORAWAN_STATUS_LENGTH_ERROR;
01721     }
01722     return LORAWAN_STATUS_OK;
01723 }
01724 
01725 lorawan_status_t LoRaMac::add_channel_plan(const lorawan_channelplan_t& plan)
01726 {
01727     // Validate if the MAC is in a correct state
01728     if ((_params.mac_state & LORAMAC_TX_RUNNING) == LORAMAC_TX_RUNNING) {
01729         if ((_params.mac_state & LORAMAC_TX_CONFIG) != LORAMAC_TX_CONFIG) {
01730             return LORAWAN_STATUS_BUSY;
01731         }
01732     }
01733 
01734     return channel_plan.set_plan(plan);
01735 }
01736 
01737 lorawan_status_t LoRaMac::remove_channel_plan()
01738 {
01739     if ((_params.mac_state & LORAMAC_TX_RUNNING) == LORAMAC_TX_RUNNING) {
01740         if ((_params.mac_state & LORAMAC_TX_CONFIG) != LORAMAC_TX_CONFIG) {
01741             return LORAWAN_STATUS_BUSY;
01742         }
01743     }
01744 
01745     return channel_plan.remove_plan();
01746 
01747 }
01748 
01749 lorawan_status_t LoRaMac::get_channel_plan(lorawan_channelplan_t& plan)
01750 {
01751     // Request Mib to get channels
01752     loramac_mib_req_confirm_t  mib_confirm;
01753     memset(&mib_confirm, 0, sizeof(mib_confirm));
01754     mib_confirm.type  = MIB_CHANNELS ;
01755 
01756     lorawan_status_t status = mib.get_request(&mib_confirm, &_params);
01757 
01758     if (status != LORAWAN_STATUS_OK) {
01759         return status;
01760     }
01761 
01762     return channel_plan.get_plan(plan, &mib_confirm);
01763 }
01764 
01765 lorawan_status_t LoRaMac::remove_single_channel(uint8_t id)
01766 {
01767     if ((_params.mac_state & LORAMAC_TX_RUNNING) == LORAMAC_TX_RUNNING) {
01768         if ((_params.mac_state & LORAMAC_TX_CONFIG) != LORAMAC_TX_CONFIG) {
01769             return LORAWAN_STATUS_BUSY;
01770         }
01771     }
01772 
01773     return channel_plan.remove_single_channel(id);
01774 }
01775 
01776 lorawan_status_t LoRaMac::multicast_channel_link(multicast_params_t  *channel_param)
01777 {
01778     if (channel_param == NULL) {
01779         return LORAWAN_STATUS_PARAMETER_INVALID;
01780     }
01781     if ((_params.mac_state & LORAMAC_TX_RUNNING) == LORAMAC_TX_RUNNING) {
01782         return LORAWAN_STATUS_BUSY;
01783     }
01784 
01785     // Reset downlink counter
01786     channel_param->dl_frame_counter  = 0;
01787 
01788     if (_params.multicast_channels == NULL) {
01789         // New node is the fist element
01790         _params.multicast_channels = channel_param;
01791     } else {
01792         multicast_params_t  *cur = _params.multicast_channels;
01793 
01794         // Search the last node in the list
01795         while (cur->next  != NULL) {
01796             cur = cur->next ;
01797         }
01798         // This function always finds the last node
01799         cur->next  = channel_param;
01800     }
01801 
01802     return LORAWAN_STATUS_OK;
01803 }
01804 
01805 lorawan_status_t LoRaMac::multicast_channel_unlink(
01806         multicast_params_t  *channel_param)
01807 {
01808     if (channel_param == NULL) {
01809         return LORAWAN_STATUS_PARAMETER_INVALID;
01810     }
01811     if ((_params.mac_state & LORAMAC_TX_RUNNING) == LORAMAC_TX_RUNNING) {
01812         return LORAWAN_STATUS_BUSY;
01813     }
01814 
01815     if (_params.multicast_channels != NULL) {
01816         if (_params.multicast_channels == channel_param) {
01817             // First element
01818             _params.multicast_channels = channel_param->next ;
01819         } else {
01820             multicast_params_t  *cur = _params.multicast_channels;
01821 
01822             // Search the node in the list
01823             while (cur->next  && cur->next  != channel_param) {
01824                 cur = cur->next ;
01825             }
01826             // If we found the node, remove it
01827             if (cur->next ) {
01828                 cur->next  = channel_param->next ;
01829             }
01830         }
01831         channel_param->next  = NULL;
01832     }
01833 
01834     return LORAWAN_STATUS_OK;
01835 }
01836 
01837 lorawan_status_t LoRaMac::mlme_request( loramac_mlme_req_t  *mlmeRequest )
01838 {
01839     if (LORAMAC_IDLE != _params.mac_state) {
01840         return LORAWAN_STATUS_BUSY;
01841     }
01842 
01843     mlme.reset_confirmation();
01844 
01845     mlme.get_confirmation().req_type = mlmeRequest->type ;
01846     _params.flags.bits.mlme_req = 1;
01847 
01848     lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN;
01849 
01850     if (MLME_LINK_CHECK  == mlmeRequest->type ) {
01851         status = mac_commands.add_mac_command(MOTE_MAC_LINK_CHECK_REQ , 0, 0);
01852     } else if (MLME_JOIN  == mlmeRequest->type ) {
01853         if ((_params.mac_state & LORAMAC_TX_DELAYED) == LORAMAC_TX_DELAYED) {
01854             return LORAWAN_STATUS_BUSY;
01855         }
01856 
01857         if ((mlmeRequest->req.join .dev_eui  == NULL)
01858                 || (mlmeRequest->req.join .app_eui  == NULL)
01859                 || (mlmeRequest->req.join .app_key  == NULL)
01860                 || (mlmeRequest->req.join .nb_trials  == 0)) {
01861             return LORAWAN_STATUS_PARAMETER_INVALID;
01862         }
01863         _params.keys.dev_eui = mlmeRequest->req.join .dev_eui ;
01864         _params.keys.app_eui = mlmeRequest->req.join .app_eui ;
01865         _params.keys.app_key = mlmeRequest->req.join .app_key ;
01866         _params.max_join_request_trials = mlmeRequest->req.join .nb_trials ;
01867 
01868         if (!lora_phy->verify_nb_join_trials(mlmeRequest->req.join .nb_trials )) {
01869             // Value not supported, get default
01870             _params.max_join_request_trials = MBED_CONF_LORA_NB_TRIALS;
01871         }
01872         // Reset variable JoinRequestTrials
01873         _params.join_request_trial_counter = 0;
01874 
01875         reset_mac_parameters();
01876 
01877         _params.sys_params.channel_data_rate =
01878                 lora_phy->get_alternate_DR(_params.join_request_trial_counter + 1);
01879 
01880         loramac_mhdr_t  machdr;
01881         machdr.value  = 0;
01882         machdr.bits.mtype  = FRAME_TYPE_JOIN_REQ ;
01883         status = send(&machdr, 0, NULL, 0);
01884     } else if (MLME_TXCW  == mlmeRequest->type ) {
01885         mlme.set_tx_continuous_wave(_params.channel, _params.sys_params.channel_data_rate, _params.sys_params.channel_tx_power,
01886                                     _params.sys_params.max_eirp, _params.sys_params.antenna_gain, mlmeRequest->req.cw_tx_mode .timeout );
01887         _lora_time.start(_params.timers.mac_state_check_timer,
01888                          MAC_STATE_CHECK_TIMEOUT);
01889 
01890         _params.mac_state |= LORAMAC_TX_RUNNING;
01891         status = LORAWAN_STATUS_OK;
01892     } else if (MLME_TXCW_1  == mlmeRequest->type ) {
01893         mlme.set_tx_continuous_wave(0, 0, mlmeRequest->req.cw_tx_mode .power , 0, 0, mlmeRequest->req.cw_tx_mode .timeout );
01894         _lora_time.start(_params.timers.mac_state_check_timer,
01895                          MAC_STATE_CHECK_TIMEOUT);
01896 
01897         _params.mac_state |= LORAMAC_TX_RUNNING;
01898         status = LORAWAN_STATUS_OK;
01899     }
01900 
01901     if (status != LORAWAN_STATUS_OK) {
01902         _params.is_node_ack_requested = false;
01903         _params.flags.bits.mlme_req = 0;
01904     }
01905 
01906 
01907     return status;
01908 }
01909 
01910 lorawan_status_t LoRaMac::mcps_request( loramac_mcps_req_t  *mcpsRequest )
01911 {
01912     if (_params.mac_state != LORAMAC_IDLE) {
01913         return LORAWAN_STATUS_BUSY;
01914     }
01915 
01916     loramac_mhdr_t  machdr;
01917     int8_t datarate = mcpsRequest->data_rate ;
01918     // TODO: The comment is different than the code???
01919     // Apply the minimum possible datarate.
01920     // Some regions have limitations for the minimum datarate.
01921     datarate = MAX(datarate, (int8_t)lora_phy->get_minimum_tx_datarate());
01922 
01923     machdr.value  = 0;
01924 
01925     mcps.reset_confirmation();
01926 
01927     _params.ack_timeout_retry_counter = 1;
01928     _params.max_ack_timeout_retries = 1;
01929 
01930     switch (mcpsRequest->type ) {
01931         case MCPS_UNCONFIRMED : {
01932             machdr.bits.mtype  = FRAME_TYPE_DATA_UNCONFIRMED_UP ;
01933             break;
01934         }
01935         case MCPS_CONFIRMED : {
01936             machdr.bits.mtype  = FRAME_TYPE_DATA_CONFIRMED_UP ;
01937             _params.max_ack_timeout_retries = mcpsRequest->nb_trials ;
01938             break;
01939         }
01940         case MCPS_PROPRIETARY : {
01941             machdr.bits.mtype  = FRAME_TYPE_PROPRIETARY ;
01942             break;
01943         }
01944         default:
01945             return LORAWAN_STATUS_PARAMETER_INVALID;
01946     }
01947 
01948 //    Filter fPorts
01949 //    TODO: Does not work with PROPRIETARY messages
01950 //    if( IsFPortAllowed( mcpsRequest->fport ) == false ) {
01951 //        return LORAWAN_STATUS_PARAMETER_INVALID;
01952 //    }
01953 
01954     if (_params.sys_params.adr_on == false) {
01955         if (lora_phy->verify_tx_datarate(datarate, false) == true) {
01956             _params.sys_params.channel_data_rate = datarate;
01957         } else {
01958             return LORAWAN_STATUS_PARAMETER_INVALID;
01959         }
01960     }
01961 
01962     lorawan_status_t status = send(&machdr, mcpsRequest->fport , mcpsRequest->f_buffer,
01963                                    mcpsRequest->f_buffer_size);
01964     if (status == LORAWAN_STATUS_OK) {
01965         mcps.get_confirmation().req_type = mcpsRequest->type ;
01966         _params.flags.bits.mcps_req = 1;
01967     } else {
01968         _params.is_node_ack_requested = false;
01969     }
01970 
01971     return status;
01972 }
01973 
01974 lorawan_status_t LoRaMac::mib_get_request_confirm( loramac_mib_req_confirm_t  *mibGet )
01975 {
01976     return mib.get_request(mibGet, &_params);
01977 }
01978 
01979 lorawan_status_t LoRaMac::mib_set_request_confirm( loramac_mib_req_confirm_t  *mibSet )
01980 {
01981     lorawan_status_t status = mib.set_request(mibSet, &_params);
01982     if (LORAWAN_STATUS_OK == status && CLASS_C  == _params.dev_class && (MIB_DEVICE_CLASS  == mibSet->type  ||
01983        (MIB_RX2_CHANNEL  == mibSet->type  && _params.is_nwk_joined))) {
01984         open_continuous_rx2_window();
01985     }
01986     return status;
01987 }
01988 
01989 radio_events_t *LoRaMac::get_phy_event_handlers()
01990 {
01991     radio_events.tx_done = mbed::callback(this, &LoRaMac::handle_tx_done);
01992     radio_events.rx_done = mbed::callback(this, &LoRaMac::handle_rx_done);
01993     radio_events.rx_error = mbed::callback(this, &LoRaMac::handle_rx_error);
01994     radio_events.tx_timeout = mbed::callback(this, &LoRaMac::handle_tx_timeout);
01995     radio_events.rx_timeout = mbed::callback(this, &LoRaMac::handle_rx_timeout);
01996 
01997     return &radio_events;
01998 }
01999 
02000 #if defined(LORAWAN_COMPLIANCE_TEST)
02001 /***************************************************************************
02002  * Compliance testing                                                      *
02003  **************************************************************************/
02004 
02005 lorawan_status_t LoRaMac::LoRaMacSetTxTimer( uint32_t TxDutyCycleTime )
02006 {
02007     _lora_time.start(tx_next_packet_timer, TxDutyCycleTime);
02008     return LORAWAN_STATUS_OK;
02009 }
02010 
02011  lorawan_status_t LoRaMac::LoRaMacStopTxTimer( )
02012 {
02013     _lora_time.stop(tx_next_packet_timer);
02014     return LORAWAN_STATUS_OK;
02015 }
02016 
02017 void LoRaMac::LoRaMacTestRxWindowsOn( bool enable )
02018 {
02019     _params.is_rx_window_enabled = enable;
02020 }
02021 
02022 void LoRaMac::LoRaMacTestSetMic( uint16_t txPacketCounter )
02023 {
02024     _params.ul_frame_counter = txPacketCounter;
02025     _params.is_ul_frame_counter_fixed = true;
02026 }
02027 
02028 void LoRaMac::LoRaMacTestSetDutyCycleOn( bool enable )
02029 {
02030     if(lora_phy->verify_duty_cycle(enable) == true)
02031     {
02032         _params.is_dutycycle_on = enable;
02033     }
02034 }
02035 
02036 void LoRaMac::LoRaMacTestSetChannel( uint8_t channel )
02037 {
02038     _params.channel = channel;
02039 }
02040 #endif