Skip to content

Commit cd87f3b

Browse files
tokangasnordicjm
authored andcommitted
lib: lte_link_control: Send NEIGHBOR_CELL_MEAS event in case of error
Earlier, no LTE_LC_EVT_NEIGHBOR_CELL_MEAS event was sent in case an error occurred during parsing of the %NCELLMEAS notification. Because of this, the user of the library did not have any way to determine when the operation had been completed. The implementation has been changed so, that an LTE_LC_EVT_NEIGHBOR_CELL_MEAS event is always sent, if lte_lc_neighbor_cell_measurement() has returned 0. In case of an error, an empty LTE_LC_EVT_NEIGHBOR_CELL_MEAS (current_cell set to LTE_LC_CELL_EUTRAN_ID_INVALID) is sent. Signed-off-by: Tommi Kangas <[email protected]>
1 parent ec6f3f3 commit cd87f3b

File tree

4 files changed

+89
-10
lines changed

4 files changed

+89
-10
lines changed

doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ Modem libraries
495495
* :ref:`lte_lc_readme` library:
496496

497497
* Fixed handling of ``%NCELLMEAS`` notification with status 2 (measurement interrupted) and no cells.
498+
* Added sending of ``LTE_LC_EVT_NEIGHBOR_CELL_MEAS`` event with ``current_cell`` set to ``LTE_LC_CELL_EUTRAN_ID_INVALID`` in case an error occurs while parsing the ``%NCELLMEAS`` notification.
498499

499500
* :ref:`modem_key_mgmt` library:
500501

include/modem/lte_lc.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,10 @@ enum lte_lc_evt_type {
283283
* Neighbor cell measurement results.
284284
*
285285
* The associated payload is the @c lte_lc_evt.cells_info member of type
286-
* @ref lte_lc_cells_info in the event.
286+
* @ref lte_lc_cells_info in the event. In case of an error or if no cells were found,
287+
* the @c lte_lc_cells_info.current_cell member is set to
288+
* @ref LTE_LC_CELL_EUTRAN_ID_INVALID, and @c lte_lc_cells_info.ncells_count and
289+
* @c lte_lc_cells_info.gci_cells_count members are set to zero.
287290
*/
288291
LTE_LC_EVT_NEIGHBOR_CELL_MEAS = 7,
289292
#endif /* CONFIG_LTE_LC_NEIGHBOR_CELL_MEAS_MODULE */
@@ -1688,7 +1691,8 @@ int lte_lc_lte_mode_get(enum lte_lc_lte_mode *mode);
16881691
* @ref LTE_LC_EVT_NEIGHBOR_CELL_MEAS, meaning that an event handler must be registered to receive
16891692
* the information. Depending on the network conditions, LTE connection state and requested search
16901693
* type, it may take a while before the measurement result is ready and reported back. After the
1691-
* event is received, the neighbor cell measurements are automatically stopped.
1694+
* event is received, the neighbor cell measurements are automatically stopped. If the
1695+
* function returns successfully, the @ref LTE_LC_EVT_NEIGHBOR_CELL_MEAS event is always reported.
16921696
*
16931697
* @note This feature is only supported by modem firmware versions >= 1.3.0.
16941698
*

lib/lte_link_control/modules/ncellmeas.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,17 @@ static int parse_ncellmeas(const char *at_response, struct lte_lc_cells_info *ce
610610
return err;
611611
}
612612

613+
static void ncellmeas_empty_event_dispatch(void)
614+
{
615+
struct lte_lc_evt evt = {0};
616+
617+
LOG_DBG("Dispatching empty LTE_LC_EVT_NEIGHBOR_CELL_MEAS event");
618+
619+
evt.type = LTE_LC_EVT_NEIGHBOR_CELL_MEAS;
620+
evt.cells_info.current_cell.id = LTE_LC_CELL_EUTRAN_ID_INVALID;
621+
event_handler_list_dispatch(&evt);
622+
}
623+
613624
static void at_handler_ncellmeas_gci(const char *response)
614625
{
615626
int err;
@@ -625,6 +636,7 @@ static void at_handler_ncellmeas_gci(const char *response)
625636
cells = k_calloc(ncellmeas_params.gci_count, sizeof(struct lte_lc_cell));
626637
if (cells == NULL) {
627638
LOG_ERR("Failed to allocate memory for the GCI cells");
639+
ncellmeas_empty_event_dispatch();
628640
return;
629641
}
630642

@@ -646,6 +658,7 @@ static void at_handler_ncellmeas_gci(const char *response)
646658
break;
647659
default:
648660
LOG_ERR("Parsing of neighbor cells failed, err: %d", err);
661+
ncellmeas_empty_event_dispatch();
649662
break;
650663
}
651664

@@ -655,14 +668,9 @@ static void at_handler_ncellmeas_gci(const char *response)
655668

656669
static void ncellmeas_cancel_timeout_work_fn(struct k_work *work)
657670
{
658-
struct lte_lc_evt evt = {0};
659-
660-
LOG_DBG("No %%NCELLMEAS notification received after AT%%NCELLMEASSTOP, "
661-
"sending empty results");
671+
LOG_DBG("No %%NCELLMEAS notification received after AT%%NCELLMEASSTOP");
662672

663-
evt.type = LTE_LC_EVT_NEIGHBOR_CELL_MEAS;
664-
evt.cells_info.current_cell.id = LTE_LC_CELL_EUTRAN_ID_INVALID;
665-
event_handler_list_dispatch(&evt);
673+
ncellmeas_empty_event_dispatch();
666674

667675
k_sem_give(&ncellmeas_idle_sem);
668676
}
@@ -709,6 +717,7 @@ static void at_handler_ncellmeas(const char *response)
709717
neighbor_cells = k_calloc(ncell_count, sizeof(struct lte_lc_ncell));
710718
if (neighbor_cells == NULL) {
711719
LOG_ERR("Failed to allocate memory for neighbor cells");
720+
ncellmeas_empty_event_dispatch();
712721
goto exit;
713722
}
714723
}
@@ -730,6 +739,7 @@ static void at_handler_ncellmeas(const char *response)
730739
break;
731740
default:
732741
LOG_ERR("Parsing of neighbor cells failed, err: %d", err);
742+
ncellmeas_empty_event_dispatch();
733743
break;
734744
}
735745

tests/lib/lte_lc_api/src/lte_lc_api_test.c

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "cmock_nrf_modem_at.h"
1717
#include "cmock_nrf_modem.h"
1818

19-
#define TEST_EVENT_MAX_COUNT 10
19+
#define TEST_EVENT_MAX_COUNT 20
2020

2121
static struct lte_lc_evt test_event_data[TEST_EVENT_MAX_COUNT];
2222
static struct lte_lc_ncell test_neighbor_cells[CONFIG_LTE_NEIGHBOR_CELLS_MAX];
@@ -2746,6 +2746,14 @@ void test_lte_lc_neighbor_cell_measurement_cell_id_missing_fail(void)
27462746
"%NCELLMEAS:0,,\"98712\",\"0AB9\",4800,7,63,31,456,4800,"
27472747
"8,60,29,4,3500,9,99,18,5,5300,11\r\n");
27482748

2749+
lte_lc_callback_count_expected = 1;
2750+
2751+
/* In case of an error, we're expected to receive an empty event. */
2752+
test_event_data[0].type = LTE_LC_EVT_NEIGHBOR_CELL_MEAS;
2753+
test_event_data[0].cells_info.current_cell.id = LTE_LC_CELL_EUTRAN_ID_INVALID;
2754+
test_event_data[0].cells_info.ncells_count = 0;
2755+
test_event_data[0].cells_info.gci_cells_count = 0;
2756+
27492757
__mock_nrf_modem_at_printf_ExpectAndReturn("AT%NCELLMEAS", EXIT_SUCCESS);
27502758

27512759
ret = lte_lc_neighbor_cell_measurement(NULL);
@@ -2762,6 +2770,14 @@ void test_lte_lc_neighbor_cell_measurement_cell_id_too_big_fail(void)
27622770
"%NCELLMEAS:0,\"FFFFFFFF\",\"98712\",\"0AB9\",4800,7,63,31,456,4800,"
27632771
"8,60,29,4,3500,9,99,18,5,5300,11\r\n");
27642772

2773+
lte_lc_callback_count_expected = 1;
2774+
2775+
/* In case of an error, we're expected to receive an empty event. */
2776+
test_event_data[0].type = LTE_LC_EVT_NEIGHBOR_CELL_MEAS;
2777+
test_event_data[0].cells_info.current_cell.id = LTE_LC_CELL_EUTRAN_ID_INVALID;
2778+
test_event_data[0].cells_info.ncells_count = 0;
2779+
test_event_data[0].cells_info.gci_cells_count = 0;
2780+
27652781
__mock_nrf_modem_at_printf_ExpectAndReturn("AT%NCELLMEAS", EXIT_SUCCESS);
27662782

27672783
ret = lte_lc_neighbor_cell_measurement(NULL);
@@ -2778,6 +2794,14 @@ void test_lte_lc_neighbor_cell_measurement_malformed_fail(void)
27782794
"%NCELLMEAS:0,\"00112233\",\"98712\",\"0AB9\",4800,7,63,31,456,4800,"
27792795
"8,60,29,4,35 00,9,99,18,5,5300,11\r\n");
27802796

2797+
lte_lc_callback_count_expected = 1;
2798+
2799+
/* In case of an error, we're expected to receive an empty event. */
2800+
test_event_data[0].type = LTE_LC_EVT_NEIGHBOR_CELL_MEAS;
2801+
test_event_data[0].cells_info.current_cell.id = LTE_LC_CELL_EUTRAN_ID_INVALID;
2802+
test_event_data[0].cells_info.ncells_count = 0;
2803+
test_event_data[0].cells_info.gci_cells_count = 0;
2804+
27812805
__mock_nrf_modem_at_printf_ExpectAndReturn("AT%NCELLMEAS", EXIT_SUCCESS);
27822806

27832807
ret = lte_lc_neighbor_cell_measurement(NULL);
@@ -3506,6 +3530,16 @@ void test_lte_lc_neighbor_cell_measurement_normal_invalid_field_format_fail(void
35063530
.gci_count = 0,
35073531
};
35083532

3533+
lte_lc_callback_count_expected = 16;
3534+
3535+
/* In case of an error, we're expected to receive an empty event. */
3536+
for (int i = 0; i < lte_lc_callback_count_expected; i++) {
3537+
test_event_data[i].type = LTE_LC_EVT_NEIGHBOR_CELL_MEAS;
3538+
test_event_data[i].cells_info.current_cell.id = LTE_LC_CELL_EUTRAN_ID_INVALID;
3539+
test_event_data[i].cells_info.ncells_count = 0;
3540+
test_event_data[i].cells_info.gci_cells_count = 0;
3541+
}
3542+
35093543
/* Syntax:
35103544
* %NCELLMEAS: status
35113545
* [,<cell_id>,<plmn>,<tac>,<ta>,<earfcn>,<phys_cell_id>,<rsrp>,<rsrq>,<meas_time>
@@ -3671,6 +3705,16 @@ void test_lte_lc_neighbor_cell_measurement_gci_invalid_field_format_fail(void)
36713705
.gci_count = 10,
36723706
};
36733707

3708+
lte_lc_callback_count_expected = 18;
3709+
3710+
/* In case of an error, we're expected to receive an empty event. */
3711+
for (int i = 0; i < lte_lc_callback_count_expected; i++) {
3712+
test_event_data[i].type = LTE_LC_EVT_NEIGHBOR_CELL_MEAS;
3713+
test_event_data[i].cells_info.current_cell.id = LTE_LC_CELL_EUTRAN_ID_INVALID;
3714+
test_event_data[i].cells_info.ncells_count = 0;
3715+
test_event_data[i].cells_info.gci_cells_count = 0;
3716+
}
3717+
36743718
/* Syntax for GCI search types:
36753719
* High level:
36763720
* status[,
@@ -3881,6 +3925,16 @@ void test_lte_lc_neighbor_cell_measurement_normal_invalid_mccmnc_fail(void)
38813925
{
38823926
int ret;
38833927

3928+
lte_lc_callback_count_expected = 2;
3929+
3930+
/* In case of an error, we're expected to receive an empty event. */
3931+
for (int i = 0; i < lte_lc_callback_count_expected; i++) {
3932+
test_event_data[i].type = LTE_LC_EVT_NEIGHBOR_CELL_MEAS;
3933+
test_event_data[i].cells_info.current_cell.id = LTE_LC_CELL_EUTRAN_ID_INVALID;
3934+
test_event_data[i].cells_info.ncells_count = 0;
3935+
test_event_data[i].cells_info.gci_cells_count = 0;
3936+
}
3937+
38843938
/* Invalid MCC */
38853939
__mock_nrf_modem_at_printf_ExpectAndReturn("AT%NCELLMEAS", EXIT_SUCCESS);
38863940
ret = lte_lc_neighbor_cell_measurement(NULL);
@@ -3908,6 +3962,16 @@ void test_lte_lc_neighbor_cell_measurement_gci_invalid_mccmnc_fail(void)
39083962
.gci_count = 2,
39093963
};
39103964

3965+
lte_lc_callback_count_expected = 2;
3966+
3967+
/* In case of an error, we're expected to receive an empty event. */
3968+
for (int i = 0; i < lte_lc_callback_count_expected; i++) {
3969+
test_event_data[i].type = LTE_LC_EVT_NEIGHBOR_CELL_MEAS;
3970+
test_event_data[i].cells_info.current_cell.id = LTE_LC_CELL_EUTRAN_ID_INVALID;
3971+
test_event_data[i].cells_info.ncells_count = 0;
3972+
test_event_data[i].cells_info.gci_cells_count = 0;
3973+
}
3974+
39113975
/* Invalid MCC */
39123976
__mock_nrf_modem_at_printf_ExpectAndReturn("AT%NCELLMEAS=5,2", EXIT_SUCCESS);
39133977
ret = lte_lc_neighbor_cell_measurement(&params);

0 commit comments

Comments
 (0)