Skip to content

Commit a926402

Browse files
jtguggedaljorgenmk
authored andcommitted
lib: lte_link_control: Add cellular profile module
Add module to configure cellular profile. This is needed for NTN + TN operation. Signed-off-by: Jan Tore Guggedal <[email protected]>
1 parent 5bdf565 commit a926402

File tree

7 files changed

+283
-31
lines changed

7 files changed

+283
-31
lines changed

doc/nrf/nrf.doxyfile.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2472,7 +2472,8 @@ PREDEFINED = __DOXYGEN__ \
24722472
"CONFIG_LTE_LC_TAU_PRE_WARNING_MODULE=y" \
24732473
"CONFIG_LTE_LC_ENV_EVAL_MODULE=y" \
24742474
"CONFIG_LTE_LC_PDN_MODULE=y" \
2475-
"CONFIG_LTE_LC_DNS_FALLBACK_MODULE=y"
2475+
"CONFIG_LTE_LC_DNS_FALLBACK_MODULE=y" \
2476+
"CONFIG_LTE_LC_CELLULAR_PROFILE_MODULE=y"
24762477

24772478

24782479
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this

include/modem/lte_lc.h

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -483,13 +483,15 @@ enum lte_lc_evt_type {
483483
LTE_LC_EVT_PDN = 14,
484484
#endif /* CONFIG_LTE_LC_PDN_MODULE */
485485

486+
#if defined(CONFIG_LTE_LC_CELLULAR_PROFILE_MODULE)
486487
/**
487488
* A cellular profile is activated for the current access technology.
488489
*
489-
* The associated payload is the @c lte_lc_evt.cellular_profile_id member in the event,
490-
* which is the cellular profile ID of the active cellular profile.
490+
* The associated payload is the @c lte_lc_evt.cellular_profile member of type
491+
* @ref lte_lc_cellular_profile_evt in the event.
491492
*/
492493
LTE_LC_EVT_CELLULAR_PROFILE_ACTIVE = 15,
494+
#endif /* CONFIG_LTE_LC_CELLULAR_PROFILE_MODULE */
493495
};
494496

495497
/** RRC connection state. */
@@ -1537,6 +1539,11 @@ struct lte_lc_pdn_evt {
15371539
int8_t cellular_profile_id;
15381540
};
15391541

1542+
struct lte_lc_cellular_profile_evt {
1543+
/** Cellular profile ID. */
1544+
int8_t profile_id;
1545+
};
1546+
15401547
/** LTE event. */
15411548
struct lte_lc_evt {
15421549
/** Event type. */
@@ -1602,6 +1609,11 @@ struct lte_lc_evt {
16021609
/** Payload for event @ref LTE_LC_EVT_PDN. */
16031610
struct lte_lc_pdn_evt pdn;
16041611
#endif /* CONFIG_LTE_LC_PDN_MODULE */
1612+
1613+
#if defined(CONFIG_LTE_LC_CELLULAR_PROFILE_MODULE)
1614+
/** Payload for event @ref LTE_LC_EVT_CELLULAR_PROFILE_ACTIVE. */
1615+
struct lte_lc_cellular_profile_evt cellular_profile;
1616+
#endif /* CONFIG_LTE_LC_CELLULAR_PROFILE_MODULE */
16051617
};
16061618
};
16071619

@@ -1678,23 +1690,51 @@ enum lte_lc_uicc {
16781690
/** Physical SIM or eSIM */
16791691
LTE_LC_UICC_PHYSICAL = 0,
16801692
/** SoftSIM */
1681-
LTE_LC_UICC_SOFTSIM = 1,
1693+
LTE_LC_UICC_SOFTSIM = 2,
1694+
};
1695+
1696+
/**
1697+
* @brief LTE access technology (AcT) bitmap.
1698+
*
1699+
* This bitmap selects which access technologies are enabled for an operation.
1700+
* It maps directly to the AcT bitmask in AT commands such as `AT%CELLULARPRFL`
1701+
* and `AT%PALL`.
1702+
*/
1703+
enum lte_lc_act {
1704+
/** LTE-M (Cat-M1). */
1705+
LTE_LC_ACT_LTEM = BIT(0),
1706+
/** NB-IoT. */
1707+
LTE_LC_ACT_NBIOT = BIT(1),
1708+
/** NTN NB-IoT. */
1709+
LTE_LC_ACT_NTN = BIT(2),
16821710
};
16831711

16841712
/**
16851713
* @brief Cellular profile.
16861714
*
1687-
* Used to set the cellular profile for the PDN connection.
1715+
* Cellular profiles are used when there is a need for simultaneous terrestrial and
1716+
* non-terrestrial LTE registrations and PDN connections. There can be only one physical
1717+
* access at a time, but a second access is logically stored by the modem. Typically,
1718+
* this means that there are more than one USIM card or profile, so that certain USIM
1719+
* card or profile is used in certain access technology. A cellular profile combines
1720+
* the information that is needed for LTE registration and is identified by the
1721+
* cellular profile ID.
16881722
*
1689-
* @note The profile ID 0 is associated with PDN contexts in the range 0-9, while profile ID 1
1690-
* is associated with PDN contexts in the range 10-19. The default context for each profile
1723+
* @note The profile ID 0 is associated with PDP contexts in the range 0-9, while profile ID 1
1724+
* is associated with PDP contexts in the range 10-19. The default context for each profile
16911725
* is the first context in the range.
16921726
*/
16931727
struct lte_lc_cellular_profile {
16941728
/** Cellular profile ID. Valid values are 0 and 1. */
16951729
uint8_t id;
1696-
/** LTE mode for the profile (access technology) */
1697-
enum lte_lc_lte_mode lte_mode;
1730+
1731+
/**
1732+
* Access technology bitmap for the profile.
1733+
*
1734+
* This is a combination of @ref lte_lc_act values.
1735+
*/
1736+
uint8_t act;
1737+
16981738
/** UICC configuration */
16991739
enum lte_lc_uicc uicc;
17001740
};
@@ -2487,26 +2527,32 @@ const char *lte_lc_pdn_esm_strerror(int reason);
24872527
* The active cellular profile is reported in the @ref LTE_LC_EVT_CELLULAR_PROFILE_ACTIVE
24882528
* event if an event handler is registered.
24892529
*
2530+
* @note Requires `CONFIG_LTE_LC_CELLULAR_PROFILE_MODULE` to be enabled.
2531+
*
2532+
* @note A cellular profile can only be configured when the modem is in functional mode
2533+
* @ref LTE_LC_FUNC_MODE_POWER_OFF or @ref LTE_LC_FUNC_MODE_OFFLINE.
2534+
*
24902535
* @param[in] profile The cellular profile to set.
24912536
*
24922537
* @retval 0 on success, otherwise negative error code.
24932538
*/
24942539
int lte_lc_cellular_profile_configure(struct lte_lc_cellular_profile *profile);
24952540

2496-
#if defined(CONFIG_LTE_LC_PDN_ESM_STRERROR)
2497-
24982541
/**
2499-
* Retrieve a statically allocated textual description for a given ESM error reason.
2542+
* Remove a cellular profile.
25002543
*
2501-
* @param[in] reason ESM error reason.
2544+
* This clears the configuration for the given cellular profile ID.
25022545
*
2503-
* @return ESM error reason description.
2504-
* If no textual description for the given error is found,
2505-
* a placeholder string is returned instead.
2546+
* @note Requires `CONFIG_LTE_LC_CELLULAR_PROFILE_MODULE` to be enabled.
2547+
*
2548+
* @note A cellular profile can only be removed when the modem is in functional mode
2549+
* @ref LTE_LC_FUNC_MODE_POWER_OFF or @ref LTE_LC_FUNC_MODE_OFFLINE.
2550+
*
2551+
* @param[in] id Cellular profile ID to remove.
2552+
*
2553+
* @retval 0 on success, otherwise negative error code.
25062554
*/
2507-
const char *lte_lc_pdn_esm_strerror(int reason);
2508-
2509-
#endif /* CONFIG_LTE_LC_PDN_ESM_STRERROR */
2555+
int lte_lc_cellular_profile_remove(uint8_t id);
25102556

25112557
/** @} */
25122558

lib/lte_link_control/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ config LTE_LC_ENV_EVAL_MODULE
7777
config LTE_LC_PDN_MODULE
7878
bool "Packet Data Network (PDN) module"
7979

80+
config LTE_LC_CELLULAR_PROFILE_MODULE
81+
bool "Cellular profile module"
82+
8083
menuconfig LTE_LC_DNS_FALLBACK_MODULE
8184
bool "DNS Fallback module"
8285
default y

lib/lte_link_control/modules/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ zephyr_library_sources_ifdef(CONFIG_LTE_LC_DNS_FALLBACK_MODULE dns.c)
2121
zephyr_library_sources_ifdef(CONFIG_LTE_LC_ENV_EVAL_MODULE enveval.c)
2222
zephyr_library_sources_ifdef(CONFIG_LTE_LC_PDN_MODULE pdn.c)
2323
zephyr_library_sources_ifdef(CONFIG_LTE_LC_PDN_ESM_STRERROR esm.c)
24+
zephyr_library_sources_ifdef(CONFIG_LTE_LC_CELLULAR_PROFILE_MODULE cellular_profile.c)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <stdint.h>
8+
#include <string.h>
9+
#include <stdlib.h>
10+
#include <zephyr/logging/log.h>
11+
#include <modem/lte_lc.h>
12+
#include <modem/at_monitor.h>
13+
#include <nrf_modem_at.h>
14+
15+
#include "common/event_handler_list.h"
16+
17+
LOG_MODULE_DECLARE(lte_lc, CONFIG_LTE_LINK_CONTROL_LOG_LEVEL);
18+
19+
#define AT_CMD_CELLULAR_PROFILE_NOTIF_SUBSCRIBE "AT%%CELLULARPRFL=1"
20+
#define AT_CMD_CELLULAR_PROFILE_CONFIGURE "AT%%CELLULARPRFL=2,%d,%d,%d"
21+
#define AT_CMD_CELLULAR_PROFILE_REMOVE "AT%%CELLULARPRFL=2,%d"
22+
23+
#ifndef CONFIG_UNITY
24+
AT_MONITOR(lte_lc_cellular_profile_notif, "%CELLULARPRFL", on_cellularprfl);
25+
#endif
26+
27+
#ifdef CONFIG_UNITY
28+
void on_cellularprfl(const char *notif)
29+
#else
30+
static void on_cellularprfl(const char *notif)
31+
#endif
32+
{
33+
char *p;
34+
int8_t cp_id;
35+
struct lte_lc_evt evt;
36+
37+
p = strstr(notif, "%CELLULARPRFL: ");
38+
if (!p) {
39+
return;
40+
}
41+
42+
p += sizeof("%CELLULARPRFL: ") - 1;
43+
44+
cp_id = (int8_t)strtoul(p, &p, 10);
45+
if (cp_id < 0 || cp_id > 1) {
46+
LOG_ERR("Invalid cellular profile ID: %d", cp_id);
47+
48+
return;
49+
}
50+
51+
evt.type = LTE_LC_EVT_CELLULAR_PROFILE_ACTIVE;
52+
evt.cellular_profile.profile_id = cp_id;
53+
54+
event_handler_list_dispatch(&evt);
55+
}
56+
57+
static int cellular_profile_act_is_valid(uint8_t act)
58+
{
59+
uint8_t mask = LTE_LC_ACT_LTEM |
60+
LTE_LC_ACT_NBIOT |
61+
LTE_LC_ACT_NTN;
62+
63+
if ((act == 0) || (act & ~mask)) {
64+
return -EINVAL;
65+
}
66+
67+
return 0;
68+
}
69+
70+
int lte_lc_cellular_profile_configure(struct lte_lc_cellular_profile *profile)
71+
{
72+
int err;
73+
74+
if (!profile) {
75+
return -EINVAL;
76+
}
77+
78+
err = cellular_profile_act_is_valid(profile->act);
79+
if (err) {
80+
LOG_ERR("Invalid AcT bitmap for cellular profile: 0x%x", profile->act);
81+
82+
return -EINVAL;
83+
}
84+
85+
err = nrf_modem_at_printf(AT_CMD_CELLULAR_PROFILE_CONFIGURE,
86+
profile->id,
87+
profile->act,
88+
profile->uicc);
89+
if (err) {
90+
LOG_ERR("Failed to configure cellular profile, err %d", err);
91+
92+
return err;
93+
}
94+
95+
err = nrf_modem_at_printf(AT_CMD_CELLULAR_PROFILE_NOTIF_SUBSCRIBE);
96+
if (err) {
97+
LOG_ERR("Failed to subscribe to cellular profile notifications, err %d", err);
98+
}
99+
100+
return 0;
101+
}
102+
103+
int lte_lc_cellular_profile_remove(uint8_t id)
104+
{
105+
int err;
106+
107+
err = nrf_modem_at_printf(AT_CMD_CELLULAR_PROFILE_REMOVE, id);
108+
if (err) {
109+
LOG_ERR("Failed to remove cellular profile, err %d", err);
110+
111+
return err;
112+
}
113+
114+
return 0;
115+
}

lib/lte_link_control/modules/pdn.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ LOG_MODULE_DECLARE(lte_lc, CONFIG_LTE_LINK_CONTROL_LOG_LEVEL);
4848

4949
#define AT_CMD_PDN_CONTEXT_READ_RSP_DELIM "\r\n"
5050

51-
/* "+CGCONTRDP: 0,,"example.com","","","198.276.154.230","12.34.56.78",,,,,1464\r\n
51+
/* "+CGCONTRDP: 0,,"example.com","","","198.176.154.230","12.34.56.78",,,,,1464\r\n
5252
* +CGCONTRDP: 0,,"example.com","","","1111:2222:3:FFF::55","1111:2222:3:FFF::55",,,,,1464"
5353
*/
5454
#define AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE1 \

0 commit comments

Comments
 (0)