diff --git a/doc/releases/release-notes-4.2.rst b/doc/releases/release-notes-4.2.rst index 59346c68a58..bbfa68a494d 100644 --- a/doc/releases/release-notes-4.2.rst +++ b/doc/releases/release-notes-4.2.rst @@ -172,6 +172,9 @@ New APIs and options * :c:func:`util_eq` * :c:func:`util_memeq` +* LoRaWAN + * :c:func:`lorawan_request_link_check` + New Boards ********** diff --git a/include/zephyr/lorawan/lorawan.h b/include/zephyr/lorawan/lorawan.h index 6644c0c5156..9f8688189cb 100644 --- a/include/zephyr/lorawan/lorawan.h +++ b/include/zephyr/lorawan/lorawan.h @@ -217,6 +217,14 @@ typedef uint8_t (*lorawan_battery_level_cb_t)(void); */ typedef void (*lorawan_dr_changed_cb_t)(enum lorawan_datarate dr); +/** + * @brief Defines the link check answer handler function signature. + * + * @param demod_margin The demodulation margin in db. + * @param nb_gateways The number of gateways the device is connected to. + */ +typedef void (*lorawan_link_check_ans_cb_t)(uint8_t demod_margin, uint8_t nb_gateways); + /** * @brief Defines the user's descriptor callback handler function signature. * @@ -267,6 +275,14 @@ void lorawan_register_downlink_callback(struct lorawan_downlink_cb *cb); */ void lorawan_register_dr_changed_callback(lorawan_dr_changed_cb_t cb); +/** + * @brief Register a callback to be called when getting answer + * a to check link request. + * + * @param cb Pointer to link check ans callback + */ +void lorawan_register_link_check_ans_callback(lorawan_link_check_ans_cb_t cb); + /** * @brief Join the LoRaWAN network * @@ -426,6 +442,18 @@ int lorawan_request_device_time(bool force_request); */ int lorawan_device_time_get(uint32_t *gps_time); +/** + * @brief Request for link check according to LinkCheckReq MAC cmd + * + * Append MAC LinkCheckReq command. It will be processed on next send + * message or force sending empty message to request time immediately. + * + * @param force_request Immediately send an empty message to execute the request + * + * @return 0 if successful, negative errno otherwise + */ +int lorawan_request_link_check(bool force_request); + #ifdef CONFIG_LORAWAN_APP_CLOCK_SYNC /** diff --git a/subsys/lorawan/lorawan.c b/subsys/lorawan/lorawan.c index 0f3c777fece..5a55281d086 100644 --- a/subsys/lorawan/lorawan.c +++ b/subsys/lorawan/lorawan.c @@ -93,6 +93,7 @@ static enum lorawan_channels_mask_size region_channels_mask_size = static lorawan_battery_level_cb_t battery_level_cb; static lorawan_dr_changed_cb_t dr_changed_cb; +static lorawan_link_check_ans_cb_t link_check_cb; /* implementation required by the soft-se (software secure element) */ void BoardGetUniqueId(uint8_t *id) @@ -213,8 +214,10 @@ static void mlme_confirm_handler(MlmeConfirm_t *mlme_confirm) LOG_INF("Joined network! DevAddr: %08x", mib_req.Param.DevAddr); break; case MLME_LINK_CHECK: - /* Not implemented */ - LOG_INF("Link check not implemented yet!"); + if (link_check_cb != NULL) { + link_check_cb(mlme_confirm->DemodMargin, mlme_confirm->NbGateways); + } + LOG_INF("Link check done"); break; case MLME_DEVICE_TIME: LOG_INF("DevTimeReq done"); @@ -399,6 +402,27 @@ int lorawan_set_region(enum lorawan_region region) return 0; } +int lorawan_request_link_check(bool force_request) +{ + int ret = 0; + LoRaMacStatus_t status; + MlmeReq_t mlme_req; + + mlme_req.Type = MLME_LINK_CHECK; + status = LoRaMacMlmeRequest(&mlme_req); + if (status != LORAMAC_STATUS_OK) { + LOG_ERR("LinkCheckReq failed: %s", lorawan_status2str(status)); + ret = lorawan_status2errno(status); + return ret; + } + + if (force_request) { + ret = lorawan_send(0U, "", 0U, LORAWAN_MSG_UNCONFIRMED); + } + + return ret; +} + int lorawan_request_device_time(bool force_request) { int ret = 0; @@ -732,6 +756,11 @@ void lorawan_register_dr_changed_callback(lorawan_dr_changed_cb_t cb) dr_changed_cb = cb; } +void lorawan_register_link_check_ans_callback(lorawan_link_check_ans_cb_t cb) +{ + link_check_cb = cb; +} + int lorawan_start(void) { LoRaMacStatus_t status;