Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mac_pd_sap.c Source File

mac_pd_sap.c

00001 /*
00002  * Copyright (c) 2014-2018, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #include "nsconfig.h"
00018 #include "ns_types.h"
00019 #include "eventOS_event.h"
00020 #include "string.h"
00021 #include "nsdynmemLIB.h"
00022 #include "randLIB.h"
00023 #include "ccmLIB.h"
00024 #include "common_functions.h"
00025 #include "platform/arm_hal_interrupt.h"
00026 #include "mac_api.h"
00027 #include "fhss_api.h "
00028 #include "MAC/IEEE802_15_4/sw_mac_internal.h"
00029 #include "MAC/IEEE802_15_4/mac_pd_sap.h"
00030 #include "MAC/IEEE802_15_4/mac_defines.h"
00031 #include "MAC/IEEE802_15_4/mac_header_helper_functions.h"
00032 #include "MAC/IEEE802_15_4/mac_timer.h"
00033 #include "MAC/IEEE802_15_4/mac_security_mib.h"
00034 #include "MAC/IEEE802_15_4/mac_mlme.h"
00035 #include "MAC/IEEE802_15_4/mac_filter.h"
00036 #include "MAC/IEEE802_15_4/mac_mcps_sap.h"
00037 #include "MAC/rf_driver_storage.h"
00038 
00039 /* Define TX Timeot Period */
00040 // Hardcoded to 1200ms. Should be changed dynamic: (FHSS) channel retries needs longer timeout
00041 #define NWKTX_TIMEOUT_PERIOD (1200*20)
00042 // Measured 3750us with 1280 byte secured packet from calculating TX time to starting CSMA timer on PHY.
00043 // Typically varies from 500us to several milliseconds depending on packet size and the platform.
00044 // MAC should learn and make this dynamic by sending first few packets with predefined CSMA period.
00045 #define MIN_FHSS_CSMA_PERIOD_US    5000
00046 
00047 static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry);
00048 static void  mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr);
00049 
00050 void mac_csma_param_init(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00051 {
00052     rf_mac_setup->macCurrentBE = rf_mac_setup->macMinBE;
00053 }
00054 
00055 static void mac_csma_BE_update(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00056 {
00057     if (rf_mac_setup->macCurrentBE < rf_mac_setup->macMaxBE) {
00058         rf_mac_setup->macCurrentBE++;
00059     }
00060 }
00061 
00062 // 8-bit because maxBE is maximum 8 (according to 802.15.4)
00063 static uint8_t mac_csma_random_backoff_get(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00064 {
00065     return randLIB_get_random_in_range(0, (1 << rf_mac_setup->macCurrentBE) - 1);
00066 }
00067 
00068 static uint16_t mac_csma_backoff_period_convert_to50us(uint8_t random, uint8_t backoff_period_in_10us)
00069 {
00070     return (random * backoff_period_in_10us) / 5;
00071 }
00072 
00073 void mac_csma_backoff_start(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00074 {
00075     uint8_t backoff = mac_csma_random_backoff_get(rf_mac_setup);
00076     uint16_t backoff_slots = mac_csma_backoff_period_convert_to50us(backoff, rf_mac_setup->backoff_period_in_10us);
00077     if (backoff_slots == 0) {
00078         backoff_slots = 1;
00079     }
00080 
00081     timer_mac_start(rf_mac_setup, MAC_TIMER_CCA, backoff_slots);
00082 }
00083 
00084 
00085 uint32_t mac_csma_backoff_get(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00086 {
00087     // Use minimum allowed CSMA-CA for asynch frames
00088     if (rf_mac_setup->active_pd_data_request->asynch_request) {
00089         return MIN_FHSS_CSMA_PERIOD_US;
00090     }
00091     uint8_t backoff = mac_csma_random_backoff_get(rf_mac_setup);
00092     uint32_t backoff_in_us;
00093     //Multiple aUnitBackoffPeriod symbol time
00094     if (rf_mac_setup->rf_csma_extension_supported) {
00095         backoff_in_us = backoff * rf_mac_setup->aUnitBackoffPeriod * rf_mac_setup->symbol_time_us;
00096     } else {
00097         backoff_in_us = backoff * rf_mac_setup->backoff_period_in_10us * 10;
00098     }
00099 
00100     if (backoff_in_us == 0) {
00101         backoff_in_us = 1;
00102     }
00103     if (rf_mac_setup->fhss_api) {
00104         // Synchronization error when backoff time is shorter than allowed.
00105         // TODO: Make this dynamic.
00106         if (backoff_in_us < MIN_FHSS_CSMA_PERIOD_US) {
00107             backoff_in_us += MIN_FHSS_CSMA_PERIOD_US;
00108         }
00109         // Backoff must be long enough to make multiple CCA checks
00110         if (backoff_in_us < (uint32_t)(rf_mac_setup->multi_cca_interval * (rf_mac_setup->number_of_csma_ca_periods - 1))) {
00111             backoff_in_us += ((rf_mac_setup->multi_cca_interval * (rf_mac_setup->number_of_csma_ca_periods - 1)) - backoff_in_us);
00112         }
00113         if (rf_mac_setup->mac_tx_retry) {
00114             backoff_in_us += rf_mac_setup->fhss_api->get_retry_period(rf_mac_setup->fhss_api, rf_mac_setup->active_pd_data_request->DstAddr, rf_mac_setup->dev_driver->phy_driver->phy_MTU);
00115         }
00116     }
00117     return backoff_in_us;
00118 }
00119 
00120 
00121 /*
00122  * \file mac_pd_sap.c
00123  * \brief Add short description about this file!!!
00124  *
00125  */
00126 static bool mac_data_interface_read_last_ack_pending_status(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00127 {
00128     uint8_t pending = 1;
00129     phy_device_driver_s *dev_driver = rf_mac_setup->dev_driver->phy_driver;
00130     if (dev_driver->extension) {
00131         dev_driver->extension(PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS, &pending);
00132     }
00133 
00134 
00135     return pending;
00136 
00137 }
00138 
00139 static void mac_tx_done_state_set(protocol_interface_rf_mac_setup_s *rf_ptr, mac_event_t event)
00140 {
00141     rf_ptr->mac_tx_result = event;
00142 
00143     if (event == MAC_TX_DONE  || event == MAC_TX_DONE_PENDING) {
00144 
00145     } else {
00146         rf_ptr->macTxRequestAck = false;
00147     }
00148     rf_ptr->macRfRadioTxActive = false;
00149     rf_ptr->macTxProcessActive = false;
00150     mcps_sap_pd_confirm(rf_ptr);
00151 }
00152 
00153 static void mac_data_interface_tx_to_cb(protocol_interface_rf_mac_setup_s *rf_ptr)
00154 {
00155     rf_ptr->macRfRadioTxActive = false;
00156     mac_tx_done_state_set(rf_ptr, MAC_TX_TIMEOUT);
00157 }
00158 
00159 int8_t mac_plme_cca_req(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00160 {
00161     dev_driver_tx_buffer_s *tx_buf = &rf_mac_setup->dev_driver_tx_buffer;
00162     phy_device_driver_s *dev_driver = rf_mac_setup->dev_driver->phy_driver;
00163 
00164     rf_mac_setup->macRfRadioTxActive = true;
00165     if (dev_driver->arm_net_virtual_tx_cb) {
00166         if (dev_driver->tx(tx_buf->buf, tx_buf->len, 1, PHY_LAYER_PAYLOAD) == 0) {
00167             timer_mac_start(rf_mac_setup, MAC_TX_TIMEOUT, NWKTX_TIMEOUT_PERIOD);  /*Start Timeout timer for virtual packet loss*/
00168         } else {
00169             rf_mac_setup->macRfRadioTxActive = false;
00170             mac_data_interface_tx_to_cb(rf_mac_setup);
00171         }
00172         return 0;
00173     }
00174 
00175     uint8_t *buffer;
00176     uint16_t length;
00177     if (rf_mac_setup->mac_ack_tx_active) {
00178         buffer = tx_buf->enhanced_ack_buf;
00179         length = tx_buf->ack_len;
00180     } else {
00181         buffer = tx_buf->buf ;
00182         length = tx_buf->len;
00183     }
00184     if (dev_driver->tx(buffer, length, 1, PHY_LAYER_PAYLOAD) == 0) {
00185         return 0;
00186     }
00187 
00188     rf_mac_setup->macRfRadioTxActive = false;
00189     return -1;
00190 }
00191 
00192 /**
00193  * Send a buffer to the MAC.
00194  * Used by the protocol core.
00195  *
00196  * \param buf pointer to buffer
00197  *
00198  */
00199 int8_t mac_pd_sap_req(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00200 {
00201     if (!rf_mac_setup || !rf_mac_setup->macUpState || !rf_mac_setup->active_pd_data_request) {
00202         return -1;
00203     }
00204 
00205     rf_mac_setup->mac_cca_retry = 0;
00206     rf_mac_setup->mac_tx_retry = 0;
00207     rf_mac_setup->macTxProcessActive = true;
00208     mac_csma_param_init(rf_mac_setup);
00209     mac_csma_backoff_start(rf_mac_setup);
00210     return 0;
00211 }
00212 
00213 
00214 /**
00215  * Abort active PHY transmission.
00216  *
00217  * \param rf_mac_setup pointer to MAC.
00218  *
00219  */
00220 void mac_pd_abort_active_tx(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00221 {
00222     phy_csma_params_t csma_params;
00223     // Set TX time to 0 to abort current transmission
00224     csma_params.backoff_time = 0;
00225     rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t *) &csma_params);
00226 }
00227 
00228 /**
00229  * Set PHY TX time.
00230  *
00231  * \param rf_mac_setup pointer to MAC.
00232  * \param tx_time TX timestamp to be set.
00233  *
00234  */
00235 void mac_pd_sap_set_phy_tx_time(protocol_interface_rf_mac_setup_s *rf_mac_setup, uint32_t tx_time, bool cca_enabled)
00236 {
00237     // With TX time set to zero, PHY sends immediately
00238     if (!tx_time) {
00239         tx_time++;
00240     }
00241     phy_csma_params_t csma_params;
00242     csma_params.backoff_time = tx_time;
00243     csma_params.cca_enabled = cca_enabled;
00244     rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_SET_CSMA_PARAMETERS, (uint8_t *) &csma_params);
00245 }
00246 
00247 /**
00248  * Get PHY RX time.
00249  *
00250  * \param rf_mac_setup pointer to MAC
00251  * \return Timestamp of last PHY reception
00252  *
00253  */
00254 static uint32_t mac_pd_sap_get_phy_rx_time(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00255 {
00256     if (!rf_mac_setup->rf_csma_extension_supported) {
00257         return 0;
00258     }
00259     uint8_t rx_time_buffer[4];
00260     rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_READ_RX_TIME, rx_time_buffer);
00261     return common_read_32_bit(rx_time_buffer);
00262 }
00263 
00264 /**
00265  * Run Mac data interface state Machine for mac timer.
00266  *
00267  */
00268 void mac_pd_sap_state_machine(protocol_interface_rf_mac_setup_s *rf_mac_setup)
00269 {
00270 
00271     if (rf_mac_setup->macUpState && rf_mac_setup->macTxProcessActive) {
00272 
00273         if (rf_mac_setup->mac_tx_result == MAC_TIMER_CCA) {
00274 
00275             if (rf_mac_setup->rf_csma_extension_supported) {
00276                 mac_sap_cca_fail_cb(rf_mac_setup);
00277                 return;
00278             }
00279 
00280             if (rf_mac_setup->fhss_api) {
00281                 uint8_t *synch_info = NULL;
00282                 mac_pre_build_frame_t *active_buf = rf_mac_setup->active_pd_data_request;
00283                 if (!active_buf) {
00284                     return;
00285                 }
00286                 bool cca_enabled;
00287                 if (active_buf->fcf_dsn.frametype == MAC_FRAME_ACK) {
00288                     cca_enabled = false;
00289                 } else {
00290                     cca_enabled = true;
00291                 }
00292 
00293                 mac_pd_sap_set_phy_tx_time(rf_mac_setup, active_buf->tx_time, cca_enabled);
00294                 if (active_buf->fcf_dsn.frametype == FC_BEACON_FRAME) {
00295                     // FHSS synchronization info is written in the end of transmitted (Beacon) buffer
00296                     dev_driver_tx_buffer_s *tx_buf = &rf_mac_setup->dev_driver_tx_buffer;
00297                     synch_info = tx_buf->buf + rf_mac_setup->dev_driver->phy_driver->phy_header_length + tx_buf->len - FHSS_SYNCH_INFO_LENGTH;
00298                     rf_mac_setup->fhss_api->write_synch_info(rf_mac_setup->fhss_api, synch_info, 0, FHSS_SYNCH_FRAME, 0);
00299                 }
00300                 // Change to destination channel and write synchronization info to Beacon frames here
00301                 int tx_handle_retval = rf_mac_setup->fhss_api->tx_handle(rf_mac_setup->fhss_api, !mac_is_ack_request_set(active_buf),
00302                                                                          active_buf->DstAddr, mac_convert_frame_type_to_fhss(active_buf->fcf_dsn.frametype),
00303                                                                          active_buf->mac_payload_length, rf_mac_setup->dev_driver->phy_driver->phy_header_length,
00304                                                                          rf_mac_setup->dev_driver->phy_driver->phy_tail_length, active_buf->tx_time);
00305                 // When FHSS TX handle returns -1, transmission of the packet is currently not allowed -> restart CCA timer
00306                 if (tx_handle_retval == -1) {
00307                     timer_mac_start(rf_mac_setup, MAC_TIMER_CCA, randLIB_get_random_in_range(20, 400) + 1);
00308                     return;
00309                 }
00310                 // When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back
00311                 // to queue by using CCA fail event
00312                 if (tx_handle_retval == -3) {
00313                     mac_tx_done_state_set(rf_mac_setup, MAC_CCA_FAIL);
00314                     return;
00315                 } else if (tx_handle_retval == -2) {
00316                     mac_tx_done_state_set(rf_mac_setup, MAC_UNKNOWN_DESTINATION);
00317                     return;
00318                 }
00319             }
00320             if (mac_plme_cca_req(rf_mac_setup) != 0) {
00321                 mac_csma_backoff_start(rf_mac_setup);
00322             }
00323         } else if (rf_mac_setup->mac_tx_result == MAC_TX_TIMEOUT) {
00324             mac_data_interface_tx_to_cb(rf_mac_setup);
00325         } else if (rf_mac_setup->mac_tx_result == MAC_TIMER_ACK) {
00326             mac_data_interface_tx_done_cb(rf_mac_setup, PHY_LINK_TX_FAIL, 0, 0);
00327         }
00328     }
00329 }
00330 
00331 static void  mac_sap_cca_fail_cb(protocol_interface_rf_mac_setup_s *rf_ptr)
00332 {
00333     if (rf_ptr->mac_ack_tx_active) {
00334         if (rf_ptr->active_pd_data_request) {
00335             mac_csma_backoff_start(rf_ptr);
00336         }
00337     } else {
00338 
00339         rf_ptr->macRfRadioTxActive = false;
00340         if (rf_ptr->mac_cca_retry > rf_ptr->macMaxCSMABackoffs || (rf_ptr->active_pd_data_request && rf_ptr->active_pd_data_request->asynch_request)) {
00341             //Send MAC_CCA_FAIL
00342             mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL);
00343         } else {
00344             timer_mac_stop(rf_ptr);
00345             mac_csma_BE_update(rf_ptr);
00346             if (mcps_pd_data_rebuild(rf_ptr, rf_ptr->active_pd_data_request)) {
00347                 mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL);
00348             }
00349         }
00350     }
00351 }
00352 
00353 //static uint16_t mac_get_retry_period(protocol_interface_rf_mac_setup_s *rf_ptr)
00354 //{
00355 //    if (rf_ptr->fhss_api && rf_ptr->fhss_api->get_retry_period) {
00356 //        return rf_ptr->fhss_api->get_retry_period(rf_ptr->fhss_api, rf_ptr->active_pd_data_request->DstAddr, rf_ptr->dev_driver->phy_driver->phy_MTU);
00357 //    }
00358 //    uint8_t backoff_length = mac_csma_random_backoff_get(rf_ptr);
00359 //    uint16_t backoff_slots = mac_csma_backoff_period_convert_to50us(backoff_length, rf_ptr->backoff_period_in_10us);
00360 //    if (backoff_slots == 0) {
00361 //        backoff_slots = 1;
00362 //    }
00363 //    return backoff_slots;
00364 //}
00365 
00366 static void mac_sap_no_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr)
00367 {
00368     rf_ptr->macRfRadioTxActive = false;
00369     if (rf_ptr->mac_tx_retry < rf_ptr->mac_mlme_retry_max) {
00370         rf_ptr->mac_cca_retry = 0;
00371         rf_ptr->mac_tx_retry++; //Update retry counter
00372         mac_csma_param_init(rf_ptr);
00373         // Increase current backoff exponent when retry count grows
00374         for (int retry_index = rf_ptr->mac_tx_retry; retry_index > 0; retry_index--) {
00375             mac_csma_BE_update(rf_ptr);
00376         }
00377         rf_ptr->mac_tx_status.retry++;
00378         /*Send retry using random interval*/
00379         if (mcps_pd_data_rebuild(rf_ptr, rf_ptr->active_pd_data_request)) {
00380             mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL);
00381         }
00382 
00383     } else {
00384         //Send TX Fail event
00385         // rf_mac_setup->ip_tx_active->bad_channel = rf_mac_setup->mac_channel;
00386         mac_tx_done_state_set(rf_ptr, MAC_TX_FAIL);
00387     }
00388 }
00389 
00390 
00391 static bool mac_data_asynch_channel_switch(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_build_frame_t *active_buf)
00392 {
00393     if (!active_buf || !active_buf->asynch_request) {
00394         return false;
00395     }
00396     active_buf->asynch_channel = rf_ptr->mac_channel; //Store Original channel
00397     uint16_t channel = mlme_scan_analyze_next_channel(&active_buf->asynch_channel_list, true);
00398     if (channel <= 0xff) {
00399         mac_mlme_rf_channel_change(rf_ptr, channel);
00400 
00401     }
00402     return true;
00403 }
00404 
00405 
00406 static void mac_data_ack_tx_finish(protocol_interface_rf_mac_setup_s *rf_ptr)
00407 {
00408     rf_ptr->mac_ack_tx_active = false;
00409     if (rf_ptr->fhss_api) {
00410         //SET tx completed false because ack isnot never queued
00411         rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, false, 0xff);
00412     }
00413     if (rf_ptr->active_pd_data_request) {
00414 
00415         mcps_pending_packet_counter_update_check(rf_ptr, rf_ptr->active_pd_data_request);
00416         //GEN TX failure
00417         mac_sap_cca_fail_cb(rf_ptr);
00418     }
00419 }
00420 
00421 static int8_t mac_data_interface_tx_done_cb(protocol_interface_rf_mac_setup_s *rf_ptr, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry)
00422 {
00423 
00424     if (!rf_ptr->macRfRadioTxActive) {
00425         return -1;
00426     }
00427 
00428     if (status == PHY_LINK_CCA_PREPARE) {
00429 
00430         if (rf_ptr->mac_ack_tx_active) {
00431             //Accept direct non crypted acks and crypted only if neighbor is at list
00432             if (rf_ptr->ack_tx_possible || mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode, rf_ptr->enhanced_ack_buffer.DstPANId)) {
00433                 return PHY_TX_ALLOWED;
00434             }
00435 
00436             //Compare time to started time
00437             if (mac_mcps_sap_get_phy_timestamp(rf_ptr) - rf_ptr->enhanced_ack_handler_timestamp > ENHANCED_ACK_NEIGHBOUR_POLL_MAX_TIME_US || mcps_generic_ack_build(rf_ptr, false) != 0) {
00438                 mac_data_ack_tx_finish(rf_ptr);
00439             }
00440 
00441             return PHY_TX_NOT_ALLOWED;
00442         }
00443 
00444         if (mac_data_asynch_channel_switch(rf_ptr, rf_ptr->active_pd_data_request)) {
00445             return PHY_TX_ALLOWED;
00446         }
00447 
00448         if (rf_ptr->fhss_api) {
00449             mac_pre_build_frame_t *active_buf = rf_ptr->active_pd_data_request;
00450             if (!active_buf) {
00451                 return PHY_TX_NOT_ALLOWED;
00452             }
00453 
00454             // Change to destination channel and write synchronization info to Beacon frames here
00455             int tx_handle_retval = rf_ptr->fhss_api->tx_handle(rf_ptr->fhss_api, !mac_is_ack_request_set(active_buf),
00456                                                                active_buf->DstAddr, mac_convert_frame_type_to_fhss(active_buf->fcf_dsn.frametype),
00457                                                                active_buf->mac_payload_length, rf_ptr->dev_driver->phy_driver->phy_header_length,
00458                                                                rf_ptr->dev_driver->phy_driver->phy_tail_length, active_buf->tx_time);
00459             // When FHSS TX handle returns -1, transmission of the packet is currently not allowed -> restart CCA timer
00460             if (tx_handle_retval == -1) {
00461                 mac_sap_cca_fail_cb(rf_ptr);
00462                 return PHY_TX_NOT_ALLOWED;
00463             }
00464             // When FHSS TX handle returns -3, we are trying to transmit broadcast packet on unicast channel -> push back
00465             // to queue by using CCA fail event
00466             if (tx_handle_retval == -3) {
00467                 mac_tx_done_state_set(rf_ptr, MAC_CCA_FAIL);
00468                 return PHY_TX_NOT_ALLOWED;
00469             } else if (tx_handle_retval == -2) {
00470                 mac_tx_done_state_set(rf_ptr, MAC_UNKNOWN_DESTINATION);
00471                 return PHY_TX_NOT_ALLOWED;
00472             }
00473             if (active_buf->csma_periods_left > 0) {
00474                 active_buf->csma_periods_left--;
00475                 active_buf->tx_time += rf_ptr->multi_cca_interval;
00476                 mac_pd_sap_set_phy_tx_time(rf_ptr, active_buf->tx_time, true);
00477                 return PHY_RESTART_CSMA;
00478             }
00479         }
00480 
00481         return 0;
00482     }
00483 
00484     //
00485     bool waiting_ack = false;
00486 
00487 
00488     if (rf_ptr->mac_ack_tx_active) {
00489         mac_data_ack_tx_finish(rf_ptr);
00490         return 0;
00491     } else {
00492         // Do not update CCA count when Ack is received, it was already updated with PHY_LINK_TX_SUCCESS event
00493         // Do not update CCA count when CCA_OK is received, PHY_LINK_TX_SUCCESS will update it
00494         if ((status != PHY_LINK_TX_DONE) && (status != PHY_LINK_TX_DONE_PENDING) && (status != PHY_LINK_CCA_OK)) {
00495             /* For PHY_LINK_TX_SUCCESS and PHY_LINK_CCA_FAIL cca_retry must always be > 0.
00496              * PHY_LINK_TX_FAIL either happened during transmission or when waiting Ack -> we must use the CCA count given by PHY.
00497              */
00498             if ((cca_retry == 0) && (status != PHY_LINK_TX_FAIL)) {
00499                 cca_retry = 1;
00500             }
00501             rf_ptr->mac_tx_status.cca_cnt += cca_retry;
00502             rf_ptr->mac_cca_retry += cca_retry;
00503         }
00504         rf_ptr->mac_tx_status.retry += tx_retry;
00505         rf_ptr->mac_tx_retry += tx_retry;
00506         timer_mac_stop(rf_ptr);
00507     }
00508 
00509     switch (status) {
00510         case PHY_LINK_TX_SUCCESS:
00511             if (rf_ptr->macTxRequestAck) {
00512                 timer_mac_start(rf_ptr, MAC_TIMER_ACK, rf_ptr->mac_ack_wait_duration); /*wait for ACK 1 ms*/
00513                 waiting_ack = true;
00514             } else {
00515                 //TODO CHECK this is MAC_TX_ PERMIT OK
00516                 mac_tx_done_state_set(rf_ptr, MAC_TX_DONE);
00517             }
00518             break;
00519 
00520         case PHY_LINK_CCA_FAIL:
00521             mac_sap_cca_fail_cb(rf_ptr);
00522             break;
00523 
00524         case PHY_LINK_CCA_OK:
00525             break;
00526 
00527         case PHY_LINK_TX_FAIL:
00528             mac_sap_no_ack_cb(rf_ptr);
00529             break;
00530 
00531         case PHY_LINK_TX_DONE:
00532             //mac_tx_result
00533             mac_tx_done_state_set(rf_ptr, MAC_TX_DONE);
00534             break;
00535 
00536         case PHY_LINK_TX_DONE_PENDING:
00537             mac_tx_done_state_set(rf_ptr, MAC_TX_DONE_PENDING);
00538             break;
00539 
00540         default:
00541             break;
00542     }
00543     if (rf_ptr->fhss_api) {
00544         bool tx_is_done = false;
00545         if (rf_ptr->mac_tx_result == MAC_TX_DONE) {
00546             tx_is_done = true;
00547         }
00548         if (rf_ptr->active_pd_data_request->asynch_request == false) {
00549             rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, waiting_ack, tx_is_done, rf_ptr->active_pd_data_request->msduHandle);
00550         }
00551     }
00552     return 0;
00553 }
00554 
00555 
00556 static int8_t mac_data_interface_tx_done_by_ack_cb(protocol_interface_rf_mac_setup_s *rf_ptr, mac_pre_parsed_frame_t *buf)
00557 {
00558 
00559     if (!rf_ptr->macRfRadioTxActive || !rf_ptr->active_pd_data_request || rf_ptr->active_pd_data_request->fcf_dsn.DSN != buf->fcf_dsn.DSN) {
00560         return -1;
00561     }
00562 
00563     timer_mac_stop(rf_ptr);
00564     if (buf->fcf_dsn.framePending) {
00565         rf_ptr->mac_tx_result = MAC_TX_DONE_PENDING;
00566     } else {
00567         rf_ptr->mac_tx_result = MAC_TX_DONE;
00568     }
00569     rf_ptr->macRfRadioTxActive = false;
00570     rf_ptr->macTxProcessActive = false;
00571     mcps_sap_pd_ack(buf);
00572 
00573     if (rf_ptr->fhss_api) {
00574         rf_ptr->fhss_api->data_tx_done(rf_ptr->fhss_api, false, true, rf_ptr->active_pd_data_request->msduHandle);
00575     }
00576     return 0;
00577 }
00578 
00579 static bool mac_pd_sap_ack_validation(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_dsn, const uint8_t *data_ptr)
00580 {
00581     if (!rf_ptr->active_pd_data_request || !rf_ptr->active_pd_data_request->fcf_dsn.ackRequested) {
00582         return false; //No active Data request anymore or no ACK request for current TX
00583     }
00584 
00585     if (fcf_dsn->frameVersion != rf_ptr->active_pd_data_request->fcf_dsn.frameVersion) {
00586         return false;
00587     }
00588 
00589     if (fcf_dsn->frameVersion == MAC_FRAME_VERSION_2015) {
00590 
00591         //Validate ACK SRC address mode and address to Active TX dst address
00592         if (rf_ptr->active_pd_data_request->fcf_dsn.DstAddrMode != fcf_dsn->SrcAddrMode) {
00593             return false;
00594         }
00595 
00596         if (fcf_dsn->SrcAddrMode) {
00597             uint8_t srcAddress[8];
00598             uint8_t address_length = mac_address_length(fcf_dsn->SrcAddrMode);
00599             mac_header_get_src_address(fcf_dsn, data_ptr, srcAddress);
00600             if (memcmp(srcAddress, rf_ptr->active_pd_data_request->DstAddr, address_length)) {
00601                 return false;
00602             }
00603         }
00604 
00605         //Validate ACK DST address mode and address to Active TX src address
00606         if (rf_ptr->active_pd_data_request->fcf_dsn.SrcAddrMode != fcf_dsn->DstAddrMode) {
00607             return false;
00608         }
00609 
00610         if (fcf_dsn->DstAddrMode) {
00611             uint8_t dstAddress[8];
00612             uint8_t address_length = mac_address_length(fcf_dsn->DstAddrMode);
00613             mac_header_get_dst_address(fcf_dsn, data_ptr, dstAddress);
00614             if (memcmp(dstAddress, rf_ptr->active_pd_data_request->SrcAddr, address_length)) {
00615                 return false;
00616             }
00617         }
00618 
00619         if (rf_ptr->active_pd_data_request->fcf_dsn.sequenceNumberSuppress != fcf_dsn->sequenceNumberSuppress) {
00620             return false; //sequence number validation not correct
00621         }
00622 
00623         if (!fcf_dsn->sequenceNumberSuppress && (rf_ptr->active_pd_data_request->fcf_dsn.DSN != fcf_dsn->DSN)) {
00624             return false;
00625         }
00626         return true;
00627     }
00628 
00629     if (rf_ptr->active_pd_data_request->fcf_dsn.DSN != fcf_dsn->DSN) {
00630         return false;
00631     }
00632     return true;
00633 }
00634 
00635 static int8_t mac_pd_sap_validate_fcf(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind)
00636 {
00637     switch (fcf_read->frametype) {
00638         case FC_DATA_FRAME:
00639             if (fcf_read->SrcAddrMode == MAC_ADDR_MODE_NONE) {
00640                 return -1;
00641             } else if (fcf_read->DstAddrMode == MAC_ADDR_MODE_NONE && fcf_read->frameVersion != MAC_FRAME_VERSION_2015) {
00642                 return -1;
00643             }
00644             break;
00645         case FC_BEACON_FRAME:
00646             if (fcf_read->SrcAddrMode == MAC_ADDR_MODE_NONE || fcf_read->DstAddrMode != MAC_ADDR_MODE_NONE) {
00647                 return -1;
00648             }
00649             break;
00650         case FC_ACK_FRAME:
00651             // Only accept version 2015 Acks
00652             if (fcf_read->frameVersion != MAC_FRAME_VERSION_2015) {
00653                 return -1;
00654             }
00655             //Validate Ack doesn't request Ack
00656             if (fcf_read->ackRequested) {
00657                 return -1;
00658             }
00659             //Validate ACK
00660             if (!mac_pd_sap_ack_validation(rf_ptr, fcf_read, pd_data_ind->data_ptr)) {
00661                 return -1;
00662             }
00663             break;
00664         case FC_CMD_FRAME:
00665             break;
00666         default:
00667             return -1;
00668     }
00669     return 0;
00670 }
00671 
00672 static bool mac_pd_sap_panid_filter_common(const uint8_t *mac_header, const mac_fcf_sequence_t *fcf_read, uint16_t own_pan_id)
00673 {
00674     // Beacon frames shouldn't be dropped as they might be used by load balancing
00675     if (fcf_read->frametype == MAC_FRAME_BEACON) {
00676         return true;
00677     }
00678     if (own_pan_id == 0xffff) {
00679         return true;
00680     }
00681     uint16_t dst_pan_id = mac_header_get_dst_panid(fcf_read, mac_header, 0xffff);
00682     if (dst_pan_id == 0xffff) {
00683         return true;
00684     }
00685     if (own_pan_id == dst_pan_id) {
00686         return true;
00687     }
00688     return false;
00689 }
00690 
00691 static bool mac_pd_sap_panid_v2_filter(const uint8_t *ptr, const mac_fcf_sequence_t *fcf_read, uint16_t pan_id)
00692 {
00693     if ((fcf_read->DstAddrMode == MAC_ADDR_MODE_NONE) && (fcf_read->frametype == FC_DATA_FRAME || fcf_read->frametype == FC_CMD_FRAME)) {
00694         return true;
00695     }
00696     if ((fcf_read->DstAddrMode == MAC_ADDR_MODE_64_BIT) && (fcf_read->SrcAddrMode == MAC_ADDR_MODE_64_BIT) && fcf_read->intraPan) {
00697         return true;
00698     }
00699     return mac_pd_sap_panid_filter_common(ptr, fcf_read, pan_id);
00700 }
00701 
00702 static bool mac_pd_sap_addr_filter_common(const uint8_t *mac_header, const mac_fcf_sequence_t *fcf_read, uint8_t *mac_64bit_addr, uint16_t mac_16bit_addr)
00703 {
00704     uint8_t cmp_table[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
00705     uint8_t dst_addr[8];
00706     mac_header_get_dst_address(fcf_read, mac_header, dst_addr);
00707 
00708     switch (fcf_read->DstAddrMode) {
00709         case MAC_ADDR_MODE_16_BIT:
00710             if (!memcmp(dst_addr, cmp_table, 2)) {
00711                 return true;
00712             }
00713             uint8_t temp[2];
00714             common_write_16_bit(mac_16bit_addr, temp);
00715             if (!memcmp(temp, dst_addr, 2)) {
00716                 return true;
00717             }
00718             break;
00719         case MAC_ADDR_MODE_64_BIT:
00720             if (!memcmp(dst_addr, cmp_table, 8)) {
00721                 return true;
00722             }
00723             if (!memcmp(mac_64bit_addr, dst_addr, 8)) {
00724                 return true;
00725             }
00726             break;
00727         case MAC_ADDR_MODE_NONE:
00728             return true;
00729             break;
00730         default:
00731             break;
00732     }
00733     return false;
00734 }
00735 
00736 static bool mac_pd_sap_addr_v2_filter(const uint8_t *mac_header, const mac_fcf_sequence_t *fcf_read, uint8_t *mac_64bit_addr, uint16_t mac_16bit_addr)
00737 {
00738     return mac_pd_sap_addr_filter_common(mac_header, fcf_read, mac_64bit_addr, mac_16bit_addr);
00739 }
00740 
00741 static bool mac_pd_sap_rx_filter(const uint8_t *mac_header, const mac_fcf_sequence_t *fcf_read, uint8_t phy_filter_mask, uint8_t *mac_64bit_addr, uint16_t mac_16bit_addr, uint16_t pan_id)
00742 {
00743     uint8_t version = fcf_read->frameVersion;
00744 
00745     if (version == MAC_FRAME_VERSION_2015 && !(phy_filter_mask & (1 << MAC_FRAME_VERSION_2))) {
00746         if (!mac_pd_sap_panid_v2_filter(mac_header, fcf_read, pan_id)) {
00747             return false;
00748         }
00749         if (!mac_pd_sap_addr_v2_filter(mac_header, fcf_read, mac_64bit_addr, mac_16bit_addr)) {
00750             return false;
00751         }
00752     }
00753     return true;
00754 }
00755 
00756 static int8_t mac_pd_sap_generate_ack(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind)
00757 {
00758     //Generate ACK when Extension is enabled and ACK is requested only for version 2 frames.
00759     if (!rf_ptr->mac_extension_enabled || !fcf_read->ackRequested || (fcf_read->frameVersion != MAC_FRAME_VERSION_2015)) {
00760         return 0;
00761     }
00762     if (rf_ptr->mac_ack_tx_active) {
00763         return -1;
00764     }
00765 
00766     mcps_ack_data_payload_t ack_payload;
00767     mac_api_t *mac_api = get_sw_mac_api(rf_ptr);
00768     mac_api->enhanced_ack_data_req_cb(mac_api, &ack_payload, pd_data_ind->dbm, pd_data_ind->link_quality);
00769     //Calculate Delta time
00770 
00771     if (mcps_generic_ack_data_request_init(rf_ptr, fcf_read, pd_data_ind->data_ptr, &ack_payload) != 0) {
00772         return -1;
00773     }
00774 
00775     if (rf_ptr->enhanced_ack_buffer.aux_header.securityLevel == 0 || mac_sec_mib_device_description_get(rf_ptr, rf_ptr->enhanced_ack_buffer.DstAddr, rf_ptr->enhanced_ack_buffer.fcf_dsn.DstAddrMode, rf_ptr->enhanced_ack_buffer.DstPANId)) {
00776         rf_ptr->ack_tx_possible = true;
00777     } else {
00778         rf_ptr->ack_tx_possible = false;
00779     }
00780 
00781     return mcps_generic_ack_build(rf_ptr, true);
00782 }
00783 
00784 static mac_pre_parsed_frame_t *mac_pd_sap_allocate_receive_buffer(protocol_interface_rf_mac_setup_s *rf_ptr, const mac_fcf_sequence_t *fcf_read, arm_pd_sap_generic_ind_t *pd_data_ind)
00785 {
00786     mac_pre_parsed_frame_t *buffer = mcps_sap_pre_parsed_frame_buffer_get(pd_data_ind->data_ptr, pd_data_ind->data_len);
00787     if (!buffer) {
00788         return NULL;
00789     }
00790 
00791     //Copy Pre Parsed values
00792     buffer->fcf_dsn = *fcf_read;
00793     buffer->timestamp = mac_pd_sap_get_phy_rx_time(rf_ptr);
00794     buffer->ack_pendinfg_status = mac_data_interface_read_last_ack_pending_status(rf_ptr);
00795     /* Set default flags */
00796     buffer->dbm = pd_data_ind->dbm;
00797     buffer->LQI = pd_data_ind->link_quality;
00798     buffer->mac_class_ptr = rf_ptr;
00799     return buffer;
00800 }
00801 
00802 static int8_t mac_pd_sap_parse_length_fields(mac_pre_parsed_frame_t *buffer, arm_pd_sap_generic_ind_t *pd_data_ind, const uint8_t *parse_ptr)
00803 {
00804     if (buffer->fcf_dsn.frametype > FC_CMD_FRAME) {
00805         return -1;
00806     }
00807     buffer->mac_header_length = parse_ptr - pd_data_ind->data_ptr;
00808     int16_t length = pd_data_ind->data_len;
00809     buffer->mac_header_length += mac_header_address_length(&buffer->fcf_dsn);
00810     length -= buffer->mac_header_length;
00811     if (length < 0) {
00812         return -1;
00813     }
00814 
00815     buffer->mac_payload_length = (buffer->frameLength - buffer->mac_header_length);
00816 
00817     if (buffer->fcf_dsn.securityEnabled) {
00818         //Read KEYID Mode
00819         uint8_t key_id_mode, security_level, mic_len;
00820         uint8_t *security_ptr = &buffer->buf[buffer->mac_header_length];
00821         uint8_t auxBaseHeader = *security_ptr;
00822         key_id_mode = (auxBaseHeader >> 3) & 3;
00823         security_level = auxBaseHeader & 7;
00824 
00825         switch (key_id_mode) {
00826             case MAC_KEY_ID_MODE_IMPLICIT:
00827                 if (security_level) {
00828                     buffer->security_aux_header_length = 5;
00829                 } else {
00830                     buffer->security_aux_header_length = 1;
00831                 }
00832                 break;
00833             case MAC_KEY_ID_MODE_IDX:
00834                 buffer->security_aux_header_length = 6;
00835                 break;
00836             case MAC_KEY_ID_MODE_SRC4_IDX:
00837                 buffer->security_aux_header_length = 10;
00838                 break;
00839             default:
00840                 buffer->security_aux_header_length = 14;
00841                 break;
00842         }
00843 
00844         length -= buffer->security_aux_header_length;
00845         mic_len = mac_security_mic_length_get(security_level);
00846 
00847         length -= mic_len;
00848 
00849         //Verify that data length is not negative
00850         if (length < 0) {
00851             return -1;
00852         }
00853 
00854         buffer->mac_payload_length -= (buffer->security_aux_header_length + mic_len);
00855     }
00856     //Do not accept command frame with length 0
00857     if (buffer->fcf_dsn.frametype == FC_CMD_FRAME && length == 0) {
00858         return -1;
00859     }
00860     return 0;
00861 }
00862 
00863 int8_t mac_pd_sap_data_cb(void *identifier, arm_phy_sap_msg_t *message)
00864 {
00865     protocol_interface_rf_mac_setup_s *rf_ptr = (protocol_interface_rf_mac_setup_s *)identifier;
00866 
00867     if (!rf_ptr || !message) {
00868         return -1;
00869     }
00870 
00871     if (!rf_ptr->macUpState) {
00872         return -2;
00873     }
00874 
00875     if (message->id == MAC15_4_PD_SAP_DATA_IND) {
00876         arm_pd_sap_generic_ind_t *pd_data_ind = &(message->message.generic_data_ind);
00877         if (pd_data_ind->data_len < 3) {
00878             return -1;
00879         }
00880 
00881         mac_fcf_sequence_t fcf_read;
00882         const uint8_t *ptr = mac_header_parse_fcf_dsn(&fcf_read, pd_data_ind->data_ptr);
00883 
00884         mac_pre_parsed_frame_t *buffer = mac_pd_sap_allocate_receive_buffer(rf_ptr, &fcf_read, pd_data_ind);
00885         if (buffer && mac_filter_modify_link_quality(rf_ptr->mac_interface_id, buffer) == 1) {
00886             goto ERROR_HANDLER;
00887         }
00888         if (!rf_ptr->macProminousMode) {
00889             if (mac_pd_sap_validate_fcf(rf_ptr, &fcf_read, pd_data_ind)) {
00890                 goto ERROR_HANDLER;
00891             }
00892             if (!mac_pd_sap_rx_filter(pd_data_ind->data_ptr, &fcf_read, rf_ptr->mac_frame_filters, rf_ptr->mac64, rf_ptr->mac_short_address, rf_ptr->pan_id)) {
00893                 goto ERROR_HANDLER;
00894             }
00895             if (mac_pd_sap_generate_ack(rf_ptr, &fcf_read, pd_data_ind)) {
00896                 goto ERROR_HANDLER;
00897             }
00898             if (buffer) {
00899                 if (mac_pd_sap_parse_length_fields(buffer, pd_data_ind, ptr)) {
00900                     goto ERROR_HANDLER;
00901                 }
00902                 if (!mac_header_information_elements_parse(buffer)) {
00903                     goto ERROR_HANDLER;
00904                 }
00905                 if (buffer->fcf_dsn.frametype == FC_ACK_FRAME) {
00906                     if (mac_data_interface_tx_done_by_ack_cb(rf_ptr, buffer)) {
00907                         mcps_sap_pre_parsed_frame_buffer_free(buffer);
00908                     }
00909                     return 0;
00910                 }
00911             }
00912         }
00913         if (!buffer) {
00914             sw_mac_stats_update(rf_ptr, STAT_MAC_RX_DROP, 0);
00915             return -3;
00916         }
00917         if (mcps_sap_pd_ind(buffer) == 0) {
00918             return 0;
00919         }
00920 ERROR_HANDLER:
00921         mcps_sap_pre_parsed_frame_buffer_free(buffer);
00922         sw_mac_stats_update(rf_ptr, STAT_MAC_RX_DROP, 0);
00923         return -1;
00924 
00925     } else if (message->id == MAC15_4_PD_SAP_DATA_TX_CONFIRM) {
00926         arm_pd_sap_15_4_confirm_with_params_t *pd_data_cnf = &(message->message.mac15_4_pd_sap_confirm);
00927         return mac_data_interface_tx_done_cb(rf_ptr, pd_data_cnf->status, pd_data_cnf->cca_retry, pd_data_cnf->tx_retry);
00928     }
00929 
00930     return -1;
00931 }
00932 
00933 void mac_pd_sap_rf_low_level_function_set(void *mac_ptr, void *driver)
00934 {
00935     arm_device_driver_list_s *driver_ptr = (arm_device_driver_list_s *)driver;
00936     driver_ptr->phy_sap_identifier = (protocol_interface_rf_mac_setup_s *)mac_ptr;
00937     driver_ptr->phy_sap_upper_cb = mac_pd_sap_data_cb;
00938 }
00939