Style Changes in MAC layer

Style changed according to Mbed-OS guidelines.
pull/6059/head
Hasnain Virk 2018-02-09 16:23:33 +02:00
parent 20bce2f21c
commit 7224fbae1c
12 changed files with 1594 additions and 1721 deletions

View File

@ -130,7 +130,7 @@ LoRaWANStack& LoRaWANStack::get_lorawan_stack()
radio_events_t *LoRaWANStack::bind_radio_driver(LoRaRadio& radio) radio_events_t *LoRaWANStack::bind_radio_driver(LoRaRadio& radio)
{ {
// Store pointer to callback routines inside MAC layer (non-IRQ safe) // Store pointer to callback routines inside MAC layer (non-IRQ safe)
_mac_handlers = _loramac.GetPhyEventHandlers(); _mac_handlers = _loramac.get_phy_event_handlers();
// passes the reference to radio driver down to PHY layer // passes the reference to radio driver down to PHY layer
_lora_phy.set_radio_instance(radio); _lora_phy.set_radio_instance(radio);
return _mac_handlers; return _mac_handlers;
@ -154,7 +154,7 @@ lorawan_status_t LoRaWANStack::initialize_mac_layer(EventQueue *queue)
#endif #endif
_lora_time.activate_timer_subsystem(queue); _lora_time.activate_timer_subsystem(queue);
_loramac.LoRaMacInitialization(&LoRaMacPrimitives, &_lora_phy, queue); _loramac.initialize(&LoRaMacPrimitives, &_lora_phy, queue);
loramac_mib_req_confirm_t mib_req; loramac_mib_req_confirm_t mib_req;
@ -267,7 +267,7 @@ lorawan_status_t LoRaWANStack::send_compliance_test_frame_to_mac()
uint16_t LoRaWANStack::check_possible_tx_size(uint16_t size) uint16_t LoRaWANStack::check_possible_tx_size(uint16_t size)
{ {
loramac_tx_info_t tx_info; loramac_tx_info_t tx_info;
if (_loramac.LoRaMacQueryTxPossible(size, &tx_info) == LORAWAN_STATUS_LENGTH_ERROR) { if (_loramac.query_tx_possible(size, &tx_info) == LORAWAN_STATUS_LENGTH_ERROR) {
// Cannot transmit this much. Return how much data can be sent // Cannot transmit this much. Return how much data can be sent
// at the moment // at the moment
return tx_info.max_possible_payload_size; return tx_info.max_possible_payload_size;
@ -404,7 +404,7 @@ lorawan_status_t LoRaWANStack::add_channels(const lorawan_channelplan_t &channel
return LORAWAN_STATUS_NOT_INITIALIZED; return LORAWAN_STATUS_NOT_INITIALIZED;
} }
return _loramac.AddChannelPlan(channel_plan); return _loramac.add_channel_plan(channel_plan);
} }
lorawan_status_t LoRaWANStack::drop_channel_list() lorawan_status_t LoRaWANStack::drop_channel_list()
@ -414,7 +414,7 @@ lorawan_status_t LoRaWANStack::drop_channel_list()
return LORAWAN_STATUS_NOT_INITIALIZED; return LORAWAN_STATUS_NOT_INITIALIZED;
} }
return _loramac.RemoveChannelPlan(); return _loramac.remove_channel_plan();
} }
lorawan_status_t LoRaWANStack::remove_a_channel(uint8_t channel_id) lorawan_status_t LoRaWANStack::remove_a_channel(uint8_t channel_id)
@ -425,7 +425,7 @@ lorawan_status_t LoRaWANStack::remove_a_channel(uint8_t channel_id)
return LORAWAN_STATUS_NOT_INITIALIZED; return LORAWAN_STATUS_NOT_INITIALIZED;
} }
return _loramac.RemoveSingleChannel(channel_id); return _loramac.remove_single_channel(channel_id);
} }
lorawan_status_t LoRaWANStack::get_enabled_channels(lorawan_channelplan_t& channel_plan) lorawan_status_t LoRaWANStack::get_enabled_channels(lorawan_channelplan_t& channel_plan)
@ -438,7 +438,7 @@ lorawan_status_t LoRaWANStack::get_enabled_channels(lorawan_channelplan_t& chann
return LORAWAN_STATUS_BUSY; return LORAWAN_STATUS_BUSY;
} }
return _loramac.GetChannelPlan(channel_plan); return _loramac.get_channel_plan(channel_plan);
} }
lorawan_status_t LoRaWANStack::enable_adaptive_datarate(bool adr_enabled) lorawan_status_t LoRaWANStack::enable_adaptive_datarate(bool adr_enabled)
@ -771,7 +771,7 @@ lorawan_status_t LoRaWANStack::mlme_request_handler(loramac_mlme_req_t *mlme_req
return LORAWAN_STATUS_PARAMETER_INVALID; return LORAWAN_STATUS_PARAMETER_INVALID;
} }
return _loramac.LoRaMacMlmeRequest(mlme_request); return _loramac.mlme_request(mlme_request);
} }
/** MLME-Confirm event function /** MLME-Confirm event function
@ -843,7 +843,7 @@ lorawan_status_t LoRaWANStack::mcps_request_handler(loramac_mcps_req_t *mcps_req
return LORAWAN_STATUS_PARAMETER_INVALID; return LORAWAN_STATUS_PARAMETER_INVALID;
} }
return _loramac.LoRaMacMcpsRequest(mcps_request); return _loramac.mcps_request(mcps_request);
} }
/** MCPS-Confirm event function /** MCPS-Confirm event function
@ -1154,7 +1154,7 @@ lorawan_status_t LoRaWANStack::mib_set_request(loramac_mib_req_confirm_t *mib_se
if (NULL == mib_set_params) { if (NULL == mib_set_params) {
return LORAWAN_STATUS_PARAMETER_INVALID; return LORAWAN_STATUS_PARAMETER_INVALID;
} }
return _loramac.LoRaMacMibSetRequestConfirm(mib_set_params); return _loramac.mib_set_request_confirm(mib_set_params);
} }
lorawan_status_t LoRaWANStack::mib_get_request(loramac_mib_req_confirm_t *mib_get_params) lorawan_status_t LoRaWANStack::mib_get_request(loramac_mib_req_confirm_t *mib_get_params)
@ -1162,7 +1162,7 @@ lorawan_status_t LoRaWANStack::mib_get_request(loramac_mib_req_confirm_t *mib_ge
if(NULL == mib_get_params) { if(NULL == mib_get_params) {
return LORAWAN_STATUS_PARAMETER_INVALID; return LORAWAN_STATUS_PARAMETER_INVALID;
} }
return _loramac.LoRaMacMibGetRequestConfirm(mib_get_params); return _loramac.mib_get_request_confirm(mib_get_params);
} }
lorawan_status_t LoRaWANStack::set_link_check_request() lorawan_status_t LoRaWANStack::set_link_check_request()

File diff suppressed because it is too large Load Diff

View File

@ -37,8 +37,8 @@
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
* *
*/ */
#ifndef __LORAMAC_H__ #ifndef MBED_LORAWAN_MAC_H__
#define __LORAMAC_H__ #define MBED_LORAWAN_MAC_H__
#include "lorawan/system/LoRaWANTimer.h" #include "lorawan/system/LoRaWANTimer.h"
#include "lorastack/phy/LoRaPHY.h" #include "lorastack/phy/LoRaPHY.h"
@ -50,63 +50,63 @@
#include "lorastack/mac/LoRaMacMib.h" #include "lorastack/mac/LoRaMacMib.h"
#include "lorastack/mac/LoRaMacChannelPlan.h" #include "lorastack/mac/LoRaMacChannelPlan.h"
class LoRaMac class LoRaMac {
{
public: public:
/*!
* \brief Constructor /**
* Constructor
*/ */
LoRaMac(LoRaWANTimeHandler &lora_time); LoRaMac(LoRaWANTimeHandler &lora_time);
/*! /**
* \brief Destructor * Destructor
*/ */
~LoRaMac(); ~LoRaMac();
/*! /**
* \brief LoRaMAC layer initialization * @brief LoRaMAC layer initialization
* *
* \details In addition to the initialization of the LoRaMAC layer, this * @details In addition to the initialization of the LoRaMAC layer, this
* function initializes the callback primitives of the MCPS and * function initializes the callback primitives of the MCPS and
* MLME services. Every data field of \ref loramac_primitives_t must be * MLME services. Every data field of \ref loramac_primitives_t must be
* set to a valid callback function. * set to a valid callback function.
* *
* \param primitives [in] - A pointer to the structure defining the LoRaMAC * @param primitives [in] A pointer to the structure defining the LoRaMAC
* event functions. Refer to \ref loramac_primitives_t. * event functions. Refer to \ref loramac_primitives_t.
* *
* \param phy [in]- A pointer to the selected PHY layer. * @param phy [in] A pointer to the selected PHY layer.
* *
* \param queue [in]- A pointer to the application provided EventQueue. * @param queue [in] A pointer to the application provided EventQueue.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
lorawan_status_t LoRaMacInitialization(loramac_primitives_t *primitives, lorawan_status_t initialize(loramac_primitives_t *primitives, LoRaPHY *phy,
LoRaPHY *phy, events::EventQueue *queue);
events::EventQueue *queue);
/*! /**
* \brief Disconnect LoRaMac layer * @brief Disconnect LoRaMac layer
* *
* \details Cancels all outstanding requests and sets LoRaMac's * @details Cancels all outstanding requests and sets LoRaMac's
* internal state to idle. * internal state to idle.
*/ */
void disconnect(void); void disconnect(void);
/*! /**
* \brief Queries the LoRaMAC whether it is possible to send the next frame with * @brief Queries the LoRaMAC whether it is possible to send the next frame with
* a given payload size. The LoRaMAC takes the scheduled MAC commands into * a given payload size. The LoRaMAC takes the scheduled MAC commands into
* account and reports when the frame can be sent. * account and reports when the frame can be sent.
* *
* \param size [in]- The size of the applicable payload to be sent next. * @param size [in] The size of the applicable payload to be sent next.
* \param txInfo [out] - The structure \ref loramac_tx_info_t contains * @param tx_info [out] The structure \ref loramac_tx_info_t contains
* information on the actual maximum payload possible * information on the actual maximum payload possible
* (according to the configured datarate or the next * (according to the configured datarate or the next
* datarate according to ADR), and the maximum frame * datarate according to ADR), and the maximum frame
* size, taking the scheduled MAC commands into account. * size, taking the scheduled MAC commands into account.
* *
* \retval `LoRaMacStatus_t` The status of the operation. When the parameters are * @return `lorawan_status_t` The status of the operation. When the parameters are
* not valid, the function returns \ref LORAWAN_STATUS_PARAMETER_INVALID. * not valid, the function returns \ref LORAWAN_STATUS_PARAMETER_INVALID.
* In case of a length error caused by the applicable payload in combination * In case of a length error caused by the applicable payload in combination
* with the MAC commands, the function returns \ref LORAWAN_STATUS_LENGTH_ERROR. * with the MAC commands, the function returns \ref LORAWAN_STATUS_LENGTH_ERROR.
@ -116,192 +116,201 @@ public:
* If the query is valid, and the LoRaMAC is able to send the frame, * If the query is valid, and the LoRaMAC is able to send the frame,
* the function returns \ref LORAWAN_STATUS_OK. * the function returns \ref LORAWAN_STATUS_OK.
*/ */
lorawan_status_t LoRaMacQueryTxPossible( uint8_t size, loramac_tx_info_t* txInfo ); lorawan_status_t query_tx_possible(uint8_t size, loramac_tx_info_t* tx_info);
/*! /**
* \brief Adds a channel plan to the system. * @brief Adds a channel plan to the system.
* *
* \details Adds a whole channel plan or a single new channel to the. * @details Adds a whole channel plan or a single new channel if the plan
* contains only one channel and 'plan.nb_channels' is set to 1.
* Please note that this functionality is not available in all regions. * Please note that this functionality is not available in all regions.
* Information on the allowed ranges is available at the * Information on the allowed ranges is available at the
* LoRaWAN Regional Parameters V1.0.2rB. * LoRaWAN Regional Parameters V1.0.2rB.
* *
* \param plan [in] - A reference to application provided channel plan. * @param plan [in] A reference to application provided channel plan.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
lorawan_status_t AddChannelPlan(const lorawan_channelplan_t& plan); lorawan_status_t add_channel_plan(const lorawan_channelplan_t& plan);
/*! /**
* \brief Removes a channel plan from the system. * @brief Removes a channel plan from the system.
* *
* \details Removes the whole active channel plan except the 'Default Channels'.. * @details Removes the whole active channel plan except the 'Default Channels'.
* Please note that this functionality is not available in all regions. * Please note that this functionality is not available in all regions.
* Information on the allowed ranges is available at the * Information on the allowed ranges is available at the
* LoRaWAN Regional Parameters V1.0.2rB. * LoRaWAN Regional Parameters V1.0.2rB.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
lorawan_status_t RemoveChannelPlan(); lorawan_status_t remove_channel_plan();
/*! /**
* \brief Access active channel plan. * @brief Access active channel plan.
* *
* \details Provides access to the current active channel plan. * @details Provides access to the current active channel plan.
* *
* \param plan [out] - A reference to application provided channel plan data * @param plan [out] A reference to application provided channel plan data
* structure which will be filled in with active channel * structure which will be filled in with active channel
* plan. * plan.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
lorawan_status_t GetChannelPlan(lorawan_channelplan_t& plan); lorawan_status_t get_channel_plan(lorawan_channelplan_t& plan);
/*! /**
* \brief Remove a given channel from the active plan. * @brief Remove a given channel from the active plan.
* *
* \details Deactivates the given channel. * @details Deactivates the given channel.
* *
* \param id - Id of the channel. * @param id Id of the channel.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
lorawan_status_t RemoveSingleChannel( uint8_t id ); lorawan_status_t remove_single_channel(uint8_t id);
/*! /**
* \brief LoRaMAC multicast channel link service. * @brief LoRaMAC multicast channel link service.
* *
* \details Links a multicast channel into the linked list. * @details Links a multicast channel into the linked list.
* *
* \param [in] channelParam - The multicast channel parameters to link. * @param [in] channel_param The multicast channel parameters to link.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
lorawan_status_t LoRaMacMulticastChannelLink( multicast_params_t *channelParam ); lorawan_status_t multicast_channel_link(multicast_params_t *channel_param);
/*! /**
* \brief LoRaMAC multicast channel unlink service. * @brief LoRaMAC multicast channel unlink service.
* *
* \details Unlinks a multicast channel from the linked list. * @details Unlinks a multicast channel from the linked list.
* *
* \param [in] channelParam - The multicast channel parameters to unlink. * @param [in] channel_param The multicast channel parameters to unlink.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
lorawan_status_t LoRaMacMulticastChannelUnlink( multicast_params_t *channelParam ); lorawan_status_t multicast_channel_unlink(multicast_params_t *channel_param);
/*! /**
* \brief LoRaMAC MIB-GET. * @brief Get parameter values from MIB service.
* *
* \details The MAC information base service to get the attributes of the LoRaMac layer. * @details The MAC information base service to get the attributes of the LoRaMac layer.
* *
* The following code-snippet shows how to use the API to get the * The following code-snippet shows how to use the API to get the
* parameter `AdrEnable`, defined by the enumeration type * parameter `AdrEnable`, defined by the enumeration type
* \ref MIB_ADR. * \ref MIB_ADR.
* \code
* MibRequestConfirm_t mibReq;
* mibReq.Type = MIB_ADR;
* *
* if( LoRaMacMibGetRequestConfirm( &mibReq ) == LORAWAN_STATUS_OK ) * @code
* { *
* loramac_mib_req_confirm_t mib_get;
* mib_get.type = MIB_ADR;
*
* if (mib_get_request_confirm(&mib_get) == LORAWAN_STATUS_OK) {
* // LoRaMAC updated the parameter mibParam.AdrEnable * // LoRaMAC updated the parameter mibParam.AdrEnable
* } * }
* \endcode
* *
* \param [in] mibGet - The MIB-GET request to perform. Refer to \ref loramac_mib_req_confirm_t. * @endcode
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @param [in] mib_get The MIB-GET request to perform. Refer to
* \ref loramac_mib_req_confirm_t.
*
* @return `lorawan_status_t` The status of the operation.
* The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN * \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
lorawan_status_t LoRaMacMibGetRequestConfirm( loramac_mib_req_confirm_t *mibGet ); lorawan_status_t mib_get_request_confirm(loramac_mib_req_confirm_t *mib_get);
/*! /**
* \brief LoRaMAC MIB-SET. * @brief Set attributes for MAC layer using MIB service.
* *
* \details The MAC information base service to set the attributes of the LoRaMac layer. * @details The MAC information base service to set the attributes of the LoRaMac layer.
* *
* The following code-snippet shows how to use the API to set the * The following code-snippet shows how to use the API to set the
* parameter `AdrEnable`, defined by the enumeration type * parameter `adr_enable`, defined by the enumeration type
* \ref MIB_ADR. * \ref MIB_ADR.
* *
* \code * @code
* MibRequestConfirm_t mibReq;
* mibReq.Type = MIB_ADR;
* mibReq.Param.AdrEnable = true;
* *
* if( LoRaMacMibGetRequestConfirm( &mibReq ) == LORAWAN_STATUS_OK ) * loramac_mib_req_confirm_t mib_set;
* { * mib_set.Type = MIB_ADR;
* mib_set.param.adr_enable = true;
*
* if (mib_set_request_confirm(&mib_set) == LORAWAN_STATUS_OK) {
* // LoRaMAC updated the parameter * // LoRaMAC updated the parameter
* } * }
* \endcode
* *
* \param [in] mibSet - The MIB-SET request to perform. Refer to \ref loramac_mib_req_confirm_t. * @endcode
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @param [in] mib_set The MIB-SET request to perform. Refer to
* \ref loramac_mib_req_confirm_t.
*
* @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN * \ref LORAWAN_STATUS_SERVICE_UNKNOWN
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
lorawan_status_t LoRaMacMibSetRequestConfirm( loramac_mib_req_confirm_t *mibSet ); lorawan_status_t mib_set_request_confirm(loramac_mib_req_confirm_t *mib_set);
/*! /**
* \brief LoRaMAC MLME request * @brief Set forth an MLME request.
* *
* \details The MAC layer management entity handles the management services. The * @details The MAC layer management entity handles the management services. The
* following code-snippet shows how to use the API to perform a * following code-snippet shows how to use the API to perform a
* network join request. * network join request.
* *
* \code * @code
* static uint8_t DevEui[] = *
* static uint8_t dev_eui[] =
* { * {
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
* }; * };
* static uint8_t AppEui[] = * static uint8_t app_eui[] =
* { * {
* 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
* }; * };
* static uint8_t AppKey[] = * static uint8_t app_key[] =
* { * {
* 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, * 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
* 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C * 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
* }; * };
* *
* MlmeReq_t mlmeReq; * loramac_mlme_req_t mlme_req;
* mlmeReq.Type = MLME_JOIN; * mlme_req.Type = MLME_JOIN;
* mlmeReq.Req.Join.DevEui = DevEui; * mlme_req.req.join.dev_eui = dev_eui;
* mlmeReq.Req.Join.AppEui = AppEui; * mlme_req.req.join.app_eui = app_eui;
* mlmeReq.Req.Join.AppKey = AppKey; * mlme_req.req.join.app_key = app_key;
* *
* if( LoRaMacMlmeRequest( &mlmeReq ) == LORAWAN_STATUS_OK ) * if (LoRaMacMlmeRequest(&mlme_req) == LORAWAN_STATUS_OK) {
* {
* // Service started successfully. Waiting for the Mlme-Confirm event * // Service started successfully. Waiting for the Mlme-Confirm event
* } * }
* \endcode
* *
* \param [in] mlmeRequest - The MLME request to perform. Refer to \ref loramac_mlme_req_t. * @endcode
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @param [in] request The MLME request to perform.
* Refer to \ref loramac_mlme_req_t.
*
* @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN * \ref LORAWAN_STATUS_SERVICE_UNKNOWN
@ -310,33 +319,35 @@ public:
* \ref LORAWAN_STATUS_LENGTH_ERROR * \ref LORAWAN_STATUS_LENGTH_ERROR
* \ref LORAWAN_STATUS_DEVICE_OFF * \ref LORAWAN_STATUS_DEVICE_OFF
*/ */
lorawan_status_t LoRaMacMlmeRequest( loramac_mlme_req_t *mlmeRequest ); lorawan_status_t mlme_request(loramac_mlme_req_t *request);
/*! /**
* \brief LoRaMAC MCPS request * @brief Set forth an MCPS request.
* *
* \details The MAC Common Part Sublayer handles the data services. The following * @details The MAC Common Part Sublayer handles the data services. The following
* code-snippet shows how to use the API to send an unconfirmed * code-snippet shows how to use the API to send an unconfirmed
* LoRaMAC frame. * LoRaMAC frame.
* *
* \code * @code
* uint8_t myBuffer[] = { 1, 2, 3 };
* *
* McpsReq_t mcpsReq; * uint8_t buffer[] = {1, 2, 3};
* mcpsReq.Type = MCPS_UNCONFIRMED;
* mcpsReq.Req.Unconfirmed.fPort = 1;
* mcpsReq.Req.Unconfirmed.fBuffer = myBuffer;
* mcpsReq.Req.Unconfirmed.fBufferSize = sizeof( myBuffer );
* *
* if( LoRaMacMcpsRequest( &mcpsReq ) == LORAWAN_STATUS_OK ) * loramac_mcps_req_t request;
* { * request.type = MCPS_UNCONFIRMED;
* request.req.unconfirmed.fport = 1;
* request.req.unconfirmed.f_buffer = buffer;
* request.req.unconfirmed.f_buffer_size = sizeof(buffer);
*
* if (mcps_request(&request) == LORAWAN_STATUS_OK) {
* // Service started successfully. Waiting for the MCPS-Confirm event * // Service started successfully. Waiting for the MCPS-Confirm event
* } * }
* \endcode
* *
* \param [in] mcpsRequest - The MCPS request to perform. Refer to \ref loramac_mcps_req_t. * @endcode
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * @param [in] request The MCPS request to perform.
* Refer to \ref loramac_mcps_req_t.
*
* @return `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_BUSY * \ref LORAWAN_STATUS_BUSY
* \ref LORAWAN_STATUS_SERVICE_UNKNOWN * \ref LORAWAN_STATUS_SERVICE_UNKNOWN
@ -345,65 +356,76 @@ public:
* \ref LORAWAN_STATUS_LENGTH_ERROR * \ref LORAWAN_STATUS_LENGTH_ERROR
* \ref LORAWAN_STATUS_DEVICE_OFF * \ref LORAWAN_STATUS_DEVICE_OFF
*/ */
lorawan_status_t LoRaMacMcpsRequest( loramac_mcps_req_t *mcpsRequest ); lorawan_status_t mcps_request(loramac_mcps_req_t *request);
/** /**
* \brief LoRaMAC layer provides its callback functions for * @brief LoRaMAC layer provides its callback functions for
* PHY layer * PHY layer.
* *
* \return Pointer to callback functions for radio events * @return Pointer to callback functions for radio events
*/ */
radio_events_t *GetPhyEventHandlers(); radio_events_t *get_phy_event_handlers();
/*! /**
* \brief Configures the events to trigger an MLME-Indication with * @brief Configures the events to trigger an MLME-Indication with
* a MLME type of MLME_SCHEDULE_UPLINK. * a MLME type of MLME_SCHEDULE_UPLINK.
*/ */
void SetMlmeScheduleUplinkIndication( void ); void set_mlme_schedule_ul_indication(void);
/*! /**
* \brief LoRaMAC layer generic send frame * @brief Schedules the frame for sending.
* *
* \param [in] macHdr MAC header field * @details Prepares a full MAC frame and schedules it for physical
* \param [in] fPort MAC payload port * transmission.
* \param [in] fBuffer MAC data buffer to be sent *
* \param [in] fBufferSize MAC data buffer size * @param [in] mac_hdr MAC frame header field
* \retval status Status of the operation. * @param [in] fport Payload port
* @param [in] fbuffer MAC frame data buffer to be sent
* @param [in] fbuffer_size MAC frame data buffer size
*
* @return status Status of the operation. LORAWAN_STATUS_OK in case
* of success and a negative error code in case of
* failure.
*/ */
lorawan_status_t Send( loramac_mhdr_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ); lorawan_status_t send(loramac_mhdr_t *mac_hdr, uint8_t fport, void *fbuffer,
uint16_t fbuffer_size);
/*! /**
* \brief Sets the radio in continuous transmission mode * @brief Puts the system in continuous transmission mode
* *
* \remark Uses the radio parameters set on the previous transmission. * @remark Uses the radio parameters set on the previous transmission.
* *
* \param [in] timeout Time in seconds while the radio is kept in continuous wave mode * @param [in] timeout Time in seconds while the radio is kept in continuous wave mode
* \retval status Status of the operation. *
* @return status Status of the operation. LORAWAN_STATUS_OK in case
* of success and a negative error code in case of
* failure.
*/ */
lorawan_status_t SetTxContinuousWave( uint16_t timeout ); lorawan_status_t set_tx_continuous_wave(uint16_t timeout);
/*! /**
* \brief Sets the radio in continuous transmission mode * @brief Puts the system in continuous transmission mode
* *
* \remark Uses the radio parameters set on the previous transmission. * @param [in] timeout Time in seconds while the radio is kept in continuous wave mode
* @param [in] frequency RF frequency to be set.
* @param [in] power RF output power to be set.
* *
* \param [in] timeout Time in seconds while the radio is kept in continuous wave mode * @return status Status of the operation. LORAWAN_STATUS_OK in case
* \param [in] frequency RF frequency to be set. * of success and a negative error code in case of
* \param [in] power RF output power to be set. * failure.
* \retval status Status of the operation.
*/ */
lorawan_status_t SetTxContinuousWave1( uint16_t timeout, uint32_t frequency, uint8_t power ); lorawan_status_t set_tx_continuous_wave1(uint16_t timeout, uint32_t frequency, uint8_t power);
/*! /**
* \brief Resets MAC specific parameters to default * @brief Resets MAC specific parameters to default
*/ */
void ResetMacParameters( void ); void reset_mac_parameters(void);
/*! /**
* \brief Opens up a continuous RX 2 window. This is used for * @brief Opens up a continuous RX 2 window. This is used for
* class c devices. * class c devices.
*/ */
void OpenContinuousRx2Window(void); void open_continuous_rx2_window(void);
#if defined(LORAWAN_COMPLIANCE_TEST) #if defined(LORAWAN_COMPLIANCE_TEST)
public: // Test interface public: // Test interface
@ -415,7 +437,7 @@ public: // Test interface
* *
* \param [in] NextTxTime - Periodic time for next uplink. * \param [in] NextTxTime - Periodic time for next uplink.
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * \retval `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
@ -426,7 +448,7 @@ public: // Test interface
* *
* \details Stops the next tx timer. * \details Stops the next tx timer.
* *
* \retval `LoRaMacStatus_t` The status of the operation. The possible values are: * \retval `lorawan_status_t` The status of the operation. The possible values are:
* \ref LORAWAN_STATUS_OK * \ref LORAWAN_STATUS_OK
* \ref LORAWAN_STATUS_PARAMETER_INVALID * \ref LORAWAN_STATUS_PARAMETER_INVALID
*/ */
@ -480,138 +502,103 @@ private:
#endif #endif
private: private:
/*! /**
* \brief Function to be executed on Radio Tx Done event * Function to be executed on Radio Tx Done event
*/ */
void OnRadioTxDone( void ); void on_radio_tx_done(void);
/*!
* \brief This function prepares the MAC to abort the execution of function
* OnRadioRxDone in case of a reception error.
*/
void PrepareRxDoneAbort( void );
/*!
* \brief Function to be executed on Radio Rx Done event
*/
void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
/*!
* \brief Function executed on Radio Tx Timeout event
*/
void OnRadioTxTimeout( void );
/*!
* \brief Function executed on Radio Rx error event
*/
void OnRadioRxError( void );
/*!
* \brief Function executed on Radio Rx Timeout event
*/
void OnRadioRxTimeout( void );
/*!
* \brief Function executed on Resend Frame timer event.
*/
void OnMacStateCheckTimerEvent( void );
/*!
* \brief Function executed on duty cycle delayed Tx timer event
*/
void OnTxDelayedTimerEvent( void );
/** /**
* \brief Function to be executed when next Tx is possible * This function prepares the MAC to abort the execution of function
* on_radio_rx_done() in case of a reception error.
*/ */
void OnNextTx( void ); void prepare_rx_done_abort(void);
/*! /**
* \brief Function executed on first Rx window timer event * Function to be executed on Radio Rx Done event
*/ */
void OnRxWindow1TimerEvent( void ); void on_radio_rx_done(uint8_t *payload, uint16_t size, int16_t rssi,
int8_t snr);
/*! /**
* \brief Function executed on second Rx window timer event * Function executed on Radio Tx Timeout event
*/ */
void OnRxWindow2TimerEvent( void ); void on_radio_tx_timeout(void);
/*! /**
* \brief Function executed on AckTimeout timer event * Function executed on Radio Rx error event
*/ */
void OnAckTimeoutTimerEvent( void ); void on_radio_rx_error(void);
/*! /**
* \brief Initializes and opens the reception window * Function executed on Radio Rx Timeout event
*
* \param [in] rxContinuous Set to true, if the RX is in continuous mode
* \param [in] maxRxWindow Maximum RX window timeout
*/ */
void RxWindowSetup( bool rxContinuous, uint32_t maxRxWindow ); void on_radio_rx_timeout(void);
/*! /**
* \brief Validates if the payload fits into the frame, taking the datarate *Function executed on Resend Frame timer event.
* into account.
*
* \details Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0
*
* \param lenN Length of the application payload. The length depends on the
* datarate and is region specific
*
* \param datarate Current datarate
*
* \param fOptsLen Length of the fOpts field
*
* \retval [false: payload does not fit into the frame, true: payload fits into
* the frame]
*/ */
bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen ); void on_mac_state_check_timer_event(void);
/*! /**
* \brief LoRaMAC layer frame buffer initialization * Function executed on duty cycle delayed Tx timer event
*
* \param [in] macHdr MAC header field
* \param [in] fCtrl MAC frame control field
* \param [in] fPort MAC payload port
* \param [in] fBuffer MAC data buffer to be sent
* \param [in] fBufferSize MAC data buffer size
* \retval status Status of the operation.
*/ */
lorawan_status_t PrepareFrame( loramac_mhdr_t *macHdr, loramac_frame_ctrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ); void on_tx_delayed_timer_event(void);
/* /**
* \brief Schedules the frame according to the duty cycle * Function executed on first Rx window timer event
*
* \retval Status of the operation
*/ */
lorawan_status_t ScheduleTx( void ); void on_rx_window1_timer_event(void);
/* /**
* \brief Calculates the back-off time for the band of a channel. * Function executed on second Rx window timer event
*
* \param [in] channel The last Tx channel index
*/ */
void CalculateBackOff( uint8_t channel ); void on_rx_window2_timer_event(void);
/*! /**
* \brief LoRaMAC layer prepared frame buffer transmission with channel specification * Function executed on AckTimeout timer event
*
* \remark PrepareFrame must be called at least once before calling this
* function.
*
* \param [in] channel Channel to transmit on
* \retval status Status of the operation.
*/ */
lorawan_status_t SendFrameOnChannel( uint8_t channel ); void on_ack_timeout_timer_event(void);
/*! /**
* \brief Resets MAC specific parameters to default * Initializes and opens the reception window
*
* \param [in] fPort The fPort
*
* \retval [false: fPort not allowed, true: fPort allowed]
*/ */
bool IsFPortAllowed( uint8_t fPort ); void rx_window_setup(bool rx_continuous, uint32_t max_rx_window_time);
/**
* Validates if the payload fits into the frame, taking the datarate
* into account.
*
* Please Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0.2
*/
bool validate_payload_length(uint8_t length, int8_t datarate, uint8_t fopts_len);
/**
* Prepares MAC frame on the behest of send() API.
*/
lorawan_status_t prepare_frame(loramac_mhdr_t *mac_hdr,
loramac_frame_ctrl_t *fctrl, uint8_t fport,
void *fbuffer, uint16_t fbuffer_size);
/**
* Schedules a transmission on the behest of send() API.
*/
lorawan_status_t schedule_tx(void);
/**
* Calculates the back-off time for the band of a channel.
* Takes in the last used channel id as a parameter.
*/
void calculate_backOff(uint8_t channel_id);
/**
* Hands over the MAC frame to PHY layer.
*/
lorawan_status_t send_frame_on_channel(uint8_t channel);
/**
* Checks for Port validity.
*/
bool is_fPort_allowed(uint8_t fPort);
/** /**
* Prototypes for ISR handlers * Prototypes for ISR handlers
@ -660,7 +647,7 @@ private:
/** /**
* Channel planning subsystem * Channel planning subsystem
*/ */
LoRaMacChannelPlan ch_plan; LoRaMacChannelPlan channel_plan;
/** /**
* Timer subsystem handle * Timer subsystem handle
@ -675,12 +662,12 @@ private:
/** /**
* Radio event callback handlers for MAC * Radio event callback handlers for MAC
*/ */
radio_events_t RadioEvents; radio_events_t radio_events;
/*! /**
* LoRaMac upper layer event functions * LoRaMac upper layer event functions
*/ */
loramac_primitives_t *LoRaMacPrimitives; loramac_primitives_t *mac_primitives;
/** /**
* EventQueue object storage * EventQueue object storage
@ -688,4 +675,4 @@ private:
events::EventQueue *ev_queue; events::EventQueue *ev_queue;
}; };
#endif // __LORAMAC_H__ #endif // MBED_LORAWAN_MAC_H__

View File

@ -33,183 +33,167 @@ SPDX-License-Identifier: BSD-3-Clause
#define tr_error(...) (void(0)) //dummies if feature common pal is not added #define tr_error(...) (void(0)) //dummies if feature common pal is not added
#endif //defined(FEATURE_COMMON_PAL) #endif //defined(FEATURE_COMMON_PAL)
/*! /**
* LoRaMAC max EIRP (dBm) table. * LoRaMAC max EIRP (dBm) table.
*/ */
static const uint8_t LoRaMacMaxEirpTable[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21, 24, 26, 27, 29, 30, 33, 36 }; static const uint8_t max_eirp_table[] = { 8, 10, 12, 13, 14, 16, 18, 20, 21, 24, 26, 27, 29, 30, 33, 36 };
LoRaMacCommand::LoRaMacCommand(LoRaMac& lora_mac) LoRaMacCommand::LoRaMacCommand(LoRaMac& lora_mac)
: _lora_mac(lora_mac) : _lora_mac(lora_mac)
{ {
MacCommandsInNextTx = false; mac_cmd_in_next_tx = false;
MacCommandsBufferIndex = 0; mac_cmd_buf_idx = 0;
MacCommandsBufferToRepeatIndex = 0; mac_cmd_buf_idx_to_repeat = 0;
memset(MacCommandsBuffer, 0, sizeof(MacCommandsBuffer)); memset(mac_cmd_buffer, 0, sizeof(mac_cmd_buffer));
memset(MacCommandsBufferToRepeat, 0, sizeof(MacCommandsBufferToRepeat)); memset(mac_cmd_buffer_to_repeat, 0, sizeof(mac_cmd_buffer_to_repeat));
} }
LoRaMacCommand::~LoRaMacCommand() LoRaMacCommand::~LoRaMacCommand()
{ {
} }
lorawan_status_t LoRaMacCommand::AddMacCommand(uint8_t cmd, uint8_t p1, uint8_t p2) lorawan_status_t LoRaMacCommand::add_mac_command(uint8_t cmd, uint8_t p1,
uint8_t p2)
{ {
lorawan_status_t status = LORAWAN_STATUS_BUSY; lorawan_status_t status = LORAWAN_STATUS_BUSY;
// The maximum buffer length must take MAC commands to re-send into account. // The maximum buffer length must take MAC commands to re-send into account.
const uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex; const uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH
- mac_cmd_buf_idx_to_repeat;
switch( cmd ) switch (cmd) {
{
case MOTE_MAC_LINK_CHECK_REQ: case MOTE_MAC_LINK_CHECK_REQ:
if( MacCommandsBufferIndex < bufLen ) if (mac_cmd_buf_idx < bufLen) {
{ mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// No payload for this command // No payload for this command
status = LORAWAN_STATUS_OK; status = LORAWAN_STATUS_OK;
} }
break; break;
case MOTE_MAC_LINK_ADR_ANS: case MOTE_MAC_LINK_ADR_ANS:
if( MacCommandsBufferIndex < ( bufLen - 1 ) ) if (mac_cmd_buf_idx < (bufLen - 1)) {
{ mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// Margin // Margin
MacCommandsBuffer[MacCommandsBufferIndex++] = p1; mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
status = LORAWAN_STATUS_OK; status = LORAWAN_STATUS_OK;
} }
break; break;
case MOTE_MAC_DUTY_CYCLE_ANS: case MOTE_MAC_DUTY_CYCLE_ANS:
if( MacCommandsBufferIndex < bufLen ) if (mac_cmd_buf_idx < bufLen) {
{ mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// No payload for this answer // No payload for this answer
status = LORAWAN_STATUS_OK; status = LORAWAN_STATUS_OK;
} }
break; break;
case MOTE_MAC_RX_PARAM_SETUP_ANS: case MOTE_MAC_RX_PARAM_SETUP_ANS:
if( MacCommandsBufferIndex < ( bufLen - 1 ) ) if (mac_cmd_buf_idx < (bufLen - 1)) {
{ mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// Status: Datarate ACK, Channel ACK // Status: Datarate ACK, Channel ACK
MacCommandsBuffer[MacCommandsBufferIndex++] = p1; mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
// This is a sticky MAC command answer. Setup indication // This is a sticky MAC command answer. Setup indication
_lora_mac.SetMlmeScheduleUplinkIndication(); _lora_mac.set_mlme_schedule_ul_indication();
status = LORAWAN_STATUS_OK; status = LORAWAN_STATUS_OK;
} }
break; break;
case MOTE_MAC_DEV_STATUS_ANS: case MOTE_MAC_DEV_STATUS_ANS:
if( MacCommandsBufferIndex < ( bufLen - 2 ) ) if (mac_cmd_buf_idx < (bufLen - 2)) {
{ mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// 1st byte Battery // 1st byte Battery
// 2nd byte Margin // 2nd byte Margin
MacCommandsBuffer[MacCommandsBufferIndex++] = p1; mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
MacCommandsBuffer[MacCommandsBufferIndex++] = p2; mac_cmd_buffer[mac_cmd_buf_idx++] = p2;
status = LORAWAN_STATUS_OK; status = LORAWAN_STATUS_OK;
} }
break; break;
case MOTE_MAC_NEW_CHANNEL_ANS: case MOTE_MAC_NEW_CHANNEL_ANS:
if( MacCommandsBufferIndex < ( bufLen - 1 ) ) if (mac_cmd_buf_idx < (bufLen - 1)) {
{ mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// Status: Datarate range OK, Channel frequency OK // Status: Datarate range OK, Channel frequency OK
MacCommandsBuffer[MacCommandsBufferIndex++] = p1; mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
status = LORAWAN_STATUS_OK; status = LORAWAN_STATUS_OK;
} }
break; break;
case MOTE_MAC_RX_TIMING_SETUP_ANS: case MOTE_MAC_RX_TIMING_SETUP_ANS:
if( MacCommandsBufferIndex < bufLen ) if (mac_cmd_buf_idx < bufLen) {
{ mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// No payload for this answer // No payload for this answer
// This is a sticky MAC command answer. Setup indication // This is a sticky MAC command answer. Setup indication
_lora_mac.SetMlmeScheduleUplinkIndication(); _lora_mac.set_mlme_schedule_ul_indication();
status = LORAWAN_STATUS_OK; status = LORAWAN_STATUS_OK;
} }
break; break;
case MOTE_MAC_TX_PARAM_SETUP_ANS: case MOTE_MAC_TX_PARAM_SETUP_ANS:
if( MacCommandsBufferIndex < bufLen ) if (mac_cmd_buf_idx < bufLen) {
{ mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// No payload for this answer // No payload for this answer
status = LORAWAN_STATUS_OK; status = LORAWAN_STATUS_OK;
} }
break; break;
case MOTE_MAC_DL_CHANNEL_ANS: case MOTE_MAC_DL_CHANNEL_ANS:
if( MacCommandsBufferIndex < bufLen ) if (mac_cmd_buf_idx < bufLen) {
{ mac_cmd_buffer[mac_cmd_buf_idx++] = cmd;
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// Status: Uplink frequency exists, Channel frequency OK // Status: Uplink frequency exists, Channel frequency OK
MacCommandsBuffer[MacCommandsBufferIndex++] = p1; mac_cmd_buffer[mac_cmd_buf_idx++] = p1;
// This is a sticky MAC command answer. Setup indication // This is a sticky MAC command answer. Setup indication
_lora_mac.SetMlmeScheduleUplinkIndication(); _lora_mac.set_mlme_schedule_ul_indication();
status = LORAWAN_STATUS_OK; status = LORAWAN_STATUS_OK;
} }
break; break;
default: default:
return LORAWAN_STATUS_SERVICE_UNKNOWN; return LORAWAN_STATUS_SERVICE_UNKNOWN;
} }
if( status == LORAWAN_STATUS_OK ) if (status == LORAWAN_STATUS_OK) {
{ mac_cmd_in_next_tx = true;
MacCommandsInNextTx = true;
} }
return status; return status;
} }
void LoRaMacCommand::ClearCommandBuffer() void LoRaMacCommand::clear_command_buffer()
{ {
MacCommandsBufferIndex = 0; mac_cmd_buf_idx = 0;
} }
uint8_t LoRaMacCommand::GetLength() const uint8_t LoRaMacCommand::get_mac_cmd_length() const
{ {
return MacCommandsBufferIndex; return mac_cmd_buf_idx;
} }
uint8_t *LoRaMacCommand::GetMacCommandsBuffer() uint8_t *LoRaMacCommand::get_mac_commands_buffer()
{ {
return MacCommandsBuffer; return mac_cmd_buffer;
} }
void LoRaMacCommand::ParseMacCommandsToRepeat() void LoRaMacCommand::parse_mac_commands_to_repeat()
{ {
uint8_t i = 0; uint8_t i = 0;
uint8_t cmdCount = 0; uint8_t cmd_cnt = 0;
for( i = 0; i < MacCommandsBufferIndex; i++ ) for (i = 0; i < mac_cmd_buf_idx; i++) {
{ switch (mac_cmd_buffer[i]) {
switch( MacCommandsBuffer[i] )
{
// STICKY // STICKY
case MOTE_MAC_DL_CHANNEL_ANS: case MOTE_MAC_DL_CHANNEL_ANS:
case MOTE_MAC_RX_PARAM_SETUP_ANS: case MOTE_MAC_RX_PARAM_SETUP_ANS: { // 1 byte payload
{ // 1 byte payload mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i++];
MacCommandsBufferToRepeat[cmdCount++] = MacCommandsBuffer[i++]; mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i];
MacCommandsBufferToRepeat[cmdCount++] = MacCommandsBuffer[i];
break; break;
} }
case MOTE_MAC_RX_TIMING_SETUP_ANS: case MOTE_MAC_RX_TIMING_SETUP_ANS: { // 0 byte payload
{ // 0 byte payload mac_cmd_buffer_to_repeat[cmd_cnt++] = mac_cmd_buffer[i];
MacCommandsBufferToRepeat[cmdCount++] = MacCommandsBuffer[i];
break; break;
} }
// NON-STICKY // NON-STICKY
case MOTE_MAC_DEV_STATUS_ANS: case MOTE_MAC_DEV_STATUS_ANS: { // 2 bytes payload
{ // 2 bytes payload
i += 2; i += 2;
break; break;
} }
case MOTE_MAC_LINK_ADR_ANS: case MOTE_MAC_LINK_ADR_ANS:
case MOTE_MAC_NEW_CHANNEL_ANS: case MOTE_MAC_NEW_CHANNEL_ANS: { // 1 byte payload
{ // 1 byte payload
i++; i++;
break; break;
} }
case MOTE_MAC_TX_PARAM_SETUP_ANS: case MOTE_MAC_TX_PARAM_SETUP_ANS:
case MOTE_MAC_DUTY_CYCLE_ANS: case MOTE_MAC_DUTY_CYCLE_ANS:
case MOTE_MAC_LINK_CHECK_REQ: case MOTE_MAC_LINK_CHECK_REQ: { // 0 byte payload
{ // 0 byte payload
break; break;
} }
default: default:
@ -217,213 +201,210 @@ void LoRaMacCommand::ParseMacCommandsToRepeat()
} }
} }
if( cmdCount > 0 ) { if (cmd_cnt > 0) {
MacCommandsInNextTx = true; mac_cmd_in_next_tx = true;
} else { } else {
MacCommandsInNextTx = false; mac_cmd_in_next_tx = false;
} }
} }
void LoRaMacCommand::ClearRepeatBuffer() void LoRaMacCommand::clear_repeat_buffer()
{ {
MacCommandsBufferToRepeatIndex = 0; mac_cmd_buf_idx_to_repeat = 0;
} }
void LoRaMacCommand::CopyRepeatCommandsToBuffer() void LoRaMacCommand::copy_repeat_commands_to_buffer()
{ {
// Copy the MAC commands which must be re-send into the MAC command buffer // Copy the MAC commands which must be re-send into the MAC command buffer
memcpy(&MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex); memcpy(&mac_cmd_buffer[mac_cmd_buf_idx], mac_cmd_buffer_to_repeat, mac_cmd_buf_idx_to_repeat);
MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex; mac_cmd_buf_idx += mac_cmd_buf_idx_to_repeat;
} }
uint8_t LoRaMacCommand::GetRepeatLength() const uint8_t LoRaMacCommand::get_repeat_commands_length() const
{ {
return MacCommandsBufferToRepeatIndex; return mac_cmd_buf_idx_to_repeat;
} }
void LoRaMacCommand::ClearMacCommandsInNextTx() void LoRaMacCommand::clear_mac_commands_in_next_tx()
{ {
MacCommandsInNextTx = false; mac_cmd_in_next_tx = false;
} }
bool LoRaMacCommand::IsMacCommandsInNextTx() const bool LoRaMacCommand::is_mac_command_in_next_tx() const
{ {
return MacCommandsInNextTx; return mac_cmd_in_next_tx;
} }
lorawan_status_t LoRaMacCommand::ProcessMacCommands(uint8_t *payload, uint8_t macIndex, lorawan_status_t LoRaMacCommand::process_mac_commands(uint8_t *payload,
uint8_t commandsSize, uint8_t snr, uint8_t mac_index,
loramac_mlme_confirm_t& MlmeConfirm, uint8_t commands_size,
lora_mac_system_params_t &LoRaMacParams, uint8_t snr,
LoRaPHY &lora_phy) loramac_mlme_confirm_t& mlme_conf,
lora_mac_system_params_t &mac_sys_params,
LoRaPHY &lora_phy)
{ {
uint8_t status = 0; uint8_t status = 0;
lorawan_status_t ret_value = LORAWAN_STATUS_OK; lorawan_status_t ret_value = LORAWAN_STATUS_OK;
while( macIndex < commandsSize ) while (mac_index < commands_size) {
{
// Decode Frame MAC commands // Decode Frame MAC commands
switch( payload[macIndex++] ) switch (payload[mac_index++]) {
{
case SRV_MAC_LINK_CHECK_ANS: case SRV_MAC_LINK_CHECK_ANS:
MlmeConfirm.status = LORAMAC_EVENT_INFO_STATUS_OK; mlme_conf.status = LORAMAC_EVENT_INFO_STATUS_OK;
MlmeConfirm.demod_margin = payload[macIndex++]; mlme_conf.demod_margin = payload[mac_index++];
MlmeConfirm.nb_gateways = payload[macIndex++]; mlme_conf.nb_gateways = payload[mac_index++];
break; break;
case SRV_MAC_LINK_ADR_REQ: case SRV_MAC_LINK_ADR_REQ: {
{ adr_req_params_t linkAdrReq;
adr_req_params_t linkAdrReq; int8_t linkAdrDatarate = DR_0;
int8_t linkAdrDatarate = DR_0; int8_t linkAdrTxPower = TX_POWER_0;
int8_t linkAdrTxPower = TX_POWER_0; uint8_t linkAdrNbRep = 0;
uint8_t linkAdrNbRep = 0; uint8_t linkAdrNbBytesParsed = 0;
uint8_t linkAdrNbBytesParsed = 0;
// Fill parameter structure // Fill parameter structure
linkAdrReq.payload = &payload[macIndex - 1]; linkAdrReq.payload = &payload[mac_index - 1];
linkAdrReq.payload_size = commandsSize - ( macIndex - 1 ); linkAdrReq.payload_size = commands_size - (mac_index - 1);
linkAdrReq.adr_enabled = LoRaMacParams.adr_on; linkAdrReq.adr_enabled = mac_sys_params.adr_on;
linkAdrReq.ul_dwell_time = LoRaMacParams.uplink_dwell_time; linkAdrReq.ul_dwell_time = mac_sys_params.uplink_dwell_time;
linkAdrReq.current_datarate = LoRaMacParams.channel_data_rate; linkAdrReq.current_datarate = mac_sys_params.channel_data_rate;
linkAdrReq.current_tx_power = LoRaMacParams.channel_tx_power; linkAdrReq.current_tx_power = mac_sys_params.channel_tx_power;
linkAdrReq.current_nb_rep = LoRaMacParams.retry_num; linkAdrReq.current_nb_rep = mac_sys_params.retry_num;
// Process the ADR requests // Process the ADR requests
status = lora_phy.link_ADR_request(&linkAdrReq, &linkAdrDatarate, status = lora_phy.link_ADR_request(&linkAdrReq,
&linkAdrTxPower, &linkAdrNbRep, &linkAdrDatarate,
&linkAdrNbBytesParsed); &linkAdrTxPower,
&linkAdrNbRep,
&linkAdrNbBytesParsed);
if( ( status & 0x07 ) == 0x07 ) if ((status & 0x07) == 0x07) {
{ mac_sys_params.channel_data_rate = linkAdrDatarate;
LoRaMacParams.channel_data_rate = linkAdrDatarate; mac_sys_params.channel_tx_power = linkAdrTxPower;
LoRaMacParams.channel_tx_power = linkAdrTxPower; mac_sys_params.retry_num = linkAdrNbRep;
LoRaMacParams.retry_num = linkAdrNbRep;
}
// Add the answers to the buffer
for( uint8_t i = 0; i < ( linkAdrNbBytesParsed / 5 ); i++ )
{
ret_value = AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
}
// Update MAC index
macIndex += linkAdrNbBytesParsed - 1;
} }
// Add the answers to the buffer
for (uint8_t i = 0; i < (linkAdrNbBytesParsed / 5); i++) {
ret_value = add_mac_command(MOTE_MAC_LINK_ADR_ANS, status, 0);
}
// Update MAC index
mac_index += linkAdrNbBytesParsed - 1;
}
break; break;
case SRV_MAC_DUTY_CYCLE_REQ: case SRV_MAC_DUTY_CYCLE_REQ:
LoRaMacParams.max_duty_cycle = payload[macIndex++]; mac_sys_params.max_duty_cycle = payload[mac_index++];
LoRaMacParams.aggregated_duty_cycle = 1 << LoRaMacParams.max_duty_cycle; mac_sys_params.aggregated_duty_cycle = 1 << mac_sys_params.max_duty_cycle;
ret_value = AddMacCommand( MOTE_MAC_DUTY_CYCLE_ANS, 0, 0 ); ret_value = add_mac_command(MOTE_MAC_DUTY_CYCLE_ANS, 0, 0);
break; break;
case SRV_MAC_RX_PARAM_SETUP_REQ: case SRV_MAC_RX_PARAM_SETUP_REQ: {
{ rx_param_setup_req_t rxParamSetupReq;
rx_param_setup_req_t rxParamSetupReq;
rxParamSetupReq.dr_offset = ( payload[macIndex] >> 4 ) & 0x07; rxParamSetupReq.dr_offset = (payload[mac_index] >> 4) & 0x07;
rxParamSetupReq.datarate = payload[macIndex] & 0x0F; rxParamSetupReq.datarate = payload[mac_index] & 0x0F;
macIndex++; mac_index++;
rxParamSetupReq.frequency = ( uint32_t )payload[macIndex++]; rxParamSetupReq.frequency = (uint32_t) payload[mac_index++];
rxParamSetupReq.frequency |= ( uint32_t )payload[macIndex++] << 8; rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++]
rxParamSetupReq.frequency |= ( uint32_t )payload[macIndex++] << 16; << 8;
rxParamSetupReq.frequency *= 100; rxParamSetupReq.frequency |= (uint32_t) payload[mac_index++]
<< 16;
rxParamSetupReq.frequency *= 100;
// Perform request on region // Perform request on region
status = lora_phy.accept_rx_param_setup_req(&rxParamSetupReq); status = lora_phy.accept_rx_param_setup_req(&rxParamSetupReq);
if( ( status & 0x07 ) == 0x07 ) if ((status & 0x07) == 0x07) {
{ mac_sys_params.rx2_channel.datarate =
LoRaMacParams.rx2_channel.datarate = rxParamSetupReq.datarate; rxParamSetupReq.datarate;
LoRaMacParams.rx2_channel.frequency = rxParamSetupReq.frequency; mac_sys_params.rx2_channel.frequency =
LoRaMacParams.rx1_dr_offset = rxParamSetupReq.dr_offset; rxParamSetupReq.frequency;
} mac_sys_params.rx1_dr_offset = rxParamSetupReq.dr_offset;
ret_value = AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 );
} }
ret_value = add_mac_command(MOTE_MAC_RX_PARAM_SETUP_ANS, status,
0);
}
break; break;
case SRV_MAC_DEV_STATUS_REQ: case SRV_MAC_DEV_STATUS_REQ: {
{ uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE;
uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE; // we don't have a mechanism at the moment to measure
// we don't have a mechanism at the moment to measure // battery levels
// battery levels ret_value = add_mac_command(MOTE_MAC_DEV_STATUS_ANS,
ret_value = AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr ); batteryLevel, snr);
break;
}
case SRV_MAC_NEW_CHANNEL_REQ:
{
new_channel_req_params_t newChannelReq;
channel_params_t chParam;
newChannelReq.channel_id = payload[macIndex++];
newChannelReq.new_channel = &chParam;
chParam.frequency = ( uint32_t )payload[macIndex++];
chParam.frequency |= ( uint32_t )payload[macIndex++] << 8;
chParam.frequency |= ( uint32_t )payload[macIndex++] << 16;
chParam.frequency *= 100;
chParam.rx1_frequency = 0;
chParam.dr_range.value = payload[macIndex++];
status = lora_phy.request_new_channel(&newChannelReq);
ret_value = AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
}
break; break;
case SRV_MAC_RX_TIMING_SETUP_REQ: }
{ case SRV_MAC_NEW_CHANNEL_REQ: {
uint8_t delay = payload[macIndex++] & 0x0F; new_channel_req_params_t newChannelReq;
channel_params_t chParam;
if( delay == 0 ) newChannelReq.channel_id = payload[mac_index++];
{ newChannelReq.new_channel = &chParam;
delay++;
} chParam.frequency = (uint32_t) payload[mac_index++];
LoRaMacParams.recv_delay1 = delay * 1000; chParam.frequency |= (uint32_t) payload[mac_index++] << 8;
LoRaMacParams.recv_delay2 = LoRaMacParams.recv_delay1 + 1000; chParam.frequency |= (uint32_t) payload[mac_index++] << 16;
ret_value = AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 ); chParam.frequency *= 100;
} chParam.rx1_frequency = 0;
chParam.dr_range.value = payload[mac_index++];
status = lora_phy.request_new_channel(&newChannelReq);
ret_value = add_mac_command(MOTE_MAC_NEW_CHANNEL_ANS, status, 0);
}
break; break;
case SRV_MAC_TX_PARAM_SETUP_REQ: case SRV_MAC_RX_TIMING_SETUP_REQ: {
{ uint8_t delay = payload[mac_index++] & 0x0F;
tx_param_setup_req_t txParamSetupReq;
uint8_t eirpDwellTime = payload[macIndex++];
txParamSetupReq.ul_dwell_time = 0; if (delay == 0) {
txParamSetupReq.dl_dwell_time = 0; delay++;
if( ( eirpDwellTime & 0x20 ) == 0x20 )
{
txParamSetupReq.dl_dwell_time = 1;
}
if( ( eirpDwellTime & 0x10 ) == 0x10 )
{
txParamSetupReq.ul_dwell_time = 1;
}
txParamSetupReq.max_eirp = eirpDwellTime & 0x0F;
// Check the status for correctness
if(lora_phy.accept_tx_param_setup_req(&txParamSetupReq))
{
// Accept command
LoRaMacParams.uplink_dwell_time = txParamSetupReq.ul_dwell_time;
LoRaMacParams.downlink_dwell_time = txParamSetupReq.dl_dwell_time;
LoRaMacParams.max_eirp = LoRaMacMaxEirpTable[txParamSetupReq.max_eirp];
// Add command response
ret_value = AddMacCommand( MOTE_MAC_TX_PARAM_SETUP_ANS, 0, 0 );
}
} }
mac_sys_params.recv_delay1 = delay * 1000;
mac_sys_params.recv_delay2 = mac_sys_params.recv_delay1 + 1000;
ret_value = add_mac_command(MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0);
}
break; break;
case SRV_MAC_DL_CHANNEL_REQ: case SRV_MAC_TX_PARAM_SETUP_REQ: {
{ tx_param_setup_req_t txParamSetupReq;
dl_channel_req_params_t dlChannelReq; uint8_t eirpDwellTime = payload[mac_index++];
dlChannelReq.channel_id = payload[macIndex++]; txParamSetupReq.ul_dwell_time = 0;
dlChannelReq.rx1_frequency = ( uint32_t )payload[macIndex++]; txParamSetupReq.dl_dwell_time = 0;
dlChannelReq.rx1_frequency |= ( uint32_t )payload[macIndex++] << 8;
dlChannelReq.rx1_frequency |= ( uint32_t )payload[macIndex++] << 16;
dlChannelReq.rx1_frequency *= 100;
status = lora_phy.dl_channel_request(&dlChannelReq); if ((eirpDwellTime & 0x20) == 0x20) {
txParamSetupReq.dl_dwell_time = 1;
ret_value = AddMacCommand( MOTE_MAC_DL_CHANNEL_ANS, status, 0 );
} }
if ((eirpDwellTime & 0x10) == 0x10) {
txParamSetupReq.ul_dwell_time = 1;
}
txParamSetupReq.max_eirp = eirpDwellTime & 0x0F;
// Check the status for correctness
if (lora_phy.accept_tx_param_setup_req(&txParamSetupReq)) {
// Accept command
mac_sys_params.uplink_dwell_time =
txParamSetupReq.ul_dwell_time;
mac_sys_params.downlink_dwell_time =
txParamSetupReq.dl_dwell_time;
mac_sys_params.max_eirp =
max_eirp_table[txParamSetupReq.max_eirp];
// Add command response
ret_value = add_mac_command(MOTE_MAC_TX_PARAM_SETUP_ANS, 0, 0);
}
}
break;
case SRV_MAC_DL_CHANNEL_REQ: {
dl_channel_req_params_t dlChannelReq;
dlChannelReq.channel_id = payload[mac_index++];
dlChannelReq.rx1_frequency = (uint32_t) payload[mac_index++];
dlChannelReq.rx1_frequency |= (uint32_t) payload[mac_index++] << 8;
dlChannelReq.rx1_frequency |= (uint32_t) payload[mac_index++] << 16;
dlChannelReq.rx1_frequency *= 100;
status = lora_phy.dl_channel_request(&dlChannelReq);
ret_value = add_mac_command(MOTE_MAC_DL_CHANNEL_ANS, status, 0);
}
break; break;
default: default:
// Unknown command. ABORT MAC commands processing // Unknown command. ABORT MAC commands processing
@ -433,10 +414,9 @@ lorawan_status_t LoRaMacCommand::ProcessMacCommands(uint8_t *payload, uint8_t ma
return ret_value; return ret_value;
} }
bool LoRaMacCommand::IsStickyMacCommandPending() bool LoRaMacCommand::is_sticky_mac_command_pending()
{ {
if( MacCommandsBufferToRepeatIndex > 0 ) if (mac_cmd_buf_idx_to_repeat > 0) {
{
// Sticky MAC commands pending // Sticky MAC commands pending
return true; return true;
} }

View File

@ -51,129 +51,130 @@
class LoRaMac; class LoRaMac;
class LoRaMacCommand class LoRaMacCommand {
{
public: public:
LoRaMacCommand(LoRaMac &lora_mac); LoRaMacCommand(LoRaMac &lora_mac);
~LoRaMacCommand(); ~LoRaMacCommand();
/*! /**
* \brief Adds a new MAC command to be sent. * @brief Adds a new MAC command to be sent.
* *
* \remark MAC layer internal function * @remark MAC layer internal function
* *
* \param [in] cmd MAC command to be added * @param [in] cmd MAC command to be added
* [MOTE_MAC_LINK_CHECK_REQ, * [MOTE_MAC_LINK_CHECK_REQ,
* MOTE_MAC_LINK_ADR_ANS, * MOTE_MAC_LINK_ADR_ANS,
* MOTE_MAC_DUTY_CYCLE_ANS, * MOTE_MAC_DUTY_CYCLE_ANS,
* MOTE_MAC_RX2_PARAM_SET_ANS, * MOTE_MAC_RX2_PARAM_SET_ANS,
* MOTE_MAC_DEV_STATUS_ANS * MOTE_MAC_DEV_STATUS_ANS
* MOTE_MAC_NEW_CHANNEL_ANS] * MOTE_MAC_NEW_CHANNEL_ANS]
* \param [in] p1 1st parameter ( optional depends on the command ) * @param [in] p1 1st parameter (optional depends on the command)
* \param [in] p2 2nd parameter ( optional depends on the command ) * @param [in] p2 2nd parameter (optional depends on the command)
* *
* \retval status Function status [0: OK, 1: Unknown command, 2: Buffer full] * @return status Function status [0: OK, 1: Unknown command, 2: Buffer full]
*/ */
lorawan_status_t AddMacCommand(uint8_t cmd, uint8_t p1, uint8_t p2); lorawan_status_t add_mac_command(uint8_t cmd, uint8_t p1, uint8_t p2);
/*! /**
* \brief Clear MAC command buffer. * @brief Clear MAC command buffer.
*/ */
void ClearCommandBuffer(); void clear_command_buffer(void);
/*! /**
* \brief Get the length of MAC commands * @brief Get the length of MAC commands
* *
* \retval status Length of used MAC buffer (bytes) * @return status Length of used MAC buffer (bytes)
*/ */
uint8_t GetLength() const; uint8_t get_mac_cmd_length() const;
/*! /**
* \brief Get MAC command buffer * @brief Get MAC command buffer
* *
* \retval Pointer to MAC command buffer * @return Pointer to MAC command buffer
*/ */
uint8_t *GetMacCommandsBuffer(); uint8_t *get_mac_commands_buffer();
/*! /**
* \brief Parses the MAC commands which must be resent. * @brief Parses the MAC commands which must be resent.
*/ */
void ParseMacCommandsToRepeat(); void parse_mac_commands_to_repeat();
/*! /**
* \brief Clear MAC command repeat buffer. * @brief Clear MAC command repeat buffer.
*/ */
void ClearRepeatBuffer(); void clear_repeat_buffer();
/*! /**
* \brief Copy MAC commands from repeat buffer to actual MAC command buffer. * @brief Copy MAC commands from repeat buffer to actual MAC command buffer.
*/ */
void CopyRepeatCommandsToBuffer(); void copy_repeat_commands_to_buffer();
/*! /**
* \brief Get the length of MAC commands in repeat buffer * @brief Get the length of MAC commands in repeat buffer
* *
* \retval status Length of used MAC Repeat buffer (bytes) * @return status Length of used MAC Repeat buffer (bytes)
*/ */
uint8_t GetRepeatLength() const; uint8_t get_repeat_commands_length() const;
/*! /**
* \brief Clear MAC commands in next TX. * @brief Clear MAC commands in next TX.
*/ */
void ClearMacCommandsInNextTx(); void clear_mac_commands_in_next_tx();
/*! /**
* \brief Check if MAC command buffer has commands to be sent in next TX * @brief Check if MAC command buffer has commands to be sent in next TX
* *
* \retval status True: buffer has MAC commands to be sent, false: no commands in buffer] * @return status True: buffer has MAC commands to be sent, false: no commands in buffer]
*/ */
bool IsMacCommandsInNextTx() const; bool is_mac_command_in_next_tx() const;
/*! /**
* \brief Decodes MAC commands in the fOpts field and in the payload * @brief Decodes MAC commands in the fOpts field and in the payload
* \retval status Function status. LORAWAN_STATUS_OK if command successful.
*/
lorawan_status_t ProcessMacCommands(uint8_t *payload, uint8_t macIndex,
uint8_t commandsSize, uint8_t snr,
loramac_mlme_confirm_t& MlmeConfirm,
lora_mac_system_params_t& LoRaMacParams,
LoRaPHY& lora_phy);
/*!
* \brief Verifies if sticky MAC commands are pending.
* *
* \retval [true: sticky MAC commands pending, false: No MAC commands pending] * @return status Function status. LORAWAN_STATUS_OK if command successful.
*/ */
bool IsStickyMacCommandPending(); lorawan_status_t process_mac_commands(uint8_t *payload, uint8_t mac_index,
uint8_t commands_size, uint8_t snr,
loramac_mlme_confirm_t& mlme_conf,
lora_mac_system_params_t& mac_params,
LoRaPHY& lora_phy);
/**
* @brief Verifies if sticky MAC commands are pending.
*
* @return [true: sticky MAC commands pending, false: No MAC commands pending]
*/
bool is_sticky_mac_command_pending();
private: private:
LoRaMac& _lora_mac; LoRaMac& _lora_mac;
/*! /**
* Indicates if the MAC layer wants to send MAC commands * Indicates if the MAC layer wants to send MAC commands
*/ */
bool MacCommandsInNextTx; bool mac_cmd_in_next_tx;
/*! /**
* Contains the current MacCommandsBuffer index * Contains the current Mac command buffer index in 'mac_cmd_buffer'
*/ */
uint8_t MacCommandsBufferIndex; uint8_t mac_cmd_buf_idx;
/*! /**
* Contains the current MacCommandsBuffer index for MAC commands to repeat * Contains the current Mac command buffer index for MAC commands to repeat in
* 'mac_cmd_buffer_to_repeat'
*/ */
uint8_t MacCommandsBufferToRepeatIndex; uint8_t mac_cmd_buf_idx_to_repeat;
/*! /**
* Buffer containing the MAC layer commands * Buffer containing the MAC layer commands
*/ */
uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH]; uint8_t mac_cmd_buffer[LORA_MAC_COMMAND_MAX_LENGTH];
/*! /**
* Buffer containing the MAC layer commands which must be repeated * Buffer containing the MAC layer commands which must be repeated
*/ */
uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH]; uint8_t mac_cmd_buffer_to_repeat[LORA_MAC_COMMAND_MAX_LENGTH];
}; };
#endif //__LORAMACCOMMAND_H__ #endif //__LORAMACCOMMAND_H__

View File

@ -41,251 +41,253 @@
/** /**
* MIC field computation initial data * MIC field computation initial data
*/ */
static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, static uint8_t mic_block_b0[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
};
/** /**
* Contains the computed MIC field. * Contains the computed MIC field.
* *
* \remark Only the 4 first bytes are used * \remark Only the 4 first bytes are used
*/ */
static uint8_t Mic[16]; static uint8_t computed_mic[16];
/** /**
* Encryption aBlock and sBlock * Encryption aBlock and sBlock
*/ */
static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, static uint8_t a_block[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
};
static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, static uint8_t s_block[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
};
/** /**
* AES computation context variable * AES computation context variable
*/ */
static mbedtls_aes_context AesContext; static mbedtls_aes_context aes_ctx;
/** /**
* CMAC computation context variable * CMAC computation context variable
*/ */
static mbedtls_cipher_context_t AesCmacCtx[1]; static mbedtls_cipher_context_t aes_cmac_ctx[1];
#define AES_CMAC_KEY_LENGTH 16 #define AES_CMAC_KEY_LENGTH 16
/** int compute_mic(const uint8_t *buffer, uint16_t size, const uint8_t *key,
* \brief Computes the LoRaMAC frame MIC field uint32_t address, uint8_t dir, uint32_t seq_counter,
* uint32_t *mic)
* \param [in] buffer Data buffer
* \param [in] size Data buffer size
* \param [in] key AES key to be used
* \param [in] address Frame address
* \param [in] dir Frame direction [0: uplink, 1: downlink]
* \param [in] sequenceCounter Frame sequence counter
* \param [out] mic Computed MIC field
*/
int LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic )
{ {
int ret = 0; int ret = 0;
MicBlockB0[5] = dir; mic_block_b0[5] = dir;
MicBlockB0[6] = ( address ) & 0xFF; mic_block_b0[6] = (address) & 0xFF;
MicBlockB0[7] = ( address >> 8 ) & 0xFF; mic_block_b0[7] = (address >> 8) & 0xFF;
MicBlockB0[8] = ( address >> 16 ) & 0xFF; mic_block_b0[8] = (address >> 16) & 0xFF;
MicBlockB0[9] = ( address >> 24 ) & 0xFF; mic_block_b0[9] = (address >> 24) & 0xFF;
MicBlockB0[10] = ( sequenceCounter ) & 0xFF; mic_block_b0[10] = (seq_counter) & 0xFF;
MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF; mic_block_b0[11] = (seq_counter >> 8) & 0xFF;
MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF; mic_block_b0[12] = (seq_counter >> 16) & 0xFF;
MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF; mic_block_b0[13] = (seq_counter >> 24) & 0xFF;
MicBlockB0[15] = size & 0xFF; mic_block_b0[15] = size & 0xFF;
mbedtls_cipher_init(aes_cmac_ctx);
mbedtls_cipher_init(AesCmacCtx);
const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
if (NULL != cipher_info) { if (NULL != cipher_info) {
ret = mbedtls_cipher_setup(AesCmacCtx, cipher_info); ret = mbedtls_cipher_setup(aes_cmac_ctx, cipher_info);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_starts(AesCmacCtx, key, AES_CMAC_KEY_LENGTH*8); ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key,
AES_CMAC_KEY_LENGTH * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_update(AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE); ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, mic_block_b0,
LORAMAC_MIC_BLOCK_B0_SIZE);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_update(AesCmacCtx, buffer, size & 0xFF); ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, buffer, size & 0xFF);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_finish(AesCmacCtx, Mic); ret = mbedtls_cipher_cmac_finish(aes_cmac_ctx, computed_mic);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
*mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] ); *mic = (uint32_t) ((uint32_t) computed_mic[3] << 24
| (uint32_t) computed_mic[2] << 16
| (uint32_t) computed_mic[1] << 8 | (uint32_t) computed_mic[0]);
} else { } else {
ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED; ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
} }
exit: exit: mbedtls_cipher_free(aes_cmac_ctx);
mbedtls_cipher_free( AesCmacCtx );
return ret; return ret;
} }
int LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer ) int encrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *enc_buffer)
{ {
uint16_t i; uint16_t i;
uint8_t bufferIndex = 0; uint8_t bufferIndex = 0;
uint16_t ctr = 1; uint16_t ctr = 1;
int ret = 0; int ret = 0;
mbedtls_aes_init(&AesContext); mbedtls_aes_init(&aes_ctx);
ret = mbedtls_aes_setkey_enc(&AesContext, key, 16*8); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
aBlock[5] = dir; a_block[5] = dir;
aBlock[6] = ( address ) & 0xFF; a_block[6] = (address) & 0xFF;
aBlock[7] = ( address >> 8 ) & 0xFF; a_block[7] = (address >> 8) & 0xFF;
aBlock[8] = ( address >> 16 ) & 0xFF; a_block[8] = (address >> 16) & 0xFF;
aBlock[9] = ( address >> 24 ) & 0xFF; a_block[9] = (address >> 24) & 0xFF;
aBlock[10] = ( sequenceCounter ) & 0xFF; a_block[10] = (seq_counter) & 0xFF;
aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF; a_block[11] = (seq_counter >> 8) & 0xFF;
aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF; a_block[12] = (seq_counter >> 16) & 0xFF;
aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF; a_block[13] = (seq_counter >> 24) & 0xFF;
while( size >= 16 ) while (size >= 16) {
{ a_block[15] = ((ctr) & 0xFF);
aBlock[15] = ( ( ctr ) & 0xFF );
ctr++; ctr++;
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, aBlock, sBlock); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, a_block,
s_block);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
for( i = 0; i < 16; i++ ) for (i = 0; i < 16; i++) {
{ enc_buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ s_block[i];
encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
} }
size -= 16; size -= 16;
bufferIndex += 16; bufferIndex += 16;
} }
if( size > 0 ) if (size > 0) {
{ a_block[15] = ((ctr) & 0xFF);
aBlock[15] = ( ( ctr ) & 0xFF ); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, a_block,
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, aBlock, sBlock); s_block);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
for( i = 0; i < size; i++ ) for (i = 0; i < size; i++) {
{ enc_buffer[bufferIndex + i] = buffer[bufferIndex + i] ^ s_block[i];
encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i];
} }
} }
exit: exit: mbedtls_aes_free(&aes_ctx);
mbedtls_aes_free(&AesContext);
return ret; return ret;
} }
int LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer ) int decrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *dec_buffer)
{ {
return LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer ); return encrypt_payload(buffer, size, key, address, dir, seq_counter,
dec_buffer);
} }
int LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic ) int compute_join_frame_mic(const uint8_t *buffer, uint16_t size,
const uint8_t *key, uint32_t *mic)
{ {
int ret = 0; int ret = 0;
mbedtls_cipher_init(AesCmacCtx); mbedtls_cipher_init(aes_cmac_ctx);
const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB); const mbedtls_cipher_info_t* cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
if (NULL != cipher_info) { if (NULL != cipher_info) {
ret = mbedtls_cipher_setup(AesCmacCtx, cipher_info); ret = mbedtls_cipher_setup(aes_cmac_ctx, cipher_info);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_starts(AesCmacCtx, key, AES_CMAC_KEY_LENGTH*8); ret = mbedtls_cipher_cmac_starts(aes_cmac_ctx, key,
AES_CMAC_KEY_LENGTH * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_update(AesCmacCtx, buffer, size & 0xFF); ret = mbedtls_cipher_cmac_update(aes_cmac_ctx, buffer, size & 0xFF);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_cipher_cmac_finish(AesCmacCtx, Mic); ret = mbedtls_cipher_cmac_finish(aes_cmac_ctx, computed_mic);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
*mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] ); *mic = (uint32_t) ((uint32_t) computed_mic[3] << 24
| (uint32_t) computed_mic[2] << 16
| (uint32_t) computed_mic[1] << 8 | (uint32_t) computed_mic[0]);
} else { } else {
ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED; ret = MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
} }
exit: exit: mbedtls_cipher_free(aes_cmac_ctx);
mbedtls_cipher_free(AesCmacCtx);
return ret; return ret;
} }
int LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer ) int decrypt_join_frame(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint8_t *dec_buffer)
{ {
int ret = 0; int ret = 0;
mbedtls_aes_init(&AesContext); mbedtls_aes_init(&aes_ctx);
ret = mbedtls_aes_setkey_enc(&AesContext, key, 16*8); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, buffer, decBuffer); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, buffer,
dec_buffer);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
// Check if optional CFList is included // Check if optional CFList is included
if( size >= 16 ) if (size >= 16) {
{ ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, buffer + 16,
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, buffer + 16, decBuffer + 16); dec_buffer + 16);
} }
exit: exit: mbedtls_aes_free(&aes_ctx);
mbedtls_aes_free(&AesContext);
return ret; return ret;
} }
int LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey ) int compute_skeys_for_join_frame(const uint8_t *key, const uint8_t *app_nonce,
uint16_t dev_nonce, uint8_t *nwk_skey,
uint8_t *app_skey)
{ {
uint8_t nonce[16]; uint8_t nonce[16];
uint8_t *pDevNonce = ( uint8_t * )&devNonce; uint8_t *p_dev_nonce = (uint8_t *) &dev_nonce;
int ret = 0; int ret = 0;
mbedtls_aes_init(&AesContext); mbedtls_aes_init(&aes_ctx);
ret = mbedtls_aes_setkey_enc(&AesContext, key, 16*8); ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 16 * 8);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
memset( nonce, 0, sizeof( nonce ) ); memset(nonce, 0, sizeof(nonce));
nonce[0] = 0x01; nonce[0] = 0x01;
memcpy( nonce + 1, appNonce, 6 ); memcpy(nonce + 1, app_nonce, 6);
memcpy( nonce + 7, pDevNonce, 2 ); memcpy(nonce + 7, p_dev_nonce, 2);
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, nonce, nwkSKey); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, nonce, nwk_skey);
if (0 != ret) if (0 != ret)
goto exit; goto exit;
memset( nonce, 0, sizeof( nonce ) ); memset(nonce, 0, sizeof(nonce));
nonce[0] = 0x02; nonce[0] = 0x02;
memcpy( nonce + 1, appNonce, 6 ); memcpy(nonce + 1, app_nonce, 6);
memcpy( nonce + 7, pDevNonce, 2 ); memcpy(nonce + 7, p_dev_nonce, 2);
ret = mbedtls_aes_crypt_ecb(&AesContext, MBEDTLS_AES_ENCRYPT, nonce, appSKey); ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, nonce, app_skey);
exit: exit: mbedtls_aes_free(&aes_ctx);
mbedtls_aes_free(&AesContext);
return ret; return ret;
} }
#else #else
@ -294,8 +296,8 @@ exit:
// user knows what is wrong and in addition to that these ensure that // user knows what is wrong and in addition to that these ensure that
// Mbed-OS compiles properly under normal conditions where LoRaWAN in conjunction // Mbed-OS compiles properly under normal conditions where LoRaWAN in conjunction
// with mbedTLS is not being used. // with mbedTLS is not being used.
int LoRaMacComputeMic( const uint8_t *, uint16_t , const uint8_t *, uint32_t, int compute_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
uint8_t dir, uint32_t, uint32_t * ) uint8_t dir, uint32_t, uint32_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
@ -303,8 +305,8 @@ int LoRaMacComputeMic( const uint8_t *, uint16_t , const uint8_t *, uint32_t,
return LORAWAN_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int LoRaMacPayloadEncrypt( const uint8_t *, uint16_t , const uint8_t *, uint32_t, int encrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
uint8_t , uint32_t , uint8_t * ) uint8_t , uint32_t , uint8_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
@ -312,15 +314,8 @@ int LoRaMacPayloadEncrypt( const uint8_t *, uint16_t , const uint8_t *, uint32_t
return LORAWAN_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int LoRaMacPayloadDecrypt( const uint8_t *, uint16_t , const uint8_t *, uint32_t, int decrypt_payload(const uint8_t *, uint16_t , const uint8_t *, uint32_t,
uint8_t , uint32_t , uint8_t * ) uint8_t , uint32_t , uint8_t *)
{
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
// Never actually reaches here
return LORAWAN_STATUS_CRYPTO_FAIL;
}
int LoRaMacJoinComputeMic( const uint8_t *, uint16_t , const uint8_t *, uint32_t * )
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
@ -328,7 +323,7 @@ int LoRaMacJoinComputeMic( const uint8_t *, uint16_t , const uint8_t *, uint32_t
return LORAWAN_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int LoRaMacJoinDecrypt( const uint8_t *, uint16_t , const uint8_t *, uint8_t * ) int compute_join_frame_mic(const uint8_t *, uint16_t , const uint8_t *, uint32_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
@ -336,7 +331,16 @@ int LoRaMacJoinDecrypt( const uint8_t *, uint16_t , const uint8_t *, uint8_t * )
return LORAWAN_STATUS_CRYPTO_FAIL; return LORAWAN_STATUS_CRYPTO_FAIL;
} }
int LoRaMacJoinComputeSKeys( const uint8_t *, const uint8_t *, uint16_t , uint8_t *, uint8_t * ) int decrypt_join_frame(const uint8_t *, uint16_t , const uint8_t *, uint8_t *)
{
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");
// Never actually reaches here
return LORAWAN_STATUS_CRYPTO_FAIL;
}
int compute_skeys_for_join_frame(const uint8_t *, const uint8_t *, uint16_t ,
uint8_t *, uint8_t *)
{ {
MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS"); MBED_ASSERT("[LoRaCrypto] Must enable AES, CMAC & CIPHER from mbedTLS");

View File

@ -29,84 +29,94 @@ SPDX-License-Identifier: BSD-3-Clause
/** /**
* Computes the LoRaMAC frame MIC field * Computes the LoRaMAC frame MIC field
* *
* \param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* \param [in] size - Data buffer size * @param [in] size - Data buffer size
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [in] address - Frame address * @param [in] address - Frame address
* \param [in] dir - Frame direction [0: uplink, 1: downlink] * @param [in] dir - Frame direction [0: uplink, 1: downlink]
* \param [in] sequenceCounter - Frame sequence counter * @param [in] seq_counter - Frame sequence counter
* \param [out] mic - Computed MIC field * @param [out] mic - Computed MIC field
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic ); int compute_mic(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint32_t *mic);
/** /**
* Computes the LoRaMAC payload encryption * Performs payload encryption
* *
* \param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* \param [in] size - Data buffer size * @param [in] size - Data buffer size
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [in] address - Frame address * @param [in] address - Frame address
* \param [in] dir - Frame direction [0: uplink, 1: downlink] * @param [in] dir - Frame direction [0: uplink, 1: downlink]
* \param [in] sequenceCounter - Frame sequence counter * @param [in] seq_counter - Frame sequence counter
* \param [out] encBuffer - Encrypted buffer * @param [out] enc_buffer - Encrypted buffer
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer ); int encrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *enc_buffer);
/** /**
* Computes the LoRaMAC payload decryption * Performs payload decryption
* *
* \param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* \param [in] size - Data buffer size * @param [in] size - Data buffer size
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [in] address - Frame address * @param [in] address - Frame address
* \param [in] dir - Frame direction [0: uplink, 1: downlink] * @param [in] dir - Frame direction [0: uplink, 1: downlink]
* \param [in] sequenceCounter - Frame sequence counter * @param [in] seq_counter - Frame sequence counter
* \param [out] decBuffer - Decrypted buffer * @param [out] dec_buffer - Decrypted buffer
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer ); int decrypt_payload(const uint8_t *buffer, uint16_t size, const uint8_t *key,
uint32_t address, uint8_t dir, uint32_t seq_counter,
uint8_t *dec_buffer);
/** /**
* Computes the LoRaMAC Join Request frame MIC field * Computes the LoRaMAC Join Request frame MIC field
* *
* \param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* \param [in] size - Data buffer size * @param [in] size - Data buffer size
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [out] mic - Computed MIC field * @param [out] mic - Computed MIC field
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
* *
*/ */
int LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic ); int compute_join_frame_mic(const uint8_t *buffer, uint16_t size,
const uint8_t *key, uint32_t *mic);
/** /**
* Computes the LoRaMAC join frame decryption * Computes the LoRaMAC join frame decryption
* *
* \param [in] buffer - Data buffer * @param [in] buffer - Data buffer
* \param [in] size - Data buffer size * @param [in] size - Data buffer size
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [out] decBuffer - Decrypted buffer * @param [out] dec_buffer - Decrypted buffer
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer ); int decrypt_join_frame(const uint8_t *buffer, uint16_t size,
const uint8_t *key, uint8_t *dec_buffer);
/** /**
* Computes the LoRaMAC join frame decryption * Computes the LoRaMAC join frame decryption
* *
* \param [in] key - AES key to be used * @param [in] key - AES key to be used
* \param [in] appNonce - Application nonce * @param [in] app_nonce - Application nonce
* \param [in] devNonce - Device nonce * @param [in] dev_nonce - Device nonce
* \param [out] nwkSKey - Network session key * @param [out] nwk_skey - Network session key
* \param [out] appSKey - Application session key * @param [out] app_skey - Application session key
* *
* \return 0 if successful, or a cipher specific error code * @return 0 if successful, or a cipher specific error code
*/ */
int LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey ); int compute_skeys_for_join_frame(const uint8_t *key, const uint8_t *app_nonce,
uint16_t dev_nonce, uint8_t *nwk_skey,
uint8_t *app_skey );
#endif // MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__ #endif // MBED_LORAWAN_MAC_LORAMAC_CRYPTO_H__

View File

@ -52,15 +52,15 @@ lorawan_status_t LoRaMacMcps::set_request(loramac_mcps_req_t *mcpsRequest,
get_phy_params_t get_phy; get_phy_params_t get_phy;
phy_param_t phyParam; phy_param_t phyParam;
lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN; lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN;
loramac_mhdr_t macHdr; loramac_mhdr_t machdr;
verification_params_t verify; verification_params_t verify;
uint8_t fPort = 0; uint8_t fport = 0;
void *fBuffer; void *fbuffer;
uint16_t fBufferSize; uint16_t fbuffer_size;
int8_t datarate = DR_0; int8_t datarate = DR_0;
bool readyToSend = false; bool ready_to_send = false;
macHdr.value = 0; machdr.value = 0;
// Before performing any MCPS request, clear the confirmation structure // Before performing any MCPS request, clear the confirmation structure
memset((uint8_t*) &confirmation, 0, sizeof(confirmation)); memset((uint8_t*) &confirmation, 0, sizeof(confirmation));
@ -72,34 +72,34 @@ lorawan_status_t LoRaMacMcps::set_request(loramac_mcps_req_t *mcpsRequest,
switch (mcpsRequest->type) { switch (mcpsRequest->type) {
case MCPS_UNCONFIRMED: { case MCPS_UNCONFIRMED: {
readyToSend = true; ready_to_send = true;
params->max_ack_timeout_retries = 1; params->max_ack_timeout_retries = 1;
macHdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP; machdr.bits.mtype = FRAME_TYPE_DATA_UNCONFIRMED_UP;
fPort = mcpsRequest->req.unconfirmed.fport; fport = mcpsRequest->req.unconfirmed.fport;
fBuffer = mcpsRequest->f_buffer; fbuffer = mcpsRequest->f_buffer;
fBufferSize = mcpsRequest->f_buffer_size; fbuffer_size = mcpsRequest->f_buffer_size;
datarate = mcpsRequest->req.unconfirmed.data_rate; datarate = mcpsRequest->req.unconfirmed.data_rate;
break; break;
} }
case MCPS_CONFIRMED: { case MCPS_CONFIRMED: {
readyToSend = true; ready_to_send = true;
params->max_ack_timeout_retries = mcpsRequest->req.confirmed.nb_trials; params->max_ack_timeout_retries = mcpsRequest->req.confirmed.nb_trials;
macHdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP; machdr.bits.mtype = FRAME_TYPE_DATA_CONFIRMED_UP;
fPort = mcpsRequest->req.confirmed.fport; fport = mcpsRequest->req.confirmed.fport;
fBuffer = mcpsRequest->f_buffer; fbuffer = mcpsRequest->f_buffer;
fBufferSize = mcpsRequest->f_buffer_size; fbuffer_size = mcpsRequest->f_buffer_size;
datarate = mcpsRequest->req.confirmed.data_rate; datarate = mcpsRequest->req.confirmed.data_rate;
break; break;
} }
case MCPS_PROPRIETARY: { case MCPS_PROPRIETARY: {
readyToSend = true; ready_to_send = true;
params->max_ack_timeout_retries = 1; params->max_ack_timeout_retries = 1;
macHdr.bits.mtype = FRAME_TYPE_PROPRIETARY; machdr.bits.mtype = FRAME_TYPE_PROPRIETARY;
fBuffer = mcpsRequest->f_buffer; fbuffer = mcpsRequest->f_buffer;
fBufferSize = mcpsRequest->f_buffer_size; fbuffer_size = mcpsRequest->f_buffer_size;
datarate = mcpsRequest->req.proprietary.data_rate; datarate = mcpsRequest->req.proprietary.data_rate;
break; break;
} }
@ -122,7 +122,7 @@ lorawan_status_t LoRaMacMcps::set_request(loramac_mcps_req_t *mcpsRequest,
// Some regions have limitations for the minimum datarate. // Some regions have limitations for the minimum datarate.
datarate = MAX(datarate, (int8_t)phyParam.value); datarate = MAX(datarate, (int8_t)phyParam.value);
if (readyToSend == true) { if (ready_to_send == true) {
if (params->sys_params.adr_on == false) { if (params->sys_params.adr_on == false) {
verify.datarate = datarate; verify.datarate = datarate;
@ -133,7 +133,7 @@ lorawan_status_t LoRaMacMcps::set_request(loramac_mcps_req_t *mcpsRequest,
} }
} }
status = _lora_mac->Send(&macHdr, fPort, fBuffer, fBufferSize); status = _lora_mac->send(&machdr, fport, fbuffer, fbuffer_size);
if (status == LORAWAN_STATUS_OK) { if (status == LORAWAN_STATUS_OK) {
confirmation.req_type = mcpsRequest->type; confirmation.req_type = mcpsRequest->type;
params->flags.bits.mcps_req = 1; params->flags.bits.mcps_req = 1;

View File

@ -75,7 +75,7 @@ lorawan_status_t LoRaMacMib::set_request(loramac_mib_req_confirm_t *mibSet,
params->sys_params.min_rx_symb, params->sys_params.min_rx_symb,
params->sys_params.max_sys_rx_error, params->sys_params.max_sys_rx_error,
&params->rx_window2_config); &params->rx_window2_config);
_lora_mac->OpenContinuousRx2Window(); _lora_mac->open_continuous_rx2_window();
break; break;
} }
} }
@ -144,7 +144,7 @@ lorawan_status_t LoRaMacMib::set_request(loramac_mib_req_confirm_t *mibSet,
params->sys_params.max_sys_rx_error, params->sys_params.max_sys_rx_error,
&params->rx_window2_config); &params->rx_window2_config);
_lora_mac->OpenContinuousRx2Window(); _lora_mac->open_continuous_rx2_window();
} }
} else { } else {
status = LORAWAN_STATUS_PARAMETER_INVALID; status = LORAWAN_STATUS_PARAMETER_INVALID;
@ -272,7 +272,7 @@ lorawan_status_t LoRaMacMib::get_request(loramac_mib_req_confirm_t *mibGet,
{ {
lorawan_status_t status = LORAWAN_STATUS_OK; lorawan_status_t status = LORAWAN_STATUS_OK;
get_phy_params_t get_phy; get_phy_params_t get_phy;
phy_param_t phyParam; phy_param_t phy_param;
rx2_channel_params rx2_channel; rx2_channel_params rx2_channel;
if( mibGet == NULL ) if( mibGet == NULL )
@ -330,9 +330,9 @@ lorawan_status_t LoRaMacMib::get_request(loramac_mib_req_confirm_t *mibGet,
case MIB_CHANNELS: case MIB_CHANNELS:
{ {
get_phy.attribute = PHY_CHANNELS; get_phy.attribute = PHY_CHANNELS;
phyParam = _lora_phy->get_phy_params( &get_phy ); phy_param = _lora_phy->get_phy_params( &get_phy );
mibGet->param.channel_list = phyParam.channel_params; mibGet->param.channel_list = phy_param.channel_params;
break; break;
} }
case MIB_RX2_CHANNEL: case MIB_RX2_CHANNEL:
@ -343,12 +343,12 @@ lorawan_status_t LoRaMacMib::get_request(loramac_mib_req_confirm_t *mibGet,
case MIB_RX2_DEFAULT_CHANNEL: case MIB_RX2_DEFAULT_CHANNEL:
{ {
get_phy.attribute = PHY_DEF_RX2_DR; get_phy.attribute = PHY_DEF_RX2_DR;
phyParam = _lora_phy->get_phy_params( &get_phy ); phy_param = _lora_phy->get_phy_params( &get_phy );
rx2_channel.datarate = phyParam.value; rx2_channel.datarate = phy_param.value;
get_phy.attribute = PHY_DEF_RX2_FREQUENCY; get_phy.attribute = PHY_DEF_RX2_FREQUENCY;
phyParam = _lora_phy->get_phy_params( &get_phy ); phy_param = _lora_phy->get_phy_params( &get_phy );
rx2_channel.frequency = phyParam.value; rx2_channel.frequency = phy_param.value;
mibGet->param.rx2_channel = rx2_channel; mibGet->param.rx2_channel = rx2_channel;
break; break;
@ -356,17 +356,17 @@ lorawan_status_t LoRaMacMib::get_request(loramac_mib_req_confirm_t *mibGet,
case MIB_CHANNELS_DEFAULT_MASK: case MIB_CHANNELS_DEFAULT_MASK:
{ {
get_phy.attribute = PHY_CHANNELS_DEFAULT_MASK; get_phy.attribute = PHY_CHANNELS_DEFAULT_MASK;
phyParam = _lora_phy->get_phy_params( &get_phy ); phy_param = _lora_phy->get_phy_params( &get_phy );
mibGet->param.default_channel_mask = phyParam.channel_mask; mibGet->param.default_channel_mask = phy_param.channel_mask;
break; break;
} }
case MIB_CHANNELS_MASK: case MIB_CHANNELS_MASK:
{ {
get_phy.attribute = PHY_CHANNELS_MASK; get_phy.attribute = PHY_CHANNELS_MASK;
phyParam = _lora_phy->get_phy_params( &get_phy ); phy_param = _lora_phy->get_phy_params( &get_phy );
mibGet->param.channel_mask = phyParam.channel_mask; mibGet->param.channel_mask = phy_param.channel_mask;
break; break;
} }
case MIB_CHANNELS_NB_REP: case MIB_CHANNELS_NB_REP:
@ -402,8 +402,8 @@ lorawan_status_t LoRaMacMib::get_request(loramac_mib_req_confirm_t *mibGet,
case MIB_CHANNELS_DEFAULT_DATARATE: case MIB_CHANNELS_DEFAULT_DATARATE:
{ {
get_phy.attribute = PHY_DEF_TX_DR; get_phy.attribute = PHY_DEF_TX_DR;
phyParam = _lora_phy->get_phy_params( &get_phy ); phy_param = _lora_phy->get_phy_params( &get_phy );
mibGet->param.default_channel_data_rate = phyParam.value; mibGet->param.default_channel_data_rate = phy_param.value;
break; break;
} }
case MIB_CHANNELS_DATARATE: case MIB_CHANNELS_DATARATE:
@ -414,8 +414,8 @@ lorawan_status_t LoRaMacMib::get_request(loramac_mib_req_confirm_t *mibGet,
case MIB_CHANNELS_DEFAULT_TX_POWER: case MIB_CHANNELS_DEFAULT_TX_POWER:
{ {
get_phy.attribute = PHY_DEF_TX_POWER; get_phy.attribute = PHY_DEF_TX_POWER;
phyParam = _lora_phy->get_phy_params( &get_phy ); phy_param = _lora_phy->get_phy_params( &get_phy );
mibGet->param.default_channel_tx_pwr = phyParam.value; mibGet->param.default_channel_tx_pwr = phy_param.value;
break; break;
} }
case MIB_CHANNELS_TX_POWER: case MIB_CHANNELS_TX_POWER:

View File

@ -43,17 +43,17 @@ void LoRaMacMlme::activate_mlme_subsystem(LoRaMac *mac, LoRaPHY *phy,
_mac_cmd = cmd; _mac_cmd = cmd;
} }
lorawan_status_t LoRaMacMlme::set_request(loramac_mlme_req_t *mlmeRequest, lorawan_status_t LoRaMacMlme::set_request(loramac_mlme_req_t *request,
loramac_protocol_params *params) loramac_protocol_params *params)
{ {
if (mlmeRequest && params && _lora_mac && _lora_phy && _mac_cmd) { if (request && params && _lora_mac && _lora_phy && _mac_cmd) {
lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN; lorawan_status_t status = LORAWAN_STATUS_SERVICE_UNKNOWN;
loramac_mhdr_t macHdr; loramac_mhdr_t machdr;
verification_params_t verify; verification_params_t verify;
get_phy_params_t get_phy; get_phy_params_t get_phy;
phy_param_t phyParam; phy_param_t phy_param;
if (params->mac_state != LORAMAC_IDLE) { if (params->mac_state != LORAMAC_IDLE) {
@ -66,73 +66,73 @@ lorawan_status_t LoRaMacMlme::set_request(loramac_mlme_req_t *mlmeRequest,
confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR; confirmation.status = LORAMAC_EVENT_INFO_STATUS_ERROR;
switch (mlmeRequest->type) { switch (request->type) {
case MLME_JOIN: { case MLME_JOIN: {
if ((params->mac_state & LORAMAC_TX_DELAYED) if ((params->mac_state & LORAMAC_TX_DELAYED)
== LORAMAC_TX_DELAYED) { == LORAMAC_TX_DELAYED) {
return LORAWAN_STATUS_BUSY; return LORAWAN_STATUS_BUSY;
} }
if ((mlmeRequest->req.join.dev_eui == NULL) if ((request->req.join.dev_eui == NULL)
|| (mlmeRequest->req.join.app_eui == NULL) || (request->req.join.app_eui == NULL)
|| (mlmeRequest->req.join.app_key == NULL) || (request->req.join.app_key == NULL)
|| (mlmeRequest->req.join.nb_trials == 0)) { || (request->req.join.nb_trials == 0)) {
return LORAWAN_STATUS_PARAMETER_INVALID; return LORAWAN_STATUS_PARAMETER_INVALID;
} }
// Verify the parameter NbTrials for the join procedure // Verify the parameter NbTrials for the join procedure
verify.nb_join_trials = mlmeRequest->req.join.nb_trials; verify.nb_join_trials = request->req.join.nb_trials;
if (_lora_phy->verify(&verify, PHY_NB_JOIN_TRIALS) == false) { if (_lora_phy->verify(&verify, PHY_NB_JOIN_TRIALS) == false) {
// Value not supported, get default // Value not supported, get default
get_phy.attribute = PHY_DEF_NB_JOIN_TRIALS; get_phy.attribute = PHY_DEF_NB_JOIN_TRIALS;
phyParam = _lora_phy->get_phy_params(&get_phy); phy_param = _lora_phy->get_phy_params(&get_phy);
mlmeRequest->req.join.nb_trials = (uint8_t) phyParam.value; request->req.join.nb_trials = (uint8_t) phy_param.value;
} }
params->flags.bits.mlme_req = 1; params->flags.bits.mlme_req = 1;
confirmation.req_type = mlmeRequest->type; confirmation.req_type = request->type;
params->keys.dev_eui = mlmeRequest->req.join.dev_eui; params->keys.dev_eui = request->req.join.dev_eui;
params->keys.app_eui = mlmeRequest->req.join.app_eui; params->keys.app_eui = request->req.join.app_eui;
params->keys.app_key = mlmeRequest->req.join.app_key; params->keys.app_key = request->req.join.app_key;
params->max_join_request_trials = mlmeRequest->req.join.nb_trials; params->max_join_request_trials = request->req.join.nb_trials;
// Reset variable JoinRequestTrials // Reset variable JoinRequestTrials
params->join_request_trial_counter = 0; params->join_request_trial_counter = 0;
// Setup header information // Setup header information
macHdr.value = 0; machdr.value = 0;
macHdr.bits.mtype = FRAME_TYPE_JOIN_REQ; machdr.bits.mtype = FRAME_TYPE_JOIN_REQ;
_lora_mac->ResetMacParameters(); _lora_mac->reset_mac_parameters();
params->sys_params.channel_data_rate = params->sys_params.channel_data_rate =
_lora_phy->get_alternate_DR(params->join_request_trial_counter + 1); _lora_phy->get_alternate_DR(params->join_request_trial_counter + 1);
status = _lora_mac->Send(&macHdr, 0, NULL, 0); status = _lora_mac->send(&machdr, 0, NULL, 0);
break; break;
} }
case MLME_LINK_CHECK: { case MLME_LINK_CHECK: {
params->flags.bits.mlme_req = 1; params->flags.bits.mlme_req = 1;
// LoRaMac will send this command piggy-backed // LoRaMac will send this command piggy-backed
confirmation.req_type = mlmeRequest->type; confirmation.req_type = request->type;
status = _mac_cmd->AddMacCommand(MOTE_MAC_LINK_CHECK_REQ, 0, 0); status = _mac_cmd->add_mac_command(MOTE_MAC_LINK_CHECK_REQ, 0, 0);
break; break;
} }
case MLME_TXCW: { case MLME_TXCW: {
confirmation.req_type = mlmeRequest->type; confirmation.req_type = request->type;
params->flags.bits.mlme_req = 1; params->flags.bits.mlme_req = 1;
status = _lora_mac->SetTxContinuousWave(mlmeRequest->req.cw_tx_mode.timeout); status = _lora_mac->set_tx_continuous_wave(request->req.cw_tx_mode.timeout);
break; break;
} }
case MLME_TXCW_1: { case MLME_TXCW_1: {
confirmation.req_type = mlmeRequest->type; confirmation.req_type = request->type;
params->flags.bits.mlme_req = 1; params->flags.bits.mlme_req = 1;
status = _lora_mac->SetTxContinuousWave1(mlmeRequest->req.cw_tx_mode.timeout, status = _lora_mac->set_tx_continuous_wave1(request->req.cw_tx_mode.timeout,
mlmeRequest->req.cw_tx_mode.frequency, request->req.cw_tx_mode.frequency,
mlmeRequest->req.cw_tx_mode.power); request->req.cw_tx_mode.power);
break; break;
} }
default: default:

View File

@ -66,13 +66,13 @@ public:
* to the central MAC control. It also modifies or uses protocol information * to the central MAC control. It also modifies or uses protocol information
* provided in the MAC protocol data structure. * provided in the MAC protocol data structure.
* *
* @param mlmeRequest pointer to MLME request structure * @param request pointer to MLME request structure
* @param params pointer to MAC protocol parameters * @param params pointer to MAC protocol parameters
* *
* @return LORAWAN_STATUS_OK if everything goes well otherwise * @return LORAWAN_STATUS_OK if everything goes well otherwise
* a negative error code is returned. * a negative error code is returned.
*/ */
lorawan_status_t set_request(loramac_mlme_req_t *mlmeRequest, loramac_protocol_params *params); lorawan_status_t set_request(loramac_mlme_req_t *request, loramac_protocol_params *params);
/** Grants access to MLME confirmation data /** Grants access to MLME confirmation data
* *

View File

@ -368,7 +368,7 @@ typedef struct multicast_params_s {
/*! /*!
* A reference pointer to the next multicast channel parameters in the list. * A reference pointer to the next multicast channel parameters in the list.
*/ */
struct multicast_params_s *Next; struct multicast_params_s *next;
} multicast_params_t; } multicast_params_t;
/*! /*!