Skip to content

Commit

Permalink
lib: lte_link_control: refactor into modules
Browse files Browse the repository at this point in the history
Divides the LTE Link Controller into modules.

Signed-off-by: Mirko Covizzi <mirko.covizzi@nordicsemi.no>
  • Loading branch information
MirkoCovizzi committed Sep 27, 2024
1 parent cdbb02a commit 356e8d9
Show file tree
Hide file tree
Showing 57 changed files with 4,525 additions and 1,682 deletions.
2 changes: 2 additions & 0 deletions applications/asset_tracker_v2/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ CONFIG_LTE_PSM_REQ=y
CONFIG_LTE_PSM_REQ_RPTAU="11000001"
### 20 seconds active time.
CONFIG_LTE_PSM_REQ_RAT="00001010"
CONFIG_LTE_LC_EDRX=y
CONFIG_LTE_LC_NCELLMEAS=y

# Settings - Used to store real-time device configuration to flash.
CONFIG_SETTINGS=y
Expand Down
20 changes: 20 additions & 0 deletions include/modem/lte_lc.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,21 +214,25 @@ enum lte_lc_evt_type {
*/
LTE_LC_EVT_NW_REG_STATUS,

#if defined(CONFIG_LTE_LC_PSM) || defined(__DOXYGEN__)
/**
* PSM parameters provided by the network.
*
* The associated payload is the @c lte_lc_evt.psm_cfg member of type
* @ref lte_lc_psm_cfg in the event.
*/
LTE_LC_EVT_PSM_UPDATE,
#endif

#if defined(CONFIG_LTE_LC_EDRX) || defined(__DOXYGEN__)
/**
* eDRX parameters provided by the network.
*
* The associated payload is the @c lte_lc_evt.edrx_cfg member of type
* @ref lte_lc_edrx_cfg in the event.
*/
LTE_LC_EVT_EDRX_UPDATE,
#endif

/**
* RRC connection state.
Expand Down Expand Up @@ -272,14 +276,17 @@ enum lte_lc_evt_type {
*/
LTE_LC_EVT_TAU_PRE_WARNING,

#if defined(CONFIG_LTE_LC_NCELLMEAS) || defined(__DOXYGEN__)
/**
* Neighbor cell measurement results.
*
* The associated payload is the @c lte_lc_evt.cells_info member of type
* @ref lte_lc_cells_info in the event.
*/
LTE_LC_EVT_NEIGHBOR_CELL_MEAS,
#endif

#if defined(CONFIG_LTE_LC_XMODEMSLEEP) || defined(__DOXYGEN__)
/**
* Modem sleep pre-warning.
*
Expand Down Expand Up @@ -308,6 +315,7 @@ enum lte_lc_evt_type {
* the duration of the sleep.
*/
LTE_LC_EVT_MODEM_SLEEP_ENTER,
#endif

/**
* Information about modem operation.
Expand All @@ -317,6 +325,7 @@ enum lte_lc_evt_type {
*/
LTE_LC_EVT_MODEM_EVENT,

#if defined(CONFIG_LTE_LC_RAI) || defined(__DOXYGEN__)
/**
* Information about RAI (Release Assistance Indication) configuration.
*
Expand All @@ -326,6 +335,7 @@ enum lte_lc_evt_type {
* @note This event is only supported by modem firmware versions >= 2.0.2.
*/
LTE_LC_EVT_RAI_UPDATE,
#endif
};

/** RRC connection state. */
Expand Down Expand Up @@ -1198,23 +1208,29 @@ struct lte_lc_evt {
/** Payload for event @ref LTE_LC_EVT_RRC_UPDATE. */
enum lte_lc_rrc_mode rrc_mode;

#if defined(CONFIG_LTE_LC_PSM) || defined(__DOXYGEN__)
/** Payload for event @ref LTE_LC_EVT_PSM_UPDATE. */
struct lte_lc_psm_cfg psm_cfg;
#endif

#if defined(CONFIG_LTE_LC_EDRX) || defined(__DOXYGEN__)
/** Payload for event @ref LTE_LC_EVT_EDRX_UPDATE. */
struct lte_lc_edrx_cfg edrx_cfg;
#endif

/** Payload for event @ref LTE_LC_EVT_CELL_UPDATE. */
struct lte_lc_cell cell;

/** Payload for event @ref LTE_LC_EVT_LTE_MODE_UPDATE. */
enum lte_lc_lte_mode lte_mode;

#if defined(CONFIG_LTE_LC_XMODEMSLEEP) || defined(__DOXYGEN__)
/**
* Payload for events @ref LTE_LC_EVT_MODEM_SLEEP_EXIT_PRE_WARNING,
* @ref LTE_LC_EVT_MODEM_SLEEP_EXIT and @ref LTE_LC_EVT_MODEM_SLEEP_ENTER.
*/
struct lte_lc_modem_sleep modem_sleep;
#endif

/** Payload for event @ref LTE_LC_EVT_MODEM_EVENT. */
enum lte_lc_modem_evt modem_evt;
Expand All @@ -1226,11 +1242,15 @@ struct lte_lc_evt {
*/
uint64_t time;

#if defined(CONFIG_LTE_LC_NCELLMEAS) || defined(__DOXYGEN__)
/** Payload for event @ref LTE_LC_EVT_NEIGHBOR_CELL_MEAS. */
struct lte_lc_cells_info cells_info;
#endif

#if defined(CONFIG_LTE_LC_RAI) || defined(__DOXYGEN__)
/** Payload for event @ref LTE_LC_EVT_RAI_UPDATE. */
struct lte_lc_rai_cfg rai_cfg;
#endif
};
};

Expand Down
2 changes: 2 additions & 0 deletions lib/location/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ config LOCATION_METHOD_GNSS
bool "Allow GNSS to be used for obtaining the location"
depends on NRF_MODEM_LIB
depends on LTE_LINK_CONTROL
depends on LTE_LC_PSM
depends on LTE_LC_XMODEMSLEEP
default y

config LOCATION_METHOD_CELLULAR
Expand Down
5 changes: 4 additions & 1 deletion lib/lte_link_control/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
#

zephyr_library()
zephyr_library_include_directories(include)
zephyr_library_sources(lte_lc.c)
zephyr_library_sources(lte_lc_helpers.c)
zephyr_library_sources(lte_lc_modem_hooks.c)
zephyr_library_sources_ifdef(CONFIG_LTE_LC_TRACE lte_lc_trace.c)
zephyr_library_sources_ifdef(CONFIG_LTE_SHELL lte_lc_shell.c)

add_subdirectory(common)
add_subdirectory(modules)

zephyr_linker_sources(RODATA lte_lc.ld)
4 changes: 4 additions & 0 deletions lib/lte_link_control/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ config LTE_PSM_REQ
If this option is set the library will automatically request PSM when
the modem is initialized. This will cause the modem to include a PSM request in
every subsequent LTE attach request.
select LTE_LC_PSM

choice LTE_PSM_REQ_FORMAT
prompt "Format for PSM configuration"
Expand Down Expand Up @@ -129,6 +130,7 @@ config LTE_EDRX_REQ
help
Enable request for use of eDRX using AT+CEDRXS.
For reference, see 3GPP 27.007 Ch. 7.40.
select LTE_LC_EDRX

config LTE_EDRX_REQ_VALUE_LTE_M
string "Requested eDRX value for LTE-M"
Expand Down Expand Up @@ -354,4 +356,6 @@ module-dep = LOG
module-str = LTE link control library
source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config"

rsource "modules/Kconfig"

endif # LTE_LINK_CONTROL
9 changes: 9 additions & 0 deletions lib/lte_link_control/common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

zephyr_library_sources(event_handler_list.c)
zephyr_library_sources(helpers.c)
zephyr_library_sources(work_q.c)
124 changes: 124 additions & 0 deletions lib/lte_link_control/common/event_handler_list.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include <string.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <modem/lte_lc.h>

#include <common/event_handler_list.h>

LOG_MODULE_DECLARE(lte_lc, CONFIG_LTE_LINK_CONTROL_LOG_LEVEL);

static K_MUTEX_DEFINE(list_mtx);

/**@brief List element for event handler list. */
struct event_handler {
sys_snode_t node;
lte_lc_evt_handler_t handler;
};

static sys_slist_t handler_list;

/**
* @brief Find the handler from the event handler list.
*
* @return The node or NULL if not found and its previous node in @p prev_out.
*/
static struct event_handler *event_handler_list_node_find(struct event_handler **prev_out,
lte_lc_evt_handler_t handler)
{
struct event_handler *prev = NULL, *curr;

SYS_SLIST_FOR_EACH_CONTAINER(&handler_list, curr, node) {
if (curr->handler == handler) {
*prev_out = prev;
return curr;
}
prev = curr;
}
return NULL;
}

/**@brief Add the handler in the event handler list if not already present. */
int event_handler_list_handler_append(lte_lc_evt_handler_t handler)
{
struct event_handler *to_ins;

k_mutex_lock(&list_mtx, K_FOREVER);

/* Check if handler is already registered. */
if (event_handler_list_node_find(&to_ins, handler) != NULL) {
LOG_DBG("Handler already registered. Nothing to do");
k_mutex_unlock(&list_mtx);
return 0;
}

/* Allocate memory and fill. */
to_ins = (struct event_handler *)k_malloc(sizeof(struct event_handler));
if (to_ins == NULL) {
k_mutex_unlock(&list_mtx);
return -ENOBUFS;
}
memset(to_ins, 0, sizeof(struct event_handler));
to_ins->handler = handler;

/* Insert handler in the list. */
sys_slist_append(&handler_list, &to_ins->node);
k_mutex_unlock(&list_mtx);
return 0;
}

/**@brief Remove the handler from the event handler list if registered. */
int event_handler_list_handler_remove(lte_lc_evt_handler_t handler)
{
struct event_handler *curr, *prev = NULL;

k_mutex_lock(&list_mtx, K_FOREVER);

/* Check if the handler is registered before removing it. */
curr = event_handler_list_node_find(&prev, handler);
if (curr == NULL) {
LOG_WRN("Handler not registered. Nothing to do");
k_mutex_unlock(&list_mtx);
return 0;
}

/* Remove the handler from the list. */
sys_slist_remove(&handler_list, &prev->node, &curr->node);
k_free(curr);

k_mutex_unlock(&list_mtx);
return 0;
}

/**@brief dispatch events. */
void event_handler_list_dispatch(const struct lte_lc_evt *const evt)
{
struct event_handler *curr, *tmp;

if (event_handler_list_is_empty()) {
return;
}

k_mutex_lock(&list_mtx, K_FOREVER);

/* Dispatch events to all registered handlers */
LOG_DBG("Dispatching event: type=%d", evt->type);
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&handler_list, curr, tmp, node) {
LOG_DBG(" - handler=0x%08X", (uint32_t)curr->handler);
curr->handler(evt);
}
LOG_DBG("Done");

k_mutex_unlock(&list_mtx);
}

/**@brief Test if the handler list is empty. */
bool event_handler_list_is_empty(void)
{
return sys_slist_is_empty(&handler_list);
}
88 changes: 88 additions & 0 deletions lib/lte_link_control/common/helpers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include <stdlib.h>
#include <zephyr/logging/log.h>

#include <common/helpers.h>

LOG_MODULE_DECLARE(lte_lc, CONFIG_LTE_LINK_CONTROL_LOG_LEVEL);

int string_to_int(const char *str_buf, int base, int *output)
{
int temp;
char *end_ptr;

__ASSERT_NO_MSG(str_buf != NULL);

errno = 0;
temp = strtol(str_buf, &end_ptr, base);

if (end_ptr == str_buf || *end_ptr != '\0' ||
((temp == LONG_MAX || temp == LONG_MIN) && errno == ERANGE)) {
return -ENODATA;
}

*output = temp;

return 0;
}

int string_param_to_int(struct at_parser *parser, size_t idx, int *output, int base)
{
int err;
char str_buf[16];
size_t len = sizeof(str_buf);

__ASSERT_NO_MSG(parser != NULL);
__ASSERT_NO_MSG(output != NULL);

err = at_parser_string_get(parser, idx, str_buf, &len);
if (err) {
return err;
}

if (string_to_int(str_buf, base, output)) {
return -ENODATA;
}

return 0;
}

int plmn_param_string_to_mcc_mnc(struct at_parser *parser, size_t idx, int *mcc, int *mnc)
{
int err;
char str_buf[7];
size_t len = sizeof(str_buf);

err = at_parser_string_get(parser, idx, str_buf, &len);
if (err) {
LOG_ERR("Could not get PLMN, error: %d", err);
return err;
}

str_buf[len] = '\0';

/* Read MNC and store as integer. The MNC starts as the fourth character
* in the string, following three characters long MCC.
*/
err = string_to_int(&str_buf[3], 10, mnc);
if (err) {
LOG_ERR("Could not get MNC, error: %d", err);
return err;
}

/* NUL-terminate MCC, read and store it. */
str_buf[3] = '\0';

err = string_to_int(str_buf, 10, mcc);
if (err) {
LOG_ERR("Could not get MCC, error: %d", err);
return err;
}

return 0;
}
Loading

0 comments on commit 356e8d9

Please sign in to comment.