@@ -21,6 +21,149 @@ LOG_MODULE_DECLARE(cloud, CONFIG_APP_CLOUD_LOG_LEVEL);
2121
2222#define AGNSS_MAX_DATA_SIZE 3800
2323
24+ /**
25+ * @brief Reconstruct cellular network information from location module format
26+ *
27+ * This function converts cellular network data from the location module's format
28+ * (location_cloud_request_data) to the LTE link controller's format (lte_lc_cells_info).
29+ * It copies the current cell information, neighbor cells, and GCI (Global Cell Identity)
30+ * cells into the provided destination structures.
31+ *
32+ * The function performs validation to ensure sufficient buffer sizes are provided for
33+ * both neighbor cells and GCI cells arrays before performing the copy operation.
34+ *
35+ * @param[out] dest Pointer to destination lte_lc_cells_info structure to be populated
36+ * @param[out] neighbor_cells Array to store reconstructed neighbor cell information
37+ * @param[in] neighbor_cells_count Size of the neighbor_cells array
38+ * @param[out] gci_cells Array to store reconstructed GCI cell information
39+ * @param[in] gci_cells_count Size of the gci_cells array
40+ * @param[in] src Pointer to source location_cloud_request_data structure containing
41+ * the cellular data to be converted
42+ *
43+ * @retval 0 Success
44+ * @retval -EINVAL Invalid NULL parameter provided
45+ * @retval -ENOMEM Insufficient buffer size for neighbor_cells or gci_cells arrays
46+ */
47+ #if defined(CONFIG_LOCATION_METHOD_CELLULAR )
48+ static int reconstruct_cellular_data (struct lte_lc_cells_info * dest ,
49+ struct lte_lc_ncell * neighbor_cells ,
50+ size_t neighbor_cells_count ,
51+ struct lte_lc_cell * gci_cells ,
52+ size_t gci_cells_count ,
53+ const struct location_cloud_request_data * src )
54+ {
55+ if (!dest || !src || !neighbor_cells || !gci_cells ) {
56+ LOG_ERR ("Invalid NULL parameter(s) provided" );
57+ return - EINVAL ;
58+ }
59+
60+ if (neighbor_cells_count < src -> ncells_count ) {
61+ LOG_ERR ("Insufficient neighbor_cells_count: %zu, required: %d" ,
62+ neighbor_cells_count , src -> ncells_count );
63+ return - ENOMEM ;
64+ }
65+
66+ if (gci_cells_count < src -> gci_cells_count ) {
67+ LOG_ERR ("Insufficient gci_cells_count: %zu, required: %d" ,
68+ gci_cells_count , src -> gci_cells_count );
69+ return - ENOMEM ;
70+ }
71+
72+ /* Copy current cell information */
73+ dest -> current_cell .mcc = src -> current_cell .mcc ;
74+ dest -> current_cell .mnc = src -> current_cell .mnc ;
75+ dest -> current_cell .id = src -> current_cell .id ;
76+ dest -> current_cell .tac = src -> current_cell .tac ;
77+ dest -> current_cell .timing_advance = src -> current_cell .timing_advance ;
78+ dest -> current_cell .earfcn = src -> current_cell .earfcn ;
79+ dest -> current_cell .rsrp = src -> current_cell .rsrp ;
80+ dest -> current_cell .rsrq = src -> current_cell .rsrq ;
81+
82+ dest -> ncells_count = src -> ncells_count ;
83+ dest -> gci_cells_count = src -> gci_cells_count ;
84+
85+ /* Copy neighbor cells */
86+ for (uint8_t i = 0 ; i < src -> ncells_count ; i ++ ) {
87+ neighbor_cells [i ].earfcn = src -> neighbor_cells [i ].earfcn ;
88+ neighbor_cells [i ].time_diff = src -> neighbor_cells [i ].time_diff ;
89+ neighbor_cells [i ].phys_cell_id = src -> neighbor_cells [i ].phys_cell_id ;
90+ neighbor_cells [i ].rsrp = src -> neighbor_cells [i ].rsrp ;
91+ neighbor_cells [i ].rsrq = src -> neighbor_cells [i ].rsrq ;
92+ }
93+
94+ dest -> neighbor_cells = neighbor_cells ;
95+
96+ /* Copy GCI cells */
97+ for (uint8_t i = 0 ; i < src -> gci_cells_count ; i ++ ) {
98+ gci_cells [i ].id = src -> gci_cells [i ].id ;
99+ gci_cells [i ].mcc = src -> gci_cells [i ].mcc ;
100+ gci_cells [i ].mnc = src -> gci_cells [i ].mnc ;
101+ gci_cells [i ].tac = src -> gci_cells [i ].tac ;
102+ gci_cells [i ].timing_advance = src -> gci_cells [i ].timing_advance ;
103+ gci_cells [i ].earfcn = src -> gci_cells [i ].earfcn ;
104+ gci_cells [i ].rsrp = src -> gci_cells [i ].rsrp ;
105+ gci_cells [i ].rsrq = src -> gci_cells [i ].rsrq ;
106+ }
107+
108+ dest -> gci_cells = gci_cells ;
109+
110+ return 0 ;
111+ }
112+ #endif /* CONFIG_LOCATION_METHOD_CELLULAR */
113+
114+ #if defined(CONFIG_LOCATION_METHOD_WIFI )
115+ /**
116+ * @brief Reconstruct wifi_scan_info structure from location module format
117+ *
118+ * This function converts location module's WiFi access point data format into
119+ * the wifi_scan_info structure format. It copies RSSI values, MAC addresses,
120+ * and MAC address lengths for each access point.
121+ *
122+ * @param[out] dest Pointer to destination wifi_scan_info structure to populate
123+ * @param[out] ap_info Array to store wifi_scan_result entries
124+ * @param[in] ap_info_count Size of the ap_info array (number of entries)
125+ * @param[in] src Pointer to source location_cloud_request_data structure
126+ *
127+ * @retval 0 On success
128+ * @retval -EINVAL If any pointer parameter is NULL
129+ * @retval -ENOMEM If ap_info_count is insufficient to hold all WiFi APs from src
130+ *
131+ * @note This function is only available when CONFIG_LOCATION_METHOD_WIFI is defined
132+ * @note The dest->ap_info will point to the provided ap_info array
133+ * @note WiFi MAC addresses are expected to be WIFI_MAC_ADDR_LEN bytes long
134+ */
135+ static int reconstruct_wifi_data (struct wifi_scan_info * dest ,
136+ struct wifi_scan_result * ap_info ,
137+ size_t ap_info_count ,
138+ const struct location_cloud_request_data * src )
139+ {
140+ if (!dest || !src || !ap_info ) {
141+ LOG_ERR ("Invalid NULL parameter(s) provided" );
142+ return - EINVAL ;
143+ }
144+
145+ if ((ap_info_count < src -> wifi_cnt )) {
146+ LOG_ERR ("Insufficient ap_info_count: %zu, required: %d" ,
147+ ap_info_count , src -> wifi_cnt );
148+ return - ENOMEM ;
149+ }
150+
151+ /* Copy WiFi AP data */
152+ for (uint16_t i = 0 ; i < ap_info_count ; i ++ ) {
153+ ap_info [i ].rssi = src -> wifi_aps [i ].rssi ;
154+ memcpy (ap_info [i ].mac ,
155+ src -> wifi_aps [i ].mac ,
156+ WIFI_MAC_ADDR_LEN );
157+ ap_info [i ].mac_length = src -> wifi_aps [i ].mac_length ;
158+ }
159+
160+ dest -> ap_info = ap_info ;
161+ dest -> cnt = ap_info_count ;
162+
163+ return 0 ;
164+ }
165+ #endif /* CONFIG_LOCATION_METHOD_WIFI */
166+
24167static void send_request_failed (void )
25168{
26169 int err ;
@@ -34,7 +177,7 @@ static void send_request_failed(void)
34177}
35178
36179/* Handle cloud location requests from the location module */
37- static void handle_cloud_location_request (const struct location_data_cloud * request )
180+ static void handle_cloud_location_request (const struct location_cloud_request_data * request )
38181{
39182 int err ;
40183 struct nrf_cloud_location_config loc_config = {
@@ -48,32 +191,48 @@ static void handle_cloud_location_request(const struct location_data_cloud *requ
48191 LOG_DBG ("Handling cloud location request" );
49192
50193#if defined(CONFIG_LOCATION_METHOD_CELLULAR )
51- if (request -> cell_data != NULL ) {
52- /* Cast away const: nRF Cloud API limitation - struct fields are non-const
53- * but the data is not modified by the API
54- */
55- loc_req .cell_info = (struct lte_lc_cells_info * )request -> cell_data ; /* NOSONAR */
194+ struct lte_lc_cells_info cell_info = { 0 };
195+ struct lte_lc_ncell neighbor_cells [CONFIG_LTE_NEIGHBOR_CELLS_MAX ];
196+ struct lte_lc_cell gci_cells [CONFIG_LTE_NEIGHBOR_CELLS_MAX ];
197+
198+ if ((request -> current_cell .id != LTE_LC_CELL_EUTRAN_ID_INVALID ) &&
199+ (request -> ncells_count > 0 )) {
200+ err = reconstruct_cellular_data (& cell_info , neighbor_cells ,
201+ ARRAY_SIZE (neighbor_cells ),
202+ gci_cells ,
203+ ARRAY_SIZE (gci_cells ),
204+ request );
205+ if (err ) {
206+ LOG_ERR ("Failed to reconstruct cellular data, error: %d" , err );
207+ SEND_FATAL_ERROR ();
208+ return ;
209+ }
56210
57- LOG_DBG ("Cellular data present: current cell ID: %d, neighbor cells: %d, "
58- "GCI cells count: %d" ,
59- request -> cell_data -> current_cell .id ,
60- request -> cell_data -> ncells_count ,
61- request -> cell_data -> gci_cells_count );
211+ loc_req .cell_info = & cell_info ;
62212 }
63- #endif
213+ #endif /* CONFIG_LOCATION_METHOD_CELLULAR */
64214
65215#if defined(CONFIG_LOCATION_METHOD_WIFI )
66- if (request -> wifi_data != NULL ) {
67- /* Cast away const: nRF Cloud API limitation - struct fields are non-const
68- * but the data is not modified by the API
69- */
70- loc_req .wifi_info = (struct wifi_scan_info * )request -> wifi_data ; /* NOSONAR */
216+ struct wifi_scan_result ap_info [CONFIG_LOCATION_METHOD_WIFI_SCANNING_RESULTS_MAX_CNT ];
217+ struct wifi_scan_info wifi_info = { 0 };
218+
219+ if (request -> wifi_cnt > 0 ) {
220+ err = reconstruct_wifi_data (& wifi_info , ap_info , ARRAY_SIZE (ap_info ), request );
221+ if (err ) {
222+ LOG_ERR ("Failed to reconstruct Wi-Fi data, error: %d" , err );
223+ SEND_FATAL_ERROR ();
224+ return ;
225+ }
71226
72- LOG_DBG ("Wi-Fi data present: %d APs" , request -> wifi_data -> cnt );
227+ loc_req .wifi_info = & wifi_info ;
228+ }
229+ #endif /* CONFIG_LOCATION_METHOD_WIFI */
230+
231+ if (!loc_req .cell_info && !loc_req .wifi_info ) {
232+ LOG_ERR ("No cellular or Wi-Fi data provided for location request" );
233+ return ;
73234 }
74- #endif
75235
76- /* Send location request to nRF Cloud */
77236 err = nrf_cloud_coap_location_get (& loc_req , & result );
78237 if (err == COAP_RESPONSE_CODE_NOT_FOUND ) {
79238 LOG_WRN ("nRF Cloud CoAP location coordinates not found, error: %d" , err );
0 commit comments