From 5b76fdf46e9d03398a924927a76398990d5fcb4b Mon Sep 17 00:00:00 2001 From: Alexandre Abadie <alexandre.abadie@inria.fr> Date: Mon, 19 Mar 2018 08:27:16 +0100 Subject: [PATCH] pkg/semtech-loramac: refactor API to make it thread-safe --- pkg/semtech-loramac/contrib/semtech_loramac.c | 344 ++++++++++-------- .../contrib/semtech_loramac_getset.c | 217 +++++++---- .../contrib/semtech_loramac_timer.c | 4 + pkg/semtech-loramac/include/semtech_loramac.h | 246 +++++++++---- 4 files changed, 533 insertions(+), 278 deletions(-) diff --git a/pkg/semtech-loramac/contrib/semtech_loramac.c b/pkg/semtech-loramac/contrib/semtech_loramac.c index 55dc026850..5212b30af7 100644 --- a/pkg/semtech-loramac/contrib/semtech_loramac.c +++ b/pkg/semtech-loramac/contrib/semtech_loramac.c @@ -28,6 +28,7 @@ #include <string.h> #include "msg.h" +#include "mutex.h" #include "net/netdev.h" #include "net/loramac.h" @@ -63,30 +64,21 @@ #define SEMTECH_LORAMAC_MSG_QUEUE (16U) #define SEMTECH_LORAMAC_LORAMAC_STACKSIZE (THREAD_STACKSIZE_DEFAULT) +static msg_t _semtech_loramac_msg_queue[SEMTECH_LORAMAC_MSG_QUEUE]; static char _semtech_loramac_stack[SEMTECH_LORAMAC_LORAMAC_STACKSIZE]; kernel_pid_t semtech_loramac_pid; -kernel_pid_t semtech_loramac_handler_pid; +sx127x_t sx127x; RadioEvents_t semtech_loramac_radio_events; -uint8_t semtech_loramac_dev_eui[LORAMAC_DEVEUI_LEN]; -uint8_t semtech_loramac_app_eui[LORAMAC_APPEUI_LEN]; -uint8_t semtech_loramac_app_key[LORAMAC_APPKEY_LEN]; -uint8_t semtech_loramac_nwk_skey[LORAMAC_NWKSKEY_LEN]; -uint8_t semtech_loramac_app_skey[LORAMAC_APPSKEY_LEN]; -uint8_t semtech_loramac_dev_addr[LORAMAC_DEVADDR_LEN]; - -static uint8_t _semtech_loramac_radio_payload[SX127X_RX_BUFFER_SIZE]; -static semtech_loramac_rx_data_t _semtech_loramac_rx_data; +LoRaMacPrimitives_t semtech_loramac_primitives; +LoRaMacCallback_t semtech_loramac_callbacks; typedef struct { - uint8_t port; - uint8_t cnf; - uint8_t dr; uint8_t *payload; uint8_t len; } loramac_send_params_t; -typedef void (*semtech_loramac_func_t)(void *); +typedef void (*semtech_loramac_func_t)(semtech_loramac_t *, void *); /** * @brief Struct containing a semtech loramac function call @@ -99,12 +91,13 @@ typedef struct { } semtech_loramac_call_t; /* Prepares the payload of the frame */ -static bool _semtech_loramac_send(uint8_t cnf, uint8_t port, uint8_t dr, +static bool _semtech_loramac_send(semtech_loramac_t *mac, uint8_t *payload, uint8_t len) { DEBUG("[semtech-loramac] send frame %s\n", (char *)payload); McpsReq_t mcpsReq; LoRaMacTxInfo_t txInfo; + uint8_t dr = semtech_loramac_get_dr(mac); if (LoRaMacQueryTxPossible(len, &txInfo) != LORAMAC_STATUS_OK) { DEBUG("[semtech-loramac] empty frame in order to flush MAC commands\n"); @@ -115,10 +108,10 @@ static bool _semtech_loramac_send(uint8_t cnf, uint8_t port, uint8_t dr, mcpsReq.Req.Unconfirmed.Datarate = (int8_t)dr; } else { - if (cnf == LORAMAC_TX_UNCNF) { + if (mac->cnf == LORAMAC_TX_UNCNF) { DEBUG("[semtech-loramac] MCPS_UNCONFIRMED\n"); mcpsReq.Type = MCPS_UNCONFIRMED; - mcpsReq.Req.Unconfirmed.fPort = port; + mcpsReq.Req.Unconfirmed.fPort = mac->port; mcpsReq.Req.Unconfirmed.fBuffer = payload; mcpsReq.Req.Unconfirmed.fBufferSize = len; mcpsReq.Req.Unconfirmed.Datarate = (int8_t)dr; @@ -126,7 +119,7 @@ static bool _semtech_loramac_send(uint8_t cnf, uint8_t port, uint8_t dr, else { DEBUG("[semtech-loramac] MCPS_CONFIRMED\n"); mcpsReq.Type = MCPS_CONFIRMED; - mcpsReq.Req.Confirmed.fPort = port; + mcpsReq.Req.Confirmed.fPort = mac->port; mcpsReq.Req.Confirmed.fBuffer = payload; mcpsReq.Req.Confirmed.fBufferSize = len; mcpsReq.Req.Confirmed.NbTrials = 3; @@ -156,9 +149,8 @@ static void mcps_confirm(McpsConfirm_t *confirm) Check TxPower */ DEBUG("[semtech-loramac] MCPS confirm event UNCONFIRMED\n"); msg_t msg; - msg.type = MSG_TYPE_LORAMAC_NOTIFY; - msg.content.value = SEMTECH_LORAMAC_TX_DONE; - msg_send(&msg, semtech_loramac_handler_pid); + msg.type = MSG_TYPE_LORAMAC_TX_DONE; + msg_send(&msg, semtech_loramac_pid); break; } @@ -214,28 +206,15 @@ static void mcps_indication(McpsIndication_t *indication) } msg_t msg; - msg.type = MSG_TYPE_LORAMAC_NOTIFY; if (indication->RxData) { - indication->Buffer[indication->BufferSize] = '\0'; - memcpy(_semtech_loramac_rx_data.payload, indication->Buffer, - indication->BufferSize); - _semtech_loramac_rx_data.payload[indication->BufferSize] = 0; - _semtech_loramac_rx_data.payload_len = indication->BufferSize; - _semtech_loramac_rx_data.port = indication->Port; - DEBUG("[semtech-loramac] MCPS indication:\n" - " - Payload: %s\n" - " - Size: %d\n" - " - Port: %d\n", - (char *)_semtech_loramac_rx_data.payload, - _semtech_loramac_rx_data.payload_len, - _semtech_loramac_rx_data.port - ); - msg.content.value = SEMTECH_LORAMAC_RX_DATA; + DEBUG("[semtech-loramac] MCPS indication: data received\n"); + msg.type = MSG_TYPE_LORAMAC_RX; + msg.content.ptr = indication; } else { - msg.content.value = SEMTECH_LORAMAC_TX_DONE; + msg.type = MSG_TYPE_LORAMAC_TX_DONE; } - msg_send(&msg, semtech_loramac_handler_pid); + msg_send(&msg, semtech_loramac_pid); } /*MLME-Confirm event function */ @@ -248,17 +227,17 @@ static void mlme_confirm(MlmeConfirm_t *confirm) /* Status is OK, node has joined the network */ DEBUG("[semtech-loramac] join succeeded\n"); msg_t msg; - msg.type = MSG_TYPE_LORAMAC_NOTIFY; + msg.type = MSG_TYPE_LORAMAC_JOIN; msg.content.value = SEMTECH_LORAMAC_JOIN_SUCCEEDED; - msg_send(&msg, semtech_loramac_handler_pid); + msg_send(&msg, semtech_loramac_pid); } else { DEBUG("[semtech-loramac] join not successful\n"); /* Join was not successful. */ msg_t msg; - msg.type = MSG_TYPE_LORAMAC_NOTIFY; + msg.type = MSG_TYPE_LORAMAC_JOIN; msg.content.value = SEMTECH_LORAMAC_JOIN_FAILED; - msg_send(&msg, semtech_loramac_handler_pid); + msg_send(&msg, semtech_loramac_pid); } break; @@ -267,24 +246,10 @@ static void mlme_confirm(MlmeConfirm_t *confirm) } } -void _loramac_set_rx2_params(uint32_t freq, uint8_t dr) -{ - Rx2ChannelParams_t params; - params.Frequency = freq; - params.Datarate = dr; - - MibRequestConfirm_t mibReq; - mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; - mibReq.Param.Rx2DefaultChannel = params; - LoRaMacMibSetRequestConfirm(&mibReq); - - mibReq.Type = MIB_RX2_CHANNEL; - mibReq.Param.Rx2Channel = params; - LoRaMacMibSetRequestConfirm(&mibReq); -} - -void _init_loramac(LoRaMacPrimitives_t * primitives, LoRaMacCallback_t *callbacks) +void _init_loramac(semtech_loramac_t *mac, + LoRaMacPrimitives_t * primitives, LoRaMacCallback_t *callbacks) { + mutex_lock(&mac->lock); DEBUG("[semtech-loramac] initializing loramac\n"); primitives->MacMcpsConfirm = mcps_confirm; primitives->MacMcpsIndication = mcps_indication; @@ -324,9 +289,11 @@ void _init_loramac(LoRaMacPrimitives_t * primitives, LoRaMacCallback_t *callback #else #error "Please define a region in the compiler options." #endif + mutex_unlock(&mac->lock); #if defined(REGION_EU868) && USE_SEMTECH_DEFAULT_CHANNEL_LINEUP DEBUG("[semtech-loramac] EU868 region: use default channels\n"); + mutex_lock(&mac->lock); LoRaMacChannelAdd(3, (ChannelParams_t)LC4); LoRaMacChannelAdd(4, (ChannelParams_t)LC5); LoRaMacChannelAdd(5, (ChannelParams_t)LC6); @@ -334,15 +301,25 @@ void _init_loramac(LoRaMacPrimitives_t * primitives, LoRaMacCallback_t *callback LoRaMacChannelAdd(7, (ChannelParams_t)LC8); LoRaMacChannelAdd(8, (ChannelParams_t)LC9); LoRaMacChannelAdd(9, (ChannelParams_t)LC10); + mutex_unlock(&mac->lock); - _loramac_set_rx2_params(LORAMAC_DEFAULT_RX2_FREQ, LORAMAC_DEFAULT_RX2_DR); + semtech_loramac_set_rx2_dr(mac, LORAMAC_DEFAULT_RX2_DR); + semtech_loramac_set_rx2_freq(mac, LORAMAC_DEFAULT_RX2_FREQ); #endif + + semtech_loramac_set_dr(mac, LORAMAC_DEFAULT_DR); + semtech_loramac_set_adr(mac, LORAMAC_DEFAULT_ADR); + semtech_loramac_set_public_network(mac, LORAMAC_DEFAULT_PUBLIC_NETWORK); + semtech_loramac_set_class(mac, LORAMAC_DEFAULT_DEVICE_CLASS); + semtech_loramac_set_tx_port(mac, LORAMAC_DEFAULT_TX_PORT); + semtech_loramac_set_tx_mode(mac, LORAMAC_DEFAULT_TX_MODE); } -static void _join_otaa(void) +static void _join_otaa(semtech_loramac_t *mac) { DEBUG("[semtech-loramac] starting OTAA join\n"); + mutex_lock(&mac->lock); MibRequestConfirm_t mibReq; mibReq.Type = MIB_NETWORK_JOINED; mibReq.Param.IsNetworkJoined = false; @@ -350,65 +327,69 @@ static void _join_otaa(void) MlmeReq_t mlmeReq; mlmeReq.Type = MLME_JOIN; - mlmeReq.Req.Join.DevEui = semtech_loramac_dev_eui; - mlmeReq.Req.Join.AppEui = semtech_loramac_app_eui; - mlmeReq.Req.Join.AppKey = semtech_loramac_app_key; + mlmeReq.Req.Join.DevEui = mac->deveui; + mlmeReq.Req.Join.AppEui = mac->appeui; + mlmeReq.Req.Join.AppKey = mac->appkey; mlmeReq.Req.Join.NbTrials = LORAWAN_MAX_JOIN_RETRIES; LoRaMacMlmeRequest(&mlmeReq); + mutex_unlock(&mac->lock); } -static void _join_abp(void) +static void _join_abp(semtech_loramac_t *mac) { DEBUG("[semtech-loramac] starting ABP join\n"); + semtech_loramac_set_netid(mac, LORAMAC_DEFAULT_NETID); + + mutex_lock(&mac->lock); MibRequestConfirm_t mibReq; mibReq.Type = MIB_NETWORK_JOINED; mibReq.Param.IsNetworkJoined = false; LoRaMacMibSetRequestConfirm(&mibReq); - semtech_loramac_set_netid(LORAMAC_DEFAULT_NETID); - mibReq.Type = MIB_DEV_ADDR; - mibReq.Param.DevAddr = ((uint32_t)semtech_loramac_dev_addr[0] << 24 | - (uint32_t)semtech_loramac_dev_addr[1] << 16 | - (uint32_t)semtech_loramac_dev_addr[2] << 8 | - (uint32_t)semtech_loramac_dev_addr[3]); + mibReq.Param.DevAddr = ((uint32_t)mac->devaddr[0] << 24 | + (uint32_t)mac->devaddr[1] << 16 | + (uint32_t)mac->devaddr[2] << 8 | + (uint32_t)mac->devaddr[3]); LoRaMacMibSetRequestConfirm(&mibReq); mibReq.Type = MIB_NWK_SKEY; - mibReq.Param.NwkSKey = semtech_loramac_nwk_skey; + mibReq.Param.NwkSKey = mac->nwkskey; LoRaMacMibSetRequestConfirm(&mibReq); mibReq.Type = MIB_APP_SKEY; - mibReq.Param.AppSKey = semtech_loramac_app_skey; + mibReq.Param.AppSKey = mac->appskey; LoRaMacMibSetRequestConfirm(&mibReq); mibReq.Type = MIB_NETWORK_JOINED; mibReq.Param.IsNetworkJoined = true; LoRaMacMibSetRequestConfirm(&mibReq); + + /* switch back to idle state now*/ + mac->state = SEMTECH_LORAMAC_STATE_IDLE; + mutex_unlock(&mac->lock); } -static void _join(void *arg) +static void _join(semtech_loramac_t *mac, void *arg) { - (void) arg; uint8_t join_type = *(uint8_t *)arg; switch (join_type) { case LORAMAC_JOIN_OTAA: - _join_otaa(); + _join_otaa(mac); break; case LORAMAC_JOIN_ABP: - _join_abp(); + _join_abp(mac); break; } } -static void _send(void *arg) +static void _send(semtech_loramac_t *mac, void *arg) { loramac_send_params_t params = *(loramac_send_params_t *)arg; - _semtech_loramac_send(params.cnf, params.port, params.dr, - params.payload, params.len); + _semtech_loramac_send(mac, params.payload, params.len); } static void _semtech_loramac_call(semtech_loramac_func_t func, void *arg) @@ -417,10 +398,10 @@ static void _semtech_loramac_call(semtech_loramac_func_t func, void *arg) call.func = func; call.arg = arg; - msg_t msg; + msg_t msg, msg_resp; msg.type = MSG_TYPE_LORAMAC_CMD; msg.content.ptr = &call; - msg_send(&msg, semtech_loramac_pid); + msg_send_receive(&msg, &msg_resp, semtech_loramac_pid); } static void _semtech_loramac_event_cb(netdev_t *dev, netdev_event_t event) @@ -454,12 +435,12 @@ static void _semtech_loramac_event_cb(netdev_t *dev, netdev_event_t event) case NETDEV_EVENT_RX_COMPLETE: { size_t len; + uint8_t radio_payload[SX127X_RX_BUFFER_SIZE]; len = dev->driver->recv(dev, NULL, 0, 0); - dev->driver->recv(dev, _semtech_loramac_radio_payload, len, &packet_info); - semtech_loramac_radio_events.RxDone(_semtech_loramac_radio_payload, - len, - packet_info.rssi, - packet_info.snr); + dev->driver->recv(dev, radio_payload, len, &packet_info); + semtech_loramac_radio_events.RxDone(radio_payload, + len, packet_info.rssi, + packet_info.snr); break; } case NETDEV_EVENT_RX_TIMEOUT: @@ -492,69 +473,105 @@ static void _semtech_loramac_event_cb(netdev_t *dev, netdev_event_t event) void *_semtech_loramac_event_loop(void *arg) { - (void) arg; - static msg_t _msg_q[SEMTECH_LORAMAC_MSG_QUEUE]; - msg_init_queue(_msg_q, SEMTECH_LORAMAC_MSG_QUEUE); - LoRaMacPrimitives_t primitives; - LoRaMacCallback_t callbacks; - - _init_loramac(&primitives, &callbacks); - semtech_loramac_set_dr(LORAMAC_DEFAULT_DR); - semtech_loramac_set_adr(LORAMAC_DEFAULT_ADR); - semtech_loramac_set_public_network(LORAMAC_DEFAULT_PUBLIC_NETWORK); - semtech_loramac_set_class(LORAMAC_DEFAULT_DEVICE_CLASS); + msg_init_queue(_semtech_loramac_msg_queue, SEMTECH_LORAMAC_MSG_QUEUE); + semtech_loramac_t *mac = (semtech_loramac_t *)arg; while (1) { msg_t msg; msg_receive(&msg); - switch (msg.type) { - case MSG_TYPE_ISR: - { - netdev_t *dev = msg.content.ptr; - dev->driver->isr(dev); - break; - } - case MSG_TYPE_RX_TIMEOUT: - DEBUG("[semtech-loramac] RX timer timeout\n"); - semtech_loramac_radio_events.RxTimeout(); - break; - - case MSG_TYPE_TX_TIMEOUT: - DEBUG("[semtech-loramac] TX timer timeout\n"); - semtech_loramac_radio_events.TxTimeout(); - break; - - case MSG_TYPE_MAC_TIMEOUT: - { - DEBUG("[semtech-loramac] MAC timer timeout\n"); - void (*callback)(void) = msg.content.ptr; - callback(); - break; - } - case MSG_TYPE_LORAMAC_CMD: - { - DEBUG("[semtech-loramac] loramac cmd\n"); - semtech_loramac_call_t *call = msg.content.ptr; - call->func(call->arg); - break; + if (msg.type == MSG_TYPE_ISR) { + netdev_t *dev = msg.content.ptr; + dev->driver->isr(dev); + } + else { + switch (msg.type) { + case MSG_TYPE_RX_TIMEOUT: + DEBUG("[semtech-loramac] RX timer timeout\n"); + semtech_loramac_radio_events.RxTimeout(); + break; + + case MSG_TYPE_TX_TIMEOUT: + DEBUG("[semtech-loramac] TX timer timeout\n"); + semtech_loramac_radio_events.TxTimeout(); + break; + + case MSG_TYPE_MAC_TIMEOUT: + { + DEBUG("[semtech-loramac] MAC timer timeout\n"); + void (*callback)(void) = msg.content.ptr; + callback(); + break; + } + case MSG_TYPE_LORAMAC_CMD: + { + msg_t msg_resp; + DEBUG("[semtech-loramac] loramac cmd\n"); + mac->state = SEMTECH_LORAMAC_STATE_BUSY; + semtech_loramac_call_t *call = msg.content.ptr; + call->func(mac, call->arg); + msg_reply(&msg, &msg_resp); + break; + } + case MSG_TYPE_LORAMAC_JOIN: + { + DEBUG("[semtech-loramac] loramac join notification\n"); + msg_t msg_ret; + msg_ret.content.value = msg.content.value; + msg_send(&msg_ret, mac->caller_pid); + /* switch back to idle state now*/ + mac->state = SEMTECH_LORAMAC_STATE_IDLE; + break; + } + case MSG_TYPE_LORAMAC_TX_DONE: + { + DEBUG("[semtech-loramac] loramac TX done\n"); + msg_t msg_ret; + msg_ret.type = MSG_TYPE_LORAMAC_TX_DONE; + msg_send(&msg_ret, mac->caller_pid); + /* switch back to idle state now*/ + mac->state = SEMTECH_LORAMAC_STATE_IDLE; + break; + } + case MSG_TYPE_LORAMAC_RX: + { + msg_t msg_ret; + msg_ret.type = MSG_TYPE_LORAMAC_RX; + McpsIndication_t *indication = (McpsIndication_t *)msg.content.ptr; + memcpy(mac->rx_data.payload, + indication->Buffer, indication->BufferSize); + mac->rx_data.payload_len = indication->BufferSize; + mac->rx_data.port = indication->Port; + DEBUG("[semtech-loramac] loramac RX data:\n" + " - Payload: %s\n" + " - Size: %d\n" + " - Port: %d\n", + (char *)mac->rx_data.payload, + mac->rx_data.payload_len, + mac->rx_data.port); + msg_send(&msg_ret, mac->caller_pid); + /* switch back to idle state now*/ + mac->state = SEMTECH_LORAMAC_STATE_IDLE; + break; + } + default: + DEBUG("[semtech-loramac] Unexpected msg type '%04x'\n", + msg.type); } - default: - DEBUG("[semtech-loramac] Unexpected msg type '%04x'\n", msg.type); } } } -int semtech_loramac_init(sx127x_t *dev) +int semtech_loramac_init(semtech_loramac_t *mac) { - dev->netdev.driver = &sx127x_driver; - dev->netdev.event_callback = _semtech_loramac_event_cb; + sx127x_setup(&sx127x, &sx127x_params[0]); + sx127x.netdev.driver = &sx127x_driver; + sx127x.netdev.event_callback = _semtech_loramac_event_cb; - semtech_loramac_handler_pid = thread_getpid(); semtech_loramac_pid = thread_create(_semtech_loramac_stack, sizeof(_semtech_loramac_stack), THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, - _semtech_loramac_event_loop, NULL, + _semtech_loramac_event_loop, mac, "recv_thread"); if (semtech_loramac_pid <= KERNEL_PID_UNDEF) { @@ -562,17 +579,29 @@ int semtech_loramac_init(sx127x_t *dev) return -1; } + _init_loramac(mac, &semtech_loramac_primitives, &semtech_loramac_callbacks); + return 0; } -uint8_t semtech_loramac_join(uint8_t type) +uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type) { + DEBUG("Starting join procedure: %d\n", type); + + if (mac->state != SEMTECH_LORAMAC_STATE_IDLE) { + DEBUG("[semtech-loramac] internal mac is busy\n"); + return SEMTECH_LORAMAC_BUSY; + } + + mac->caller_pid = thread_getpid(); + _semtech_loramac_call(_join, &type); if (type == LORAMAC_JOIN_OTAA) { /* Wait until the OTAA join procedure is complete */ msg_t msg; msg_receive(&msg); + mac->state = SEMTECH_LORAMAC_STATE_IDLE; return (uint8_t)msg.content.value; } @@ -580,36 +609,47 @@ uint8_t semtech_loramac_join(uint8_t type) return SEMTECH_LORAMAC_JOIN_SUCCEEDED; } -uint8_t semtech_loramac_send(uint8_t cnf, uint8_t port, - uint8_t *tx_buf, uint8_t tx_len, - semtech_loramac_rx_data_t *rx_data) +uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len) { + mutex_lock(&mac->lock); MibRequestConfirm_t mibReq; mibReq.Type = MIB_NETWORK_JOINED; LoRaMacMibGetRequestConfirm(&mibReq); + bool is_joined = mibReq.Param.IsNetworkJoined; + mutex_unlock(&mac->lock); - if (!mibReq.Param.IsNetworkJoined) { + if (!is_joined) { DEBUG("[semtech-loramac] network is not joined\n"); return SEMTECH_LORAMAC_NOT_JOINED; } + if (mac->state != SEMTECH_LORAMAC_STATE_IDLE) { + DEBUG("[semtech-loramac] internal mac is busy\n"); + return SEMTECH_LORAMAC_BUSY; + } + loramac_send_params_t params; - params.cnf = cnf; - params.port = port; - params.dr = semtech_loramac_get_dr(); - params.payload = tx_buf; - params.len = tx_len; + params.payload = data; + params.len = len; _semtech_loramac_call(_send, ¶ms); - /* Wait until sending is fully done */ + return SEMTECH_LORAMAC_TX_SCHEDULED; +} + +uint8_t semtech_loramac_recv(semtech_loramac_t *mac) +{ + mac->caller_pid = thread_getpid(); + + /* Wait until the mac receive some information */ msg_t msg; msg_receive(&msg); - uint8_t status = (uint8_t)msg.content.value; - if (status == SEMTECH_LORAMAC_RX_DATA) { - memcpy(rx_data, &_semtech_loramac_rx_data, - sizeof(semtech_loramac_rx_data_t)); + uint8_t ret = SEMTECH_LORAMAC_TX_DONE; + if (msg.type == MSG_TYPE_LORAMAC_RX) { + ret = SEMTECH_LORAMAC_DATA_RECEIVED; } - return status; + DEBUG("[semtech-loramac] MAC reply received: %d\n", ret); + + return ret; } diff --git a/pkg/semtech-loramac/contrib/semtech_loramac_getset.c b/pkg/semtech-loramac/contrib/semtech_loramac_getset.c index 6e1e418202..5659ffb5e6 100644 --- a/pkg/semtech-loramac/contrib/semtech_loramac_getset.c +++ b/pkg/semtech-loramac/contrib/semtech_loramac_getset.c @@ -19,6 +19,8 @@ #include <string.h> +#include "mutex.h" + #include "net/loramac.h" #include "semtech-loramac/board.h" @@ -27,217 +29,302 @@ #define ENABLE_DEBUG (0) #include "debug.h" -extern uint8_t semtech_loramac_dev_eui[LORAMAC_DEVEUI_LEN]; -extern uint8_t semtech_loramac_app_eui[LORAMAC_APPEUI_LEN]; -extern uint8_t semtech_loramac_app_key[LORAMAC_APPKEY_LEN]; -extern uint8_t semtech_loramac_nwk_skey[LORAMAC_NWKSKEY_LEN]; -extern uint8_t semtech_loramac_app_skey[LORAMAC_APPSKEY_LEN]; -extern uint8_t semtech_loramac_dev_addr[LORAMAC_DEVADDR_LEN]; - -extern void _loramac_set_rx2_params(uint32_t freq, uint8_t dr); - -void semtech_loramac_set_deveui(const uint8_t *eui) +void semtech_loramac_set_deveui(semtech_loramac_t *mac, const uint8_t *eui) { - memcpy(semtech_loramac_dev_eui, eui, LORAMAC_DEVEUI_LEN); + memcpy(mac->deveui, eui, LORAMAC_DEVEUI_LEN); } -void semtech_loramac_get_deveui(uint8_t *eui) +void semtech_loramac_get_deveui(const semtech_loramac_t *mac, uint8_t *eui) { - memcpy(eui, semtech_loramac_dev_eui, LORAMAC_DEVEUI_LEN); + memcpy(eui, mac->deveui, LORAMAC_DEVEUI_LEN); } -void semtech_loramac_set_appeui(const uint8_t *eui) +void semtech_loramac_set_appeui(semtech_loramac_t *mac, const uint8_t *eui) { - memcpy(semtech_loramac_app_eui, eui, LORAMAC_APPEUI_LEN); + memcpy(mac->appeui, eui, LORAMAC_APPEUI_LEN); } -void semtech_loramac_get_appeui(uint8_t *eui) +void semtech_loramac_get_appeui(const semtech_loramac_t *mac, uint8_t *eui) { - memcpy(eui, semtech_loramac_app_eui, LORAMAC_APPEUI_LEN); + memcpy(eui, mac->appeui, LORAMAC_APPEUI_LEN); } -void semtech_loramac_set_appkey(const uint8_t *key) +void semtech_loramac_set_appkey(semtech_loramac_t *mac, const uint8_t *key) { - memcpy(semtech_loramac_app_key, key, LORAMAC_APPKEY_LEN); + memcpy(mac->appkey, key, LORAMAC_APPKEY_LEN); } -void semtech_loramac_get_appkey(uint8_t *key) +void semtech_loramac_get_appkey(const semtech_loramac_t *mac, uint8_t *key) { - memcpy(key, semtech_loramac_app_key, LORAMAC_APPKEY_LEN); + memcpy(key, mac->appkey, LORAMAC_APPKEY_LEN); } -void semtech_loramac_set_appskey(const uint8_t *skey) +void semtech_loramac_set_appskey(semtech_loramac_t *mac, const uint8_t *skey) { - memcpy(semtech_loramac_app_skey, skey, LORAMAC_APPSKEY_LEN); + memcpy(mac->appskey, skey, LORAMAC_APPSKEY_LEN); } -void semtech_loramac_get_appskey(uint8_t *skey) +void semtech_loramac_get_appskey(const semtech_loramac_t *mac, uint8_t *skey) { - memcpy(skey, semtech_loramac_app_skey, LORAMAC_APPSKEY_LEN); + memcpy(skey, mac->appskey, LORAMAC_APPSKEY_LEN); } -void semtech_loramac_set_nwkskey(const uint8_t *skey) +void semtech_loramac_set_nwkskey(semtech_loramac_t *mac, const uint8_t *skey) { - memcpy(semtech_loramac_nwk_skey, skey, LORAMAC_NWKSKEY_LEN); + memcpy(mac->nwkskey, skey, LORAMAC_NWKSKEY_LEN); } -void semtech_loramac_get_nwkskey(uint8_t *skey) +void semtech_loramac_get_nwkskey(const semtech_loramac_t *mac, uint8_t *skey) { - memcpy(skey, semtech_loramac_nwk_skey, LORAMAC_NWKSKEY_LEN); + memcpy(skey, mac->nwkskey, LORAMAC_NWKSKEY_LEN); } -void semtech_loramac_set_devaddr(const uint8_t *addr) +void semtech_loramac_set_devaddr(semtech_loramac_t *mac, const uint8_t *addr) { - memcpy(semtech_loramac_dev_addr, addr, LORAMAC_DEVADDR_LEN); + memcpy(mac->devaddr, addr, LORAMAC_DEVADDR_LEN); } -void semtech_loramac_get_devaddr(uint8_t *addr) +void semtech_loramac_get_devaddr(const semtech_loramac_t *mac, uint8_t *addr) { - memcpy(addr, semtech_loramac_dev_addr, LORAMAC_DEVADDR_LEN); + memcpy(addr, mac->devaddr, LORAMAC_DEVADDR_LEN); } -void semtech_loramac_set_class(loramac_class_t cls) +void semtech_loramac_set_class(semtech_loramac_t *mac, loramac_class_t cls) { + mutex_lock(&mac->lock); DEBUG("[semtech-loramac] set class %d\n", cls); MibRequestConfirm_t mibReq; mibReq.Type = MIB_DEVICE_CLASS; mibReq.Param.Class = (DeviceClass_t)cls; LoRaMacMibSetRequestConfirm(&mibReq); + mutex_unlock(&mac->lock); } -loramac_class_t semtech_loramac_get_class(void) +loramac_class_t semtech_loramac_get_class(semtech_loramac_t *mac) { + mutex_lock(&mac->lock); + loramac_class_t cls; DEBUG("[semtech-loramac] get device class\n"); MibRequestConfirm_t mibReq; mibReq.Type = MIB_DEVICE_CLASS; LoRaMacMibGetRequestConfirm(&mibReq); - return (loramac_class_t)mibReq.Param.Class; + cls = (loramac_class_t)mibReq.Param.Class; + mutex_unlock(&mac->lock); + return cls; } -void semtech_loramac_set_dr(uint8_t dr) +void semtech_loramac_set_dr(semtech_loramac_t *mac, uint8_t dr) { + mutex_lock(&mac->lock); DEBUG("[semtech-loramac] set dr %d\n", dr); MibRequestConfirm_t mibReq; mibReq.Type = MIB_CHANNELS_DEFAULT_DATARATE; mibReq.Param.ChannelsDatarate = dr; LoRaMacMibSetRequestConfirm(&mibReq); + mutex_unlock(&mac->lock); } -uint8_t semtech_loramac_get_dr(void) +uint8_t semtech_loramac_get_dr(semtech_loramac_t *mac) { + mutex_lock(&mac->lock); DEBUG("[semtech-loramac] get dr\n"); + uint8_t datarate; MibRequestConfirm_t mibReq; mibReq.Type = MIB_CHANNELS_DEFAULT_DATARATE; LoRaMacMibGetRequestConfirm(&mibReq); - return (uint8_t)mibReq.Param.ChannelsDatarate; + datarate = (uint8_t)mibReq.Param.ChannelsDatarate; + mutex_unlock(&mac->lock); + return datarate; } -void semtech_loramac_set_adr(bool adr) +void semtech_loramac_set_adr(semtech_loramac_t *mac, bool adr) { + mutex_lock(&mac->lock); DEBUG("[semtech-loramac] set adr %d\n", adr); MibRequestConfirm_t mibReq; mibReq.Type = MIB_ADR; mibReq.Param.AdrEnable = adr; LoRaMacMibSetRequestConfirm(&mibReq); + mutex_unlock(&mac->lock); } -bool semtech_loramac_get_adr(void) +bool semtech_loramac_get_adr(semtech_loramac_t *mac) { + mutex_lock(&mac->lock); + bool enable; DEBUG("[semtech-loramac] get adr\n"); MibRequestConfirm_t mibReq; mibReq.Type = MIB_ADR; LoRaMacMibGetRequestConfirm(&mibReq); - return mibReq.Param.AdrEnable; + enable = mibReq.Param.AdrEnable; + mutex_unlock(&mac->lock); + return enable; } -void semtech_loramac_set_public_network(bool public) +void semtech_loramac_set_public_network(semtech_loramac_t *mac, bool public) { + mutex_lock(&mac->lock); DEBUG("[semtech-loramac] set public network %d\n", public); MibRequestConfirm_t mibReq; mibReq.Type = MIB_PUBLIC_NETWORK; mibReq.Param.EnablePublicNetwork = public; LoRaMacMibSetRequestConfirm(&mibReq); + mutex_unlock(&mac->lock); } -bool semtech_loramac_get_public_network(void) +bool semtech_loramac_get_public_network(semtech_loramac_t *mac) { + mutex_lock(&mac->lock); + bool enable; DEBUG("[semtech-loramac] get public network\n"); MibRequestConfirm_t mibReq; mibReq.Type = MIB_PUBLIC_NETWORK; LoRaMacMibGetRequestConfirm(&mibReq); - return mibReq.Param.EnablePublicNetwork; + enable = mibReq.Param.EnablePublicNetwork; + mutex_unlock(&mac->lock); + return enable; } -void semtech_loramac_set_netid(uint32_t netid) +void semtech_loramac_set_netid(semtech_loramac_t *mac, uint32_t netid) { + mutex_lock(&mac->lock); DEBUG("[semtech-loramac] set NetID %lu\n", netid); MibRequestConfirm_t mibReq; mibReq.Type = MIB_NET_ID; mibReq.Param.NetID = netid; LoRaMacMibSetRequestConfirm(&mibReq); + mutex_unlock(&mac->lock); } -uint32_t semtech_loramac_get_netid(void) +uint32_t semtech_loramac_get_netid(semtech_loramac_t *mac) { + mutex_lock(&mac->lock); + uint32_t netid; DEBUG("[semtech-loramac] get NetID\n"); MibRequestConfirm_t mibReq; mibReq.Type = MIB_NET_ID; LoRaMacMibGetRequestConfirm(&mibReq); - return mibReq.Param.NetID; + netid = mibReq.Param.NetID; + mutex_unlock(&mac->lock); + return netid; } -void semtech_loramac_set_tx_power(uint8_t power) +void semtech_loramac_set_tx_power(semtech_loramac_t *mac, uint8_t power) { + mutex_lock(&mac->lock); DEBUG("[semtech-loramac] set TX power %d\n", power); MibRequestConfirm_t mibReq; mibReq.Type = MIB_CHANNELS_TX_POWER; mibReq.Param.ChannelsTxPower = power; LoRaMacMibSetRequestConfirm(&mibReq); + mutex_unlock(&mac->lock); } -uint8_t semtech_loramac_get_tx_power(void) +uint8_t semtech_loramac_get_tx_power(semtech_loramac_t *mac) { + mutex_lock(&mac->lock); + uint8_t tx_power; DEBUG("[semtech-loramac] get TX power\n"); MibRequestConfirm_t mibReq; mibReq.Type = MIB_CHANNELS_TX_POWER; LoRaMacMibGetRequestConfirm(&mibReq); - return (uint8_t)mibReq.Param.ChannelsTxPower; + tx_power = (uint8_t)mibReq.Param.ChannelsTxPower; + mutex_unlock(&mac->lock); + return tx_power; +} + +void semtech_loramac_set_tx_port(semtech_loramac_t *mac, uint8_t port) +{ + mac->port = port; +} + +uint8_t semtech_loramac_get_tx_port(semtech_loramac_t *mac) +{ + return mac->port; +} + +void semtech_loramac_set_tx_mode(semtech_loramac_t *mac, uint8_t mode) +{ + mac->cnf = mode; +} + +uint8_t semtech_loramac_get_tx_mode(semtech_loramac_t *mac) +{ + return mac->cnf; +} + +static void _semtech_loramac_set_rx2_params(semtech_loramac_channel_params_t params) +{ + Rx2ChannelParams_t p; + p.Frequency = params.frequency; + p.Datarate = params.datarate; + + MibRequestConfirm_t mibReq; + mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; + mibReq.Param.Rx2DefaultChannel = p; + LoRaMacMibSetRequestConfirm(&mibReq); + + mibReq.Type = MIB_RX2_CHANNEL; + mibReq.Param.Rx2Channel = p; + LoRaMacMibSetRequestConfirm(&mibReq); } -void semtech_loramac_set_rx2_freq(uint8_t freq) +void semtech_loramac_set_rx2_freq(semtech_loramac_t *mac, uint32_t freq) { - Rx2ChannelParams_t params; + mutex_lock(&mac->lock); + DEBUG("[semtech-loramac] setting RX2 freq to %lu\n", freq); + Rx2ChannelParams_t p; MibRequestConfirm_t mibReq; mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; LoRaMacMibGetRequestConfirm(&mibReq); - params.Frequency = freq; - params.Datarate = mibReq.Param.Rx2DefaultChannel.Datarate; - _loramac_set_rx2_params(params.Frequency, params.Datarate); + p.Frequency = freq; + p.Datarate = mibReq.Param.Rx2DefaultChannel.Datarate; + semtech_loramac_channel_params_t params; + params.frequency = freq; + params.datarate = p.Datarate; + _semtech_loramac_set_rx2_params(params); + mutex_unlock(&mac->lock); } -uint32_t semtech_loramac_get_rx2_freq(void) +uint32_t semtech_loramac_get_rx2_freq(semtech_loramac_t *mac) { + mutex_lock(&mac->lock); + uint32_t freq; + DEBUG("[semtech-loramac] getting RX2 freq\n"); MibRequestConfirm_t mibReq; mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; LoRaMacMibGetRequestConfirm(&mibReq); - return mibReq.Param.Rx2DefaultChannel.Frequency; + freq = mibReq.Param.Rx2DefaultChannel.Frequency; + mutex_unlock(&mac->lock); + return freq; } -void semtech_loramac_set_rx2_dr(uint8_t dr) +void semtech_loramac_set_rx2_dr(semtech_loramac_t *mac, uint8_t dr) { - Rx2ChannelParams_t params; + mutex_lock(&mac->lock); + DEBUG("[semtech-loramac] setting RX2 datarate to %d\n", dr); + Rx2ChannelParams_t p; MibRequestConfirm_t mibReq; mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; LoRaMacMibGetRequestConfirm(&mibReq); - params.Datarate = dr; - params.Frequency = mibReq.Param.Rx2DefaultChannel.Frequency; - _loramac_set_rx2_params(params.Frequency, params.Datarate); + p.Datarate = dr; + p.Frequency = mibReq.Param.Rx2DefaultChannel.Frequency; + semtech_loramac_channel_params_t params; + params.datarate = dr; + params.frequency = p.Frequency; + _semtech_loramac_set_rx2_params(params); + mutex_unlock(&mac->lock); } -uint8_t semtech_loramac_get_rx2_dr(void) +uint8_t semtech_loramac_get_rx2_dr(semtech_loramac_t *mac) { + mutex_lock(&mac->lock); + uint8_t datarate; + DEBUG("[semtech-loramac] getting RX2 datarate\n"); MibRequestConfirm_t mibReq; mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; LoRaMacMibGetRequestConfirm(&mibReq); - return mibReq.Param.Rx2DefaultChannel.Datarate; + datarate = mibReq.Param.Rx2DefaultChannel.Datarate; + mutex_unlock(&mac->lock); + return datarate; } diff --git a/pkg/semtech-loramac/contrib/semtech_loramac_timer.c b/pkg/semtech-loramac/contrib/semtech_loramac_timer.c index 885e16ca53..0c62722c7d 100644 --- a/pkg/semtech-loramac/contrib/semtech_loramac_timer.c +++ b/pkg/semtech-loramac/contrib/semtech_loramac_timer.c @@ -60,6 +60,10 @@ void TimerSetValue(TimerEvent_t *obj, uint32_t value) xtimer_remove(&(obj->dev)); } + /* According to the lorawan specifications, the data sent from the gateway + could arrive with a short shift in time of +/- 20ms. Here the timeout is + triggered 50ms in advance to make sure the radio switches to RX mode on + time and doesn't miss any downlink messages. */ obj->timeout = (value - 50) * 1000; } diff --git a/pkg/semtech-loramac/include/semtech_loramac.h b/pkg/semtech-loramac/include/semtech_loramac.h index 66897dac0b..321d626d32 100644 --- a/pkg/semtech-loramac/include/semtech_loramac.h +++ b/pkg/semtech-loramac/include/semtech_loramac.h @@ -24,6 +24,10 @@ extern "C" { #endif #include <inttypes.h> + +#include "mutex.h" + +#include "net/netdev.h" #include "net/loramac.h" #include "sx127x.h" @@ -37,7 +41,9 @@ extern "C" { #define MSG_TYPE_TX_TIMEOUT (0x3458) /**< radio driver TX timeout */ #define MSG_TYPE_MAC_TIMEOUT (0x3459) /**< MAC timers timeout */ #define MSG_TYPE_LORAMAC_CMD (0x3460) /**< Command sent to the MAC */ -#define MSG_TYPE_LORAMAC_NOTIFY (0x3461) /**< MAC notifications */ +#define MSG_TYPE_LORAMAC_JOIN (0x3461) /**< MAC join event */ +#define MSG_TYPE_LORAMAC_TX_DONE (0x3462) /**< MAC TX completes */ +#define MSG_TYPE_LORAMAC_RX (0x3463) /**< Some data received */ /** @} */ /** @@ -46,16 +52,34 @@ extern "C" { #define LORAWAN_APP_DATA_MAX_SIZE (242U) /** - * @brief LoRaMAC status + * @brief LoRaMAC return status */ enum { SEMTECH_LORAMAC_JOIN_SUCCEEDED, /**< Join procedure succeeded */ SEMTECH_LORAMAC_JOIN_FAILED, /**< Join procedure failed */ SEMTECH_LORAMAC_NOT_JOINED, /**< MAC is not joined */ + SEMTECH_LORAMAC_TX_SCHEDULED, /**< TX data scheduled */ SEMTECH_LORAMAC_TX_DONE, /**< Transmission completed */ - SEMTECH_LORAMAC_RX_DATA, /**< Data received */ + SEMTECH_LORAMAC_DATA_RECEIVED, /**< Data received */ + SEMTECH_LORAMAC_BUSY /**< Internal MAC is busy */ +}; + +/** + * @brief LoRaMAC internal state + */ +enum { + SEMTECH_LORAMAC_STATE_IDLE = 0, + SEMTECH_LORAMAC_STATE_BUSY }; +/** + * @brief LoRaMAC channel radio parameters + */ +typedef struct { + uint32_t frequency; /**< channel center frequency */ + uint8_t datarate; /**< channel datarate */ +} semtech_loramac_channel_params_t; + /** * @brief Structure containing LoRaWAN RX data */ @@ -66,237 +90,337 @@ typedef struct { } semtech_loramac_rx_data_t; /** - * @brief Initializes semtech loramac + * @brief Semtech LoRaMAC descriptor + */ +typedef struct { + mutex_t lock; /**< loramac access lock */ + uint8_t state; /**< internal loramac state */ + uint8_t caller_pid; /**< pid of caller thread */ + uint8_t port; /**< application TX port */ + uint8_t cnf; /**< enable/disable confirmable messages */ + uint8_t deveui[LORAMAC_DEVEUI_LEN]; /**< device EUI */ + uint8_t appeui[LORAMAC_APPEUI_LEN]; /**< application EUI */ + uint8_t appkey[LORAMAC_APPKEY_LEN]; /**< application key */ + uint8_t appskey[LORAMAC_APPSKEY_LEN]; /**< application session key */ + uint8_t nwkskey[LORAMAC_NWKSKEY_LEN]; /**< network session key */ + uint8_t devaddr[LORAMAC_DEVADDR_LEN]; /**< device address */ + semtech_loramac_rx_data_t rx_data; /**< struct handling the RX data */ +} semtech_loramac_t; + +/** + * @brief Initializes the semtech loramac mac * - * @param[in] dev pointer to the radio device + * @param[in] mac Pointer to loramac descriptor * * @return 0 on success * @return -1 on failure */ -int semtech_loramac_init(sx127x_t *dev); +int semtech_loramac_init(semtech_loramac_t *mac); /** * @brief Starts a LoRaWAN network join procedure * + * This function blocks until the join procedure succeeds or fails. + * + * @param[in] mac Pointer to the mac * @param[in] type The type of join procedure (otaa or abp) * * @return SEMTECH_LORAMAC_JOIN_SUCCEEDED on success * @return SEMTECH_LORAMAC_JOIN_FAILED on failure + * @return SEMTECH_LORAMAC_BUSY when the mac is already active (join or tx in progress) */ -uint8_t semtech_loramac_join(uint8_t type); +uint8_t semtech_loramac_join(semtech_loramac_t *mac, uint8_t type); /** - * @brief Sends data to LoRaWAN + * @brief Sends data to the LoRaWAN network + * + * This function returns immediately and leave the mac in busy state until a + * message is received from the network (with RX1 and RX2 receive windows). + * @see semtech_loramac_recv * - * @param[in] cnf Use confirmable/unconfirmable send type - * @param[in] port The send port to use (between 1 and 223) - * @param[in] tx_buf The TX buffer - * @param[in] tx_len The length of the TX buffer - * @param[out] rx_data The RX data descriptor + * @param[in] mac Pointer to the mac + * @param[in] data The TX data + * @param[in] len The length of the TX data * * @return SEMTECH_LORAMAC_NOT_JOINED when the network is not joined + * @return SEMTECH_LORAMAC_BUSY when the mac is already active (join or tx in progress) + * @return SEMTECH_LORAMAC_TX_SCHEDULED when the TX is scheduled in the mac + */ +uint8_t semtech_loramac_send(semtech_loramac_t *mac, uint8_t *data, uint8_t len); + +/** + * @brief Wait for a message sent by the LoRaWAN network + * + * This function blocks until a single message is received by the mac (RX1 and + * RX2 windows). + * With a class A device, a message can only be received after a send. With a + * class C device, a message can be received at any time. In this case, this + * function can be used in a dedicated listener thread. + * + * @see semtech_loramac_send + * + * @param[in] mac Pointer to the mac + * * @return SEMTECH_LORAMAC_TX_DONE when TX has completed, no data received - * @return SEMTECH_LORAMAC_RX_DATA when TX has completed and data is received + * @return SEMTECH_LORAMAC_DATA_RECEIVED when TX has completed and data is received */ -uint8_t semtech_loramac_send(uint8_t cnf, uint8_t port, - uint8_t *tx_buf, uint8_t tx_len, - semtech_loramac_rx_data_t *rx_data); +uint8_t semtech_loramac_recv(semtech_loramac_t *mac); /** * @brief Sets the device EUI * - * @param[in] eui The device EUI + * @param[in] mac Pointer to the mac + * @param[in] eui The device EUI */ -void semtech_loramac_set_deveui(const uint8_t *eui); +void semtech_loramac_set_deveui(semtech_loramac_t *mac, const uint8_t *eui); /** * @brief Gets the device EUI * - * @param[out] eui The device EUI + * @param[in] mac Pointer to the mac + * @param[out] eui The device EUI */ -void semtech_loramac_get_deveui(uint8_t *eui); +void semtech_loramac_get_deveui(const semtech_loramac_t *mac, uint8_t *eui); /** * @brief Sets the application EUI * - * @param[in] eui The application EUI + * @param[in] mac Pointer to the mac + * @param[in] eui The application EUI */ -void semtech_loramac_set_appeui(const uint8_t *eui); +void semtech_loramac_set_appeui(semtech_loramac_t *mac, const uint8_t *eui); /** * @brief Gets the application EUI * - * @param[out] eui The application EUI + * @param[in] mac Pointer to the mac + * @param[out] eui The application EUI */ -void semtech_loramac_get_appeui(uint8_t *eui); +void semtech_loramac_get_appeui(const semtech_loramac_t *mac, uint8_t *eui); /** * @brief Sets the application key * - * @param[in] key The application key + * @param[in] mac Pointer to the mac + * @param[in] key The application key */ -void semtech_loramac_set_appkey(const uint8_t *key); +void semtech_loramac_set_appkey(semtech_loramac_t *mac, const uint8_t *key); /** * @brief Gets the application key * - * @param[in] key The application key + * @param[in] mac Pointer to the mac + * @param[in] key The application key */ -void semtech_loramac_get_appkey(uint8_t *key); +void semtech_loramac_get_appkey(const semtech_loramac_t *mac, uint8_t *key); /** * @brief Sets the application session key * - * @param[in] skey The application session key + * @param[in] mac Pointer to the mac + * @param[in] skey The application session key */ -void semtech_loramac_set_appskey(const uint8_t *skey); +void semtech_loramac_set_appskey(semtech_loramac_t *mac, const uint8_t *skey); /** * @brief Gets the application session key * - * @param[in] skey The application session key + * @param[in] mac Pointer to the mac + * @param[in] skey The application session key */ -void semtech_loramac_get_appskey(uint8_t *skey); +void semtech_loramac_get_appskey(const semtech_loramac_t *mac, uint8_t *skey); /** * @brief Sets the network session key * - * @param[in] skey The network session key + * @param[in] mac Pointer to the mac + * @param[in] skey The network session key */ -void semtech_loramac_set_nwkskey(const uint8_t *skey); +void semtech_loramac_set_nwkskey(semtech_loramac_t *mac, const uint8_t *skey); /** * @brief Gets the network session key * - * @param[in] skey The network session key + * @param[in] mac Pointer to the mac + * @param[in] skey The network session key */ -void semtech_loramac_get_nwkskey(uint8_t *skey); +void semtech_loramac_get_nwkskey(const semtech_loramac_t *mac, uint8_t *skey); /** * @brief Sets the device address * - * @param[in] addr The device address + * @param[in] mac Pointer to the mac + * @param[in] addr The device address */ -void semtech_loramac_set_devaddr(const uint8_t *addr); +void semtech_loramac_set_devaddr(semtech_loramac_t *mac, const uint8_t *addr); /** * @brief Gets the device address * - * @param[in] addr The device address + * @param[in] mac Pointer to the mac + * @param[in] addr The device address */ -void semtech_loramac_get_devaddr(uint8_t *addr); +void semtech_loramac_get_devaddr(const semtech_loramac_t *mac, uint8_t *addr); /** * @brief Sets the device class * - * @param[in] cls The device class + * @param[in] mac Pointer to the mac + * @param[in] cls The device class */ -void semtech_loramac_set_class(loramac_class_t cls); +void semtech_loramac_set_class(semtech_loramac_t *mac, loramac_class_t cls); /** * @brief Gets the device class * + * @param[in] mac Pointer to the mac * @return The device class */ -loramac_class_t semtech_loramac_get_class(void); +loramac_class_t semtech_loramac_get_class(semtech_loramac_t *mac); /** * @brief Sets the channels datarate * + * @param[in] mac Pointer to the mac * @param[in] dr The datarate (from 1 to 16) */ -void semtech_loramac_set_dr(uint8_t dr); +void semtech_loramac_set_dr(semtech_loramac_t *mac, uint8_t dr); /** * @brief Gets the channels datarate * + * @param[in] mac Pointer to the mac * @return The datarate (from 1 to 16) */ -uint8_t semtech_loramac_get_dr(void); +uint8_t semtech_loramac_get_dr(semtech_loramac_t *mac); /** * @brief Enables/disable adaptive datarate * - * @param[in] adr Adaptive datarate mode + * @param[in] mac Pointer to the mac + * @param[in] adr Adaptive datarate mode */ -void semtech_loramac_set_adr(bool adr); +void semtech_loramac_set_adr(semtech_loramac_t *mac, bool adr); /** * @brief Checks if adaptive datarate is set * - * @return true if adr is on, false otherwise + * @param[in] mac Pointer to the mac + * @return true if adr is on, false otherwise */ -bool semtech_loramac_get_adr(void); +bool semtech_loramac_get_adr(semtech_loramac_t *mac); /** * @brief Enable/disable the public network mode * - * @param[in] public The public network mode + * @param[in] mac Pointer to the mac + * @param[in] public The public network mode */ -void semtech_loramac_set_public_network(bool public); +void semtech_loramac_set_public_network(semtech_loramac_t *mac, bool public); /** * @brief Checks if public network is set * + * @param[in] mac Pointer to the mac * @return true if public network is on, false otherwise */ -bool semtech_loramac_get_public_network(void); +bool semtech_loramac_get_public_network(semtech_loramac_t *mac); /** * @brief Sets the NetID (only useful with ABP join procedure) * + * @param[in] mac Pointer to the mac * @param[in] netid The NetID */ -void semtech_loramac_set_netid(uint32_t netid); +void semtech_loramac_set_netid(semtech_loramac_t *mac, uint32_t netid); /** * @brief Gets the NetID * + * @param[in] mac Pointer to the mac * @return The NetID */ -uint32_t semtech_loramac_get_netid(void); +uint32_t semtech_loramac_get_netid(semtech_loramac_t *mac); /** * @brief Sets the channels TX power index * + * @param[in] mac Pointer to the mac * @param[in] power The TX power index (from 1 to 16) */ -void semtech_loramac_set_tx_power(uint8_t power); +void semtech_loramac_set_tx_power(semtech_loramac_t *mac, uint8_t power); /** * @brief Gets the channels TX power index * + * @param[in] mac Pointer to the mac * @return The TX power index (from 1 to 16) */ -uint8_t semtech_loramac_get_tx_power(void); +uint8_t semtech_loramac_get_tx_power(semtech_loramac_t *mac); + +/** + * @brief Sets the TX application port + * + * @param[in] mac Pointer to the mac + * @param[in] port The TX application port + */ +void semtech_loramac_set_tx_port(semtech_loramac_t *mac, uint8_t port); + +/** + * @brief Gets the TX application port + * + * @param[in] mac Pointer to the mac + * @return The TX application port + */ +uint8_t semtech_loramac_get_tx_port(semtech_loramac_t *mac); + +/** + * @brief Sets the TX confirmable mode + * + * @param[in] mac Pointer to the mac + * @param[in] mode The TX mode (confirmable or not confirmable) + */ +void semtech_loramac_set_tx_mode(semtech_loramac_t *mac, uint8_t mode); + +/** + * @brief Gets the TX confirmable mode + * + * @param[in] mac Pointer to the mac + * @return The TX mode (confirmable or not confirmable) + */ +uint8_t semtech_loramac_get_tx_mode(semtech_loramac_t *mac); /** * @brief Sets the RX2 frequency * + * @param[in] mac Pointer to the mac * @param[in] freq The RX2 frequency */ -void semtech_loramac_set_rx2_freq(uint8_t freq); +void semtech_loramac_set_rx2_freq(semtech_loramac_t *mac, uint32_t freq); /** * @brief Gets the RX2 frequency * + * @param[in] mac Pointer to the mac * @return The RX2 frequency */ -uint32_t semtech_loramac_get_rx2_freq(void); +uint32_t semtech_loramac_get_rx2_freq(semtech_loramac_t *mac); /** * @brief Sets the RX2 datarate * + * @param[in] mac Pointer to the mac * @param[in] dr The RX2 datarate */ -void semtech_loramac_set_rx2_dr(uint8_t dr); +void semtech_loramac_set_rx2_dr(semtech_loramac_t *mac, uint8_t dr); /** * @brief Gets the RX2 datarate * + * @param[in] mac Pointer to the mac * @return The RX2 datarate */ -uint8_t semtech_loramac_get_rx2_dr(void); +uint8_t semtech_loramac_get_rx2_dr(semtech_loramac_t *mac); #ifdef __cplusplus } -- GitLab