mirror of https://github.com/ARMmbed/mbed-os.git
463 lines
15 KiB
C++
463 lines
15 KiB
C++
/**
|
|
/ _____) _ | |
|
|
( (____ _____ ____ _| |_ _____ ____| |__
|
|
\____ \| ___ | (_ _) ___ |/ ___) _ \
|
|
_____) ) ____| | | || |_| ____( (___| | | |
|
|
(______/|_____)_|_|_| \__)_____)\____)_| |_|
|
|
(C)2013 Semtech
|
|
___ _____ _ ___ _ _____ ___ ___ ___ ___
|
|
/ __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
|
|
\__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
|
|
|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
|
|
embedded.connectivity.solutions===============
|
|
|
|
Description: LoRaWAN stack layer that controls both MAC and PHY underneath
|
|
|
|
License: Revised BSD License, see LICENSE.TXT file include in the project
|
|
|
|
Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jaeckle ( STACKFORCE )
|
|
|
|
|
|
Copyright (c) 2017, Arm Limited and affiliates.
|
|
|
|
SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include "lorastack/mac/LoRaMac.h"
|
|
#include "lorastack/mac/LoRaMacMib.h"
|
|
|
|
LoRaMacMib::LoRaMacMib()
|
|
: _lora_mac(NULL), _lora_phy(NULL)
|
|
{
|
|
}
|
|
|
|
LoRaMacMib::~LoRaMacMib()
|
|
{
|
|
}
|
|
|
|
void LoRaMacMib::activate_mib_subsystem(LoRaMac *mac, LoRaPHY *phy)
|
|
{
|
|
_lora_mac = mac;
|
|
_lora_phy = phy;
|
|
}
|
|
|
|
lorawan_status_t LoRaMacMib::set_request(loramac_mib_req_confirm_t *mibSet,
|
|
loramac_protocol_params *params)
|
|
{
|
|
if (mibSet == NULL || _lora_phy == NULL || _lora_mac == NULL) {
|
|
return LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
|
|
lorawan_status_t status = LORAWAN_STATUS_OK;
|
|
verification_params_t verify;
|
|
|
|
|
|
switch (mibSet->type) {
|
|
case MIB_DEVICE_CLASS: {
|
|
params->dev_class = mibSet->param.dev_class;
|
|
switch (params->dev_class) {
|
|
case CLASS_A: {
|
|
// Set the radio into sleep to setup a defined state
|
|
_lora_phy->put_radio_to_sleep();
|
|
break;
|
|
}
|
|
case CLASS_B: {
|
|
break;
|
|
}
|
|
case CLASS_C: {
|
|
// Set the is_node_ack_requested indicator to default
|
|
params->is_node_ack_requested = false;
|
|
// Set the radio into sleep mode in case we are still in RX mode
|
|
_lora_phy->put_radio_to_sleep();
|
|
// Compute Rx2 windows parameters in case the RX2 datarate has changed
|
|
_lora_phy->compute_rx_win_params(
|
|
params->sys_params.rx2_channel.datarate,
|
|
params->sys_params.min_rx_symb,
|
|
params->sys_params.max_sys_rx_error,
|
|
¶ms->rx_window2_config);
|
|
_lora_mac->open_continuous_rx2_window();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case MIB_NETWORK_JOINED: {
|
|
params->is_nwk_joined = mibSet->param.is_nwk_joined;
|
|
break;
|
|
}
|
|
case MIB_ADR: {
|
|
params->sys_params.adr_on = mibSet->param.is_adr_enable;
|
|
break;
|
|
}
|
|
case MIB_NET_ID: {
|
|
params->net_id = mibSet->param.net_id;
|
|
break;
|
|
}
|
|
case MIB_DEV_ADDR: {
|
|
params->dev_addr = mibSet->param.dev_addr;
|
|
break;
|
|
}
|
|
case MIB_NWK_SKEY: {
|
|
if (mibSet->param.nwk_skey != NULL) {
|
|
memcpy(params->keys.nwk_skey, mibSet->param.nwk_skey,
|
|
sizeof(params->keys.nwk_skey));
|
|
} else {
|
|
status = LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
break;
|
|
}
|
|
case MIB_APP_SKEY: {
|
|
if (mibSet->param.app_skey != NULL) {
|
|
memcpy(params->keys.app_skey, mibSet->param.app_skey,
|
|
sizeof(params->keys.app_skey));
|
|
} else {
|
|
status = LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
break;
|
|
}
|
|
case MIB_PUBLIC_NETWORK: {
|
|
params->is_nwk_public = mibSet->param.enable_public_nwk;
|
|
_lora_phy->setup_public_network_mode(params->is_nwk_public);
|
|
break;
|
|
}
|
|
case MIB_REPEATER_SUPPORT: {
|
|
params->is_repeater_supported = mibSet->param.enable_repeater_support;
|
|
break;
|
|
}
|
|
case MIB_RX2_CHANNEL: {
|
|
verify.datarate = mibSet->param.rx2_channel.datarate;
|
|
|
|
if (_lora_phy->verify(&verify, PHY_RX_DR) == true) {
|
|
params->sys_params.rx2_channel = mibSet->param.rx2_channel;
|
|
|
|
if ((params->dev_class == CLASS_C)
|
|
&& (params->is_nwk_joined == true)) {
|
|
// We can only compute the RX window parameters directly, if we are already
|
|
// in class c mode and joined. We cannot setup an RX window in case of any other
|
|
// class type.
|
|
// Set the radio into sleep mode in case we are still in RX mode
|
|
_lora_phy->put_radio_to_sleep();
|
|
// Compute Rx2 windows parameters
|
|
_lora_phy->compute_rx_win_params(
|
|
params->sys_params.rx2_channel.datarate,
|
|
params->sys_params.min_rx_symb,
|
|
params->sys_params.max_sys_rx_error,
|
|
¶ms->rx_window2_config);
|
|
|
|
_lora_mac->open_continuous_rx2_window();
|
|
}
|
|
} else {
|
|
status = LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
break;
|
|
}
|
|
case MIB_RX2_DEFAULT_CHANNEL: {
|
|
verify.datarate = mibSet->param.rx2_channel.datarate;
|
|
|
|
if (_lora_phy->verify(&verify, PHY_RX_DR) == true) {
|
|
params->sys_params.rx2_channel = mibSet->param.default_rx2_channel;
|
|
} else {
|
|
status = LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_DEFAULT_MASK:
|
|
case MIB_CHANNELS_MASK: {
|
|
// channel masks must not be tempered with.
|
|
// They should be manipulated only on request with certain
|
|
// APIs like add_channel() and remove_channel()
|
|
// You should be able to get these MIB parameters, not set
|
|
status = LORAWAN_STATUS_SERVICE_UNKNOWN;
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_NB_REP: {
|
|
if ((mibSet->param.channel_nb_rep >= 1)
|
|
&& (mibSet->param.channel_nb_rep <= 15)) {
|
|
params->sys_params.retry_num = mibSet->param.channel_nb_rep;
|
|
} else {
|
|
status = LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
break;
|
|
}
|
|
case MIB_MAX_RX_WINDOW_DURATION: {
|
|
params->sys_params.max_rx_win_time = mibSet->param.max_rx_window;
|
|
break;
|
|
}
|
|
case MIB_RECEIVE_DELAY_1: {
|
|
params->sys_params.recv_delay1 = mibSet->param.recv_delay1;
|
|
break;
|
|
}
|
|
case MIB_RECEIVE_DELAY_2: {
|
|
params->sys_params.recv_delay2 = mibSet->param.recv_delay2;
|
|
break;
|
|
}
|
|
case MIB_JOIN_ACCEPT_DELAY_1: {
|
|
params->sys_params.join_accept_delay1 = mibSet->param.join_accept_delay1;
|
|
break;
|
|
}
|
|
case MIB_JOIN_ACCEPT_DELAY_2: {
|
|
params->sys_params.join_accept_delay2 = mibSet->param.join_accept_delay2;
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_DEFAULT_DATARATE: {
|
|
verify.datarate = mibSet->param.default_channel_data_rate;
|
|
|
|
if (_lora_phy->verify(&verify, PHY_DEF_TX_DR) == true) {
|
|
params->sys_params.channel_data_rate = verify.datarate;
|
|
} else {
|
|
status = LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_DATARATE: {
|
|
verify.datarate = mibSet->param.channel_data_rate;
|
|
|
|
if (_lora_phy->verify(&verify, PHY_TX_DR) == true) {
|
|
params->sys_params.channel_data_rate = verify.datarate;
|
|
} else {
|
|
status = LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_DEFAULT_TX_POWER: {
|
|
verify.tx_power = mibSet->param.default_channel_tx_pwr;
|
|
|
|
if (_lora_phy->verify(&verify, PHY_DEF_TX_POWER) == true) {
|
|
params->sys_params.channel_tx_power = verify.tx_power;
|
|
} else {
|
|
status = LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_TX_POWER: {
|
|
verify.tx_power = mibSet->param.channel_tx_pwr;
|
|
|
|
if (_lora_phy->verify(&verify, PHY_TX_POWER) == true) {
|
|
params->sys_params.channel_tx_power = verify.tx_power;
|
|
} else {
|
|
status = LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
break;
|
|
}
|
|
case MIB_UPLINK_COUNTER: {
|
|
params->ul_frame_counter = mibSet->param.ul_frame_counter;
|
|
break;
|
|
}
|
|
case MIB_DOWNLINK_COUNTER: {
|
|
params->dl_frame_counter = mibSet->param.dl_frame_counter;
|
|
break;
|
|
}
|
|
case MIB_SYSTEM_MAX_RX_ERROR: {
|
|
params->sys_params.max_sys_rx_error = mibSet->param.max_rx_sys_error;
|
|
break;
|
|
}
|
|
case MIB_MIN_RX_SYMBOLS: {
|
|
params->sys_params.min_rx_symb = mibSet->param.min_rx_symb;
|
|
break;
|
|
}
|
|
case MIB_ANTENNA_GAIN: {
|
|
params->sys_params.antenna_gain = mibSet->param.antenna_gain;
|
|
break;
|
|
}
|
|
default:
|
|
status = LORAWAN_STATUS_SERVICE_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
lorawan_status_t LoRaMacMib::get_request(loramac_mib_req_confirm_t *mibGet,
|
|
loramac_protocol_params *params)
|
|
{
|
|
lorawan_status_t status = LORAWAN_STATUS_OK;
|
|
get_phy_params_t get_phy;
|
|
phy_param_t phy_param;
|
|
rx2_channel_params rx2_channel;
|
|
|
|
if( mibGet == NULL )
|
|
{
|
|
return LORAWAN_STATUS_PARAMETER_INVALID;
|
|
}
|
|
|
|
switch( mibGet->type )
|
|
{
|
|
case MIB_DEVICE_CLASS:
|
|
{
|
|
mibGet->param.dev_class = params->dev_class;
|
|
break;
|
|
}
|
|
case MIB_NETWORK_JOINED:
|
|
{
|
|
mibGet->param.is_nwk_joined = params->is_nwk_joined;
|
|
break;
|
|
}
|
|
case MIB_ADR:
|
|
{
|
|
mibGet->param.is_adr_enable = params->sys_params.adr_on;
|
|
break;
|
|
}
|
|
case MIB_NET_ID:
|
|
{
|
|
mibGet->param.net_id = params->net_id;
|
|
break;
|
|
}
|
|
case MIB_DEV_ADDR:
|
|
{
|
|
mibGet->param.dev_addr = params->dev_addr;
|
|
break;
|
|
}
|
|
case MIB_NWK_SKEY:
|
|
{
|
|
mibGet->param.nwk_skey =params->keys.nwk_skey;
|
|
break;
|
|
}
|
|
case MIB_APP_SKEY:
|
|
{
|
|
mibGet->param.app_skey = params->keys.app_skey;
|
|
break;
|
|
}
|
|
case MIB_PUBLIC_NETWORK:
|
|
{
|
|
mibGet->param.enable_public_nwk = params->is_nwk_public;
|
|
break;
|
|
}
|
|
case MIB_REPEATER_SUPPORT:
|
|
{
|
|
mibGet->param.enable_repeater_support = params->is_repeater_supported;
|
|
break;
|
|
}
|
|
case MIB_CHANNELS:
|
|
{
|
|
get_phy.attribute = PHY_CHANNELS;
|
|
phy_param = _lora_phy->get_phy_params( &get_phy );
|
|
|
|
mibGet->param.channel_list = phy_param.channel_params;
|
|
break;
|
|
}
|
|
case MIB_RX2_CHANNEL:
|
|
{
|
|
mibGet->param.rx2_channel = params->sys_params.rx2_channel;
|
|
break;
|
|
}
|
|
case MIB_RX2_DEFAULT_CHANNEL:
|
|
{
|
|
get_phy.attribute = PHY_DEF_RX2_DR;
|
|
phy_param = _lora_phy->get_phy_params( &get_phy );
|
|
rx2_channel.datarate = phy_param.value;
|
|
|
|
get_phy.attribute = PHY_DEF_RX2_FREQUENCY;
|
|
phy_param = _lora_phy->get_phy_params( &get_phy );
|
|
rx2_channel.frequency = phy_param.value;
|
|
|
|
mibGet->param.rx2_channel = rx2_channel;
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_DEFAULT_MASK:
|
|
{
|
|
get_phy.attribute = PHY_DEFAULT_CHANNEL_MASK;
|
|
phy_param = _lora_phy->get_phy_params( &get_phy );
|
|
|
|
mibGet->param.default_channel_mask = phy_param.channel_mask;
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_MASK:
|
|
{
|
|
get_phy.attribute = PHY_CHANNEL_MASK;
|
|
phy_param = _lora_phy->get_phy_params( &get_phy );
|
|
|
|
mibGet->param.channel_mask = phy_param.channel_mask;
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_NB_REP:
|
|
{
|
|
mibGet->param.channel_nb_rep = params->sys_params.retry_num;
|
|
break;
|
|
}
|
|
case MIB_MAX_RX_WINDOW_DURATION:
|
|
{
|
|
mibGet->param.max_rx_window = params->sys_params.max_rx_win_time;
|
|
break;
|
|
}
|
|
case MIB_RECEIVE_DELAY_1:
|
|
{
|
|
mibGet->param.recv_delay1 = params->sys_params.recv_delay1;
|
|
break;
|
|
}
|
|
case MIB_RECEIVE_DELAY_2:
|
|
{
|
|
mibGet->param.recv_delay2 = params->sys_params.recv_delay2;
|
|
break;
|
|
}
|
|
case MIB_JOIN_ACCEPT_DELAY_1:
|
|
{
|
|
mibGet->param.join_accept_delay1 = params->sys_params.join_accept_delay1;
|
|
break;
|
|
}
|
|
case MIB_JOIN_ACCEPT_DELAY_2:
|
|
{
|
|
mibGet->param.join_accept_delay2 = params->sys_params.join_accept_delay2;
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_DEFAULT_DATARATE:
|
|
{
|
|
get_phy.attribute = PHY_DEF_TX_DR;
|
|
phy_param = _lora_phy->get_phy_params( &get_phy );
|
|
mibGet->param.default_channel_data_rate = phy_param.value;
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_DATARATE:
|
|
{
|
|
mibGet->param.channel_data_rate = params->sys_params.channel_data_rate;
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_DEFAULT_TX_POWER:
|
|
{
|
|
get_phy.attribute = PHY_DEF_TX_POWER;
|
|
phy_param = _lora_phy->get_phy_params( &get_phy );
|
|
mibGet->param.default_channel_tx_pwr = phy_param.value;
|
|
break;
|
|
}
|
|
case MIB_CHANNELS_TX_POWER:
|
|
{
|
|
mibGet->param.channel_tx_pwr = params->sys_params.channel_tx_power;
|
|
break;
|
|
}
|
|
case MIB_UPLINK_COUNTER:
|
|
{
|
|
mibGet->param.ul_frame_counter = params->ul_frame_counter;
|
|
break;
|
|
}
|
|
case MIB_DOWNLINK_COUNTER:
|
|
{
|
|
mibGet->param.dl_frame_counter = params->dl_frame_counter;
|
|
break;
|
|
}
|
|
case MIB_MULTICAST_CHANNEL:
|
|
{
|
|
mibGet->param.multicast_list = params->multicast_channels;
|
|
break;
|
|
}
|
|
case MIB_SYSTEM_MAX_RX_ERROR:
|
|
{
|
|
mibGet->param.max_rx_sys_error = params->sys_params.max_sys_rx_error;
|
|
break;
|
|
}
|
|
case MIB_MIN_RX_SYMBOLS:
|
|
{
|
|
mibGet->param.min_rx_symb = params->sys_params.min_rx_symb;
|
|
break;
|
|
}
|
|
case MIB_ANTENNA_GAIN:
|
|
{
|
|
mibGet->param.antenna_gain = params->sys_params.antenna_gain;
|
|
break;
|
|
}
|
|
default:
|
|
status = LORAWAN_STATUS_SERVICE_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
return status;
|
|
}
|