mirror of https://github.com/ARMmbed/mbed-os.git
244 lines
7.7 KiB
C
244 lines
7.7 KiB
C
/*
|
|
* Copyright (c) 2014-2018, Arm Limited and affiliates.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/*
|
|
* \file mac_indirect_data.c
|
|
* \brief Add short description about this file!!!
|
|
*
|
|
*/
|
|
#include "nsconfig.h"
|
|
#include "string.h"
|
|
#include "ns_types.h"
|
|
#include "ns_trace.h"
|
|
#include "eventOS_event.h"
|
|
#include "eventOS_scheduler.h"
|
|
#include "eventOS_callback_timer.h"
|
|
#include "nsdynmemLIB.h"
|
|
#include "common_functions.h"
|
|
#include "sw_mac.h"
|
|
#include "mac_api.h"
|
|
#include "MAC/IEEE802_15_4/sw_mac_internal.h"
|
|
#include "MAC/IEEE802_15_4/mac_defines.h"
|
|
#include "MAC/IEEE802_15_4/mac_indirect_data.h"
|
|
#include "MAC/IEEE802_15_4/mac_header_helper_functions.h"
|
|
#include "MAC/IEEE802_15_4/mac_mcps_sap.h"
|
|
#include "MAC/rf_driver_storage.h"
|
|
|
|
#define TRACE_GROUP_MAC_INDIR "mInD"
|
|
#define TRACE_GROUP "mInD"
|
|
|
|
void mac_indirect_data_ttl_handle(protocol_interface_rf_mac_setup_s *cur, uint16_t tick_value)
|
|
{
|
|
if (!cur || !cur->dev_driver) {
|
|
return;
|
|
}
|
|
mcps_data_conf_t confirm;
|
|
memset(&confirm, 0, sizeof(mcps_data_conf_t));
|
|
|
|
phy_device_driver_s *dev_driver = cur->dev_driver->phy_driver;
|
|
if (!cur->indirect_pd_data_request_queue) {
|
|
uint8_t value = 0;
|
|
if (dev_driver && dev_driver->extension) {
|
|
dev_driver->extension(PHY_EXTENSION_CTRL_PENDING_BIT, &value);
|
|
}
|
|
cur->mac_frame_pending = false;
|
|
return;
|
|
}
|
|
mac_pre_build_frame_t *buf, *buf_prev = 0, *buf_temp = 0;
|
|
|
|
mac_api_t *api = get_sw_mac_api(cur);
|
|
if (!api) {
|
|
return;
|
|
}
|
|
|
|
buf = cur->indirect_pd_data_request_queue;
|
|
|
|
tick_value /= 20; //Covert time ms
|
|
if (tick_value == 0) {
|
|
tick_value = 1;
|
|
}
|
|
|
|
while (buf) {
|
|
if (buf->buffer_ttl > tick_value) {
|
|
buf->buffer_ttl -= tick_value;
|
|
buf_prev = buf;
|
|
buf = buf->next;
|
|
} else {
|
|
buf->buffer_ttl = 0;
|
|
if (buf_prev) {
|
|
buf_prev->next = buf->next;
|
|
} else {
|
|
cur->indirect_pd_data_request_queue = buf->next;
|
|
}
|
|
|
|
confirm.msduHandle = buf->msduHandle;
|
|
buf_temp = buf;
|
|
buf = buf->next;
|
|
buf_temp->next = NULL;
|
|
cur->indirect_pending_bytes -= buf_temp->mac_payload_length;
|
|
|
|
confirm.status = MLME_TRANSACTION_EXPIRED;
|
|
|
|
mcps_sap_prebuild_frame_buffer_free(buf_temp);
|
|
|
|
if (cur->mac_extension_enabled) {
|
|
mcps_data_conf_payload_t data_conf;
|
|
memset(&data_conf, 0, sizeof(mcps_data_conf_payload_t));
|
|
//Check Payload Here
|
|
api->data_conf_ext_cb(api, &confirm, &data_conf);
|
|
} else {
|
|
api->data_conf_cb(api, &confirm);
|
|
}
|
|
}
|
|
}
|
|
|
|
eventOS_callback_timer_stop(cur->mac_mcps_timer);
|
|
eventOS_callback_timer_start(cur->mac_mcps_timer, MAC_INDIRECT_TICK_IN_MS * 20);
|
|
}
|
|
|
|
uint8_t mac_indirect_data_req_handle(mac_pre_parsed_frame_t *buf, protocol_interface_rf_mac_setup_s *mac_ptr)
|
|
{
|
|
|
|
if (!mac_ptr || !buf) {
|
|
return 1;
|
|
}
|
|
|
|
if (buf->fcf_dsn.DstAddrMode == MAC_ADDR_MODE_NONE || buf->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_NONE) {
|
|
return 1;
|
|
}
|
|
|
|
uint8_t srcAddress[8];
|
|
memset(&srcAddress, 0, 8);
|
|
|
|
mac_header_get_src_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), srcAddress);
|
|
|
|
//Call COMM status
|
|
mac_api_t *mac_api = get_sw_mac_api(mac_ptr);
|
|
if (mac_api) {
|
|
mlme_comm_status_t comm_status;
|
|
memset(&comm_status, 0, sizeof(mlme_comm_status_t));
|
|
|
|
comm_status.status = MLME_DATA_POLL_NOTIFICATION;
|
|
//Call com status
|
|
comm_status.PANId = mac_header_get_dst_panid(&buf->fcf_dsn, mac_header_message_start_pointer(buf), mac_ptr->pan_id);
|
|
comm_status.DstAddrMode = buf->fcf_dsn.DstAddrMode;;
|
|
mac_header_get_dst_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), comm_status.DstAddr);
|
|
comm_status.SrcAddrMode = buf->fcf_dsn.SrcAddrMode;
|
|
mac_header_get_src_address(&buf->fcf_dsn, mac_header_message_start_pointer(buf), comm_status.SrcAddr);
|
|
mac_header_security_components_read(buf, &comm_status.Key);
|
|
if (mac_api->mlme_ind_cb) {
|
|
mac_api->mlme_ind_cb(mac_api, MLME_COMM_STATUS, &comm_status);
|
|
}
|
|
}
|
|
|
|
|
|
/* If the Ack we sent for the Data Request didn't have frame pending set, we shouldn't transmit - child may have slept */
|
|
if (!buf->ack_pendinfg_status) {
|
|
//tr_debug("Drop by pending");
|
|
if (mac_ptr->indirect_pd_data_request_queue) {
|
|
tr_error("Wrongly dropped");
|
|
}
|
|
//Free Buffer
|
|
return 1;
|
|
}
|
|
|
|
uint8_t address_cmp_ok = 0;
|
|
uint8_t len;
|
|
mac_pre_build_frame_t *b_prev = NULL;
|
|
|
|
if (buf->fcf_dsn.SrcAddrMode == MAC_ADDR_MODE_16_BIT) {
|
|
len = 2;
|
|
} else {
|
|
len = 8;
|
|
}
|
|
|
|
mac_pre_build_frame_t *b = mac_ptr->indirect_pd_data_request_queue;
|
|
while (b) {
|
|
|
|
if (buf->neigh_info) {
|
|
uint16_t compare_short;
|
|
if (b->fcf_dsn.DstAddrMode == MAC_ADDR_MODE_16_BIT) {
|
|
|
|
compare_short = common_read_16_bit(b->DstAddr);
|
|
if (compare_short == buf->neigh_info->ShortAddress) {
|
|
address_cmp_ok = 1;
|
|
}
|
|
} else {
|
|
if (memcmp(b->DstAddr, buf->neigh_info->ExtAddress, 8) == 0) {
|
|
address_cmp_ok = 1;
|
|
}
|
|
}
|
|
} else {
|
|
if (b->fcf_dsn.DstAddrMode == buf->fcf_dsn.SrcAddrMode) {
|
|
if (memcmp(b->DstAddr, srcAddress, len) == 0) {
|
|
address_cmp_ok = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (address_cmp_ok) {
|
|
if (b_prev) {
|
|
b_prev->next = b->next;
|
|
|
|
} else {
|
|
mac_ptr->indirect_pd_data_request_queue = b->next;
|
|
}
|
|
b->next = NULL;
|
|
b->priority = MAC_PD_DATA_MEDIUM_PRIORITY;
|
|
mcps_sap_pd_req_queue_write(mac_ptr, b);
|
|
return 1;
|
|
} else {
|
|
b_prev = b;
|
|
b = b->next;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void mac_indirect_queue_write(protocol_interface_rf_mac_setup_s *rf_mac_setup, mac_pre_build_frame_t *buffer)
|
|
{
|
|
if (!rf_mac_setup || ! buffer) {
|
|
return;
|
|
}
|
|
rf_mac_setup->indirect_pending_bytes += buffer->mac_payload_length;
|
|
buffer->next = NULL;
|
|
buffer->buffer_ttl = 7100;
|
|
//Push to queue
|
|
if (!rf_mac_setup->indirect_pd_data_request_queue) {
|
|
rf_mac_setup->indirect_pd_data_request_queue = buffer;
|
|
//Trig timer and set pending flag to radio
|
|
eventOS_callback_timer_stop(rf_mac_setup->mac_mcps_timer);
|
|
eventOS_callback_timer_start(rf_mac_setup->mac_mcps_timer, MAC_INDIRECT_TICK_IN_MS * 20);
|
|
rf_mac_setup->mac_frame_pending = true;
|
|
if (rf_mac_setup->dev_driver->phy_driver->extension) {
|
|
uint8_t value = 1;
|
|
rf_mac_setup->dev_driver->phy_driver->extension(PHY_EXTENSION_CTRL_PENDING_BIT, &value);
|
|
}
|
|
return;
|
|
}
|
|
|
|
mac_pre_build_frame_t *cur = rf_mac_setup->indirect_pd_data_request_queue;
|
|
while (cur) {
|
|
if (cur->next == NULL) {
|
|
cur->next = buffer;
|
|
cur = NULL;
|
|
} else {
|
|
cur = cur->next;
|
|
}
|
|
}
|
|
}
|