1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @brief File containing display scan specific definitions for the
9  * Zephyr OS layer of the Wi-Fi driver.
10  */
11 
12 #include <stdlib.h>
13 
14 #include <zephyr/kernel.h>
15 #include <zephyr/logging/log.h>
16 
17 #include "util.h"
18 #include "fmac_api.h"
19 #include "fmac_tx.h"
20 #include "fmac_main.h"
21 #include "wifi_mgmt_scan.h"
22 
23 LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL);
24 
25 extern struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep;
26 
nrf_wifi_map_zep_band_to_rpu(enum wifi_frequency_bands zep_band)27 static enum nrf_wifi_band nrf_wifi_map_zep_band_to_rpu(enum wifi_frequency_bands zep_band)
28 {
29 	switch (zep_band) {
30 	case WIFI_FREQ_BAND_2_4_GHZ:
31 		return NRF_WIFI_BAND_2GHZ;
32 	case WIFI_FREQ_BAND_5_GHZ:
33 		return NRF_WIFI_BAND_5GHZ;
34 	default:
35 		return NRF_WIFI_BAND_INVALID;
36 	}
37 }
38 
nrf_wifi_disp_scan_zep(const struct device * dev,struct wifi_scan_params * params,scan_result_cb_t cb)39 int nrf_wifi_disp_scan_zep(const struct device *dev, struct wifi_scan_params *params,
40 			   scan_result_cb_t cb)
41 {
42 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
43 	struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
44 	struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
45 	struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
46 	struct nrf_wifi_umac_scan_info *scan_info = NULL;
47 	enum nrf_wifi_band band = NRF_WIFI_BAND_INVALID;
48 	uint8_t band_flags = 0xFF;
49 	uint8_t i = 0;
50 	uint8_t j = 0;
51 	uint8_t k = 0;
52 	uint16_t num_scan_channels = 0;
53 	int ret = -1;
54 
55 	vif_ctx_zep = dev->data;
56 
57 	if (!vif_ctx_zep) {
58 		LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
59 		return ret;
60 	}
61 
62 	if (vif_ctx_zep->if_op_state != NRF_WIFI_FMAC_IF_OP_STATE_UP) {
63 		LOG_ERR("%s: Interface not UP", __func__);
64 		return ret;
65 	}
66 
67 	rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
68 	if (!rpu_ctx_zep) {
69 		LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
70 		return ret;
71 	}
72 
73 	k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
74 	if (!rpu_ctx_zep->rpu_ctx) {
75 		LOG_DBG("%s: RPU context not initialized", __func__);
76 		goto out;
77 	}
78 
79 	fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
80 
81 
82 	if (vif_ctx_zep->scan_in_progress) {
83 		LOG_INF("%s: Scan already in progress", __func__);
84 		ret = -EBUSY;
85 		goto out;
86 	}
87 
88 	if (params) {
89 		band_flags &= (~(1 << WIFI_FREQ_BAND_2_4_GHZ));
90 
91 #ifndef CONFIG_NRF70_2_4G_ONLY
92 		band_flags &= (~(1 << WIFI_FREQ_BAND_5_GHZ));
93 #endif /* CONFIG_NRF70_2_4G_ONLY */
94 
95 		if (params->bands & band_flags) {
96 			LOG_ERR("%s: Unsupported band(s) (0x%X)", __func__, params->bands);
97 			ret = -EBUSY;
98 			goto out;
99 		}
100 
101 		for (j = 0; j < CONFIG_WIFI_MGMT_SCAN_CHAN_MAX_MANUAL; j++) {
102 			if (!params->band_chan[j].channel) {
103 				break;
104 			}
105 
106 			num_scan_channels++;
107 		}
108 	}
109 
110 	vif_ctx_zep->disp_scan_cb = cb;
111 
112 	scan_info = k_calloc(sizeof(*scan_info) +
113 			     (num_scan_channels *
114 			      sizeof(scan_info->scan_params.center_frequency[0])),
115 			     sizeof(char));
116 
117 	if (!scan_info) {
118 		LOG_ERR("%s: Unable to allocate memory for scan_info (size: %d bytes)",
119 			__func__,
120 		       sizeof(*scan_info) + (num_scan_channels *
121 					     sizeof(scan_info->scan_params.center_frequency[0])));
122 		goto out;
123 	}
124 
125 	memset(scan_info, 0, sizeof(*scan_info) + (num_scan_channels *
126 		sizeof(scan_info->scan_params.center_frequency[0])));
127 
128 	static uint8_t skip_local_admin_mac = IS_ENABLED(CONFIG_WIFI_NRF70_SKIP_LOCAL_ADMIN_MAC);
129 
130 	scan_info->scan_params.skip_local_admin_macs = skip_local_admin_mac;
131 
132 	scan_info->scan_reason = SCAN_DISPLAY;
133 
134 	if (params) {
135 		if (params->scan_type == WIFI_SCAN_TYPE_PASSIVE) {
136 			scan_info->scan_params.passive_scan = 1;
137 		}
138 
139 		scan_info->scan_params.bands = params->bands;
140 
141 		if (params->dwell_time_active < 0) {
142 			LOG_ERR("%s: Invalid dwell_time_active %d", __func__,
143 				params->dwell_time_active);
144 			goto out;
145 		} else {
146 			scan_info->scan_params.dwell_time_active = params->dwell_time_active;
147 		}
148 
149 		if (params->dwell_time_passive < 0) {
150 			LOG_ERR("%s: Invalid dwell_time_passive %d", __func__,
151 				params->dwell_time_passive);
152 			goto out;
153 		} else {
154 			scan_info->scan_params.dwell_time_passive = params->dwell_time_passive;
155 		}
156 
157 		if ((params->max_bss_cnt < 0) ||
158 		    (params->max_bss_cnt > WIFI_MGMT_SCAN_MAX_BSS_CNT)) {
159 			LOG_ERR("%s: Invalid max_bss_cnt %d", __func__,
160 				params->max_bss_cnt);
161 			goto out;
162 		} else {
163 			vif_ctx_zep->max_bss_cnt = params->max_bss_cnt;
164 		}
165 
166 		for (i = 0; i < NRF_WIFI_SCAN_MAX_NUM_SSIDS; i++) {
167 			if (!(params->ssids[i]) || !strlen(params->ssids[i])) {
168 				break;
169 			}
170 
171 			memcpy(scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid,
172 			       params->ssids[i],
173 			       sizeof(scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid));
174 
175 			scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid_len =
176 				strlen(scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid);
177 
178 			scan_info->scan_params.num_scan_ssids++;
179 		}
180 
181 		for (i = 0; i < CONFIG_WIFI_MGMT_SCAN_CHAN_MAX_MANUAL; i++) {
182 			if (!params->band_chan[i].channel) {
183 				break;
184 			}
185 
186 			band = nrf_wifi_map_zep_band_to_rpu(params->band_chan[i].band);
187 
188 			if (band == NRF_WIFI_BAND_INVALID) {
189 				LOG_ERR("%s: Unsupported band %d", __func__,
190 					params->band_chan[i].band);
191 				goto out;
192 			}
193 
194 			scan_info->scan_params.center_frequency[k++] = nrf_wifi_utils_chan_to_freq(
195 				band, params->band_chan[i].channel);
196 
197 			if (scan_info->scan_params.center_frequency[k - 1] == -1) {
198 				LOG_ERR("%s: Invalid channel %d", __func__,
199 					 params->band_chan[i].channel);
200 				goto out;
201 			}
202 		}
203 
204 		scan_info->scan_params.num_scan_channels = k;
205 	}
206 
207 	vif_ctx_zep->scan_res_cnt = 0;
208 
209 #ifdef CONFIG_NRF70_PASSIVE_SCAN_ONLY
210 	scan_info->scan_params.passive_scan = 1;
211 #endif /* CONFIG_NRF70_PASSIVE_SCAN_ONLY */
212 
213 	status = nrf_wifi_fmac_scan(rpu_ctx_zep->rpu_ctx, vif_ctx_zep->vif_idx, scan_info);
214 
215 	if (status != NRF_WIFI_STATUS_SUCCESS) {
216 		LOG_ERR("%s: nrf_wifi_fmac_scan failed", __func__);
217 		goto out;
218 	}
219 
220 	vif_ctx_zep->scan_type = SCAN_DISPLAY;
221 	vif_ctx_zep->scan_in_progress = true;
222 
223 	k_work_schedule(&vif_ctx_zep->scan_timeout_work,
224 		K_SECONDS(CONFIG_WIFI_NRF70_SCAN_TIMEOUT_S));
225 
226 	ret = 0;
227 out:
228 	if (scan_info) {
229 		k_free(scan_info);
230 	}
231 	k_mutex_unlock(&vif_ctx_zep->vif_lock);
232 	return ret;
233 }
234 
nrf_wifi_disp_scan_res_get_zep(struct nrf_wifi_vif_ctx_zep * vif_ctx_zep)235 enum nrf_wifi_status nrf_wifi_disp_scan_res_get_zep(struct nrf_wifi_vif_ctx_zep *vif_ctx_zep)
236 {
237 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
238 	struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
239 
240 	rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
241 	if (!rpu_ctx_zep) {
242 		LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
243 		return NRF_WIFI_STATUS_FAIL;
244 	}
245 
246 	k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
247 	if (!rpu_ctx_zep->rpu_ctx) {
248 		LOG_DBG("%s: RPU context not initialized", __func__);
249 		goto out;
250 	}
251 
252 	status = nrf_wifi_fmac_scan_res_get(rpu_ctx_zep->rpu_ctx,
253 					    vif_ctx_zep->vif_idx,
254 					    SCAN_DISPLAY);
255 
256 	if (status != NRF_WIFI_STATUS_SUCCESS) {
257 		LOG_ERR("%s: nrf_wifi_fmac_scan failed", __func__);
258 		goto out;
259 	}
260 
261 	status = NRF_WIFI_STATUS_SUCCESS;
262 out:
263 	k_mutex_unlock(&vif_ctx_zep->vif_lock);
264 	return status;
265 }
266 
drv_to_wifi_mgmt_mfp(unsigned char mfp_flag)267 static inline enum wifi_mfp_options drv_to_wifi_mgmt_mfp(unsigned char mfp_flag)
268 {
269 	if (!mfp_flag) {
270 		return WIFI_MFP_DISABLE;
271 	}
272 	if (mfp_flag & NRF_WIFI_MFP_REQUIRED) {
273 		return WIFI_MFP_REQUIRED;
274 	}
275 	if (mfp_flag & NRF_WIFI_MFP_CAPABLE) {
276 		return WIFI_MFP_OPTIONAL;
277 	}
278 
279 	return WIFI_MFP_UNKNOWN;
280 }
drv_to_wifi_mgmt(int drv_security_type)281 static inline enum wifi_security_type drv_to_wifi_mgmt(int drv_security_type)
282 {
283 	switch (drv_security_type) {
284 	case NRF_WIFI_OPEN:
285 		return WIFI_SECURITY_TYPE_NONE;
286 	case NRF_WIFI_WEP:
287 		return WIFI_SECURITY_TYPE_WEP;
288 	case NRF_WIFI_WPA:
289 		return WIFI_SECURITY_TYPE_WPA_PSK;
290 	case NRF_WIFI_WPA2:
291 		return WIFI_SECURITY_TYPE_PSK;
292 	case NRF_WIFI_WPA2_256:
293 		return WIFI_SECURITY_TYPE_PSK_SHA256;
294 	case NRF_WIFI_WPA3:
295 		return WIFI_SECURITY_TYPE_SAE;
296 	case NRF_WIFI_WAPI:
297 		return WIFI_SECURITY_TYPE_WAPI;
298 	case NRF_WIFI_EAP:
299 		return WIFI_SECURITY_TYPE_EAP;
300 	default:
301 		return WIFI_SECURITY_TYPE_UNKNOWN;
302 	}
303 }
304 
nrf_wifi_event_proc_disp_scan_res_zep(void * vif_ctx,struct nrf_wifi_umac_event_new_scan_display_results * scan_res,unsigned int event_len,bool more_res)305 void nrf_wifi_event_proc_disp_scan_res_zep(void *vif_ctx,
306 				struct nrf_wifi_umac_event_new_scan_display_results *scan_res,
307 				unsigned int event_len,
308 				bool more_res)
309 {
310 	struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
311 	struct umac_display_results *r = NULL;
312 	struct wifi_scan_result res;
313 	uint16_t max_bss_cnt = 0;
314 	unsigned int i = 0;
315 	scan_result_cb_t cb = NULL;
316 
317 	vif_ctx_zep = vif_ctx;
318 
319 	cb = (scan_result_cb_t)vif_ctx_zep->disp_scan_cb;
320 
321 	/* Delayed event (after scan timeout) or rogue event after scan done */
322 	if (!cb) {
323 		return;
324 	}
325 
326 	max_bss_cnt = vif_ctx_zep->max_bss_cnt ?
327 		vif_ctx_zep->max_bss_cnt : CONFIG_NRF_WIFI_SCAN_MAX_BSS_CNT;
328 
329 	for (i = 0; i < scan_res->event_bss_count; i++) {
330 		/* Limit the scan results to the configured maximum */
331 		if ((max_bss_cnt > 0) &&
332 		    (vif_ctx_zep->scan_res_cnt >= max_bss_cnt)) {
333 			break;
334 		}
335 
336 		memset(&res, 0x0, sizeof(res));
337 
338 		r = &scan_res->display_results[i];
339 
340 		res.ssid_length = MIN(sizeof(res.ssid), r->ssid.nrf_wifi_ssid_len);
341 
342 		res.band = r->nwk_band;
343 
344 		res.channel = r->nwk_channel;
345 
346 		res.security = drv_to_wifi_mgmt(r->security_type);
347 
348 		res.mfp = drv_to_wifi_mgmt_mfp(r->mfp_flag);
349 
350 		memcpy(res.ssid,
351 		       r->ssid.nrf_wifi_ssid,
352 		       res.ssid_length);
353 
354 		memcpy(res.mac,	r->mac_addr, NRF_WIFI_ETH_ADDR_LEN);
355 		res.mac_length = NRF_WIFI_ETH_ADDR_LEN;
356 
357 		if (r->signal.signal_type == NRF_WIFI_SIGNAL_TYPE_MBM) {
358 			int val = (r->signal.signal.mbm_signal);
359 
360 			res.rssi = (val / 100);
361 		} else if (r->signal.signal_type == NRF_WIFI_SIGNAL_TYPE_UNSPEC) {
362 			res.rssi = (r->signal.signal.unspec_signal);
363 		}
364 
365 		vif_ctx_zep->disp_scan_cb(vif_ctx_zep->zep_net_if_ctx,
366 					  0,
367 					  &res);
368 
369 		vif_ctx_zep->scan_res_cnt++;
370 
371 		/* NET_MGMT dropping events if too many are queued */
372 		k_yield();
373 	}
374 
375 	if (more_res == false) {
376 		vif_ctx_zep->disp_scan_cb(vif_ctx_zep->zep_net_if_ctx, 0, NULL);
377 		vif_ctx_zep->scan_in_progress = false;
378 		vif_ctx_zep->disp_scan_cb = NULL;
379 		k_work_cancel_delayable(&vif_ctx_zep->scan_timeout_work);
380 	}
381 }
382 
383 
384 #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS
nrf_wifi_rx_bcn_prb_resp_frm(void * vif_ctx,void * nwb,unsigned short frequency,signed short signal)385 void nrf_wifi_rx_bcn_prb_resp_frm(void *vif_ctx,
386 				  void *nwb,
387 				  unsigned short frequency,
388 				  signed short signal)
389 {
390 	struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = vif_ctx;
391 	struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
392 	struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
393 	struct wifi_raw_scan_result bcn_prb_resp_info;
394 	int frame_length = 0;
395 	int val = signal;
396 
397 	vif_ctx_zep = vif_ctx;
398 
399 	if (!vif_ctx_zep) {
400 		LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
401 		return;
402 	}
403 
404 	if (!vif_ctx_zep->scan_in_progress) {
405 		/*LOG_INF("%s: Scan not in progress : raw scan data not available", __func__);*/
406 		return;
407 	}
408 
409 	rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
410 
411 	if (!rpu_ctx_zep) {
412 		LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
413 		return;
414 	}
415 
416 	k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
417 	if (!rpu_ctx_zep->rpu_ctx) {
418 		LOG_DBG("%s: RPU context not initialized", __func__);
419 		goto out;
420 	}
421 
422 	fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
423 
424 	frame_length = nrf_wifi_osal_nbuf_data_size(nwb);
425 
426 	if (frame_length > CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH) {
427 		nrf_wifi_osal_mem_cpy(&bcn_prb_resp_info.data,
428 				      nrf_wifi_osal_nbuf_data_get(nwb),
429 				      CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH);
430 
431 	} else {
432 		nrf_wifi_osal_mem_cpy(&bcn_prb_resp_info.data,
433 				      nrf_wifi_osal_nbuf_data_get(nwb),
434 				      frame_length);
435 	}
436 
437 	bcn_prb_resp_info.rssi = MBM_TO_DBM(val);
438 	bcn_prb_resp_info.frequency = frequency;
439 	bcn_prb_resp_info.frame_length = frame_length;
440 
441 	wifi_mgmt_raise_raw_scan_result_event(vif_ctx_zep->zep_net_if_ctx,
442 					      &bcn_prb_resp_info);
443 
444 out:
445 	k_mutex_unlock(&vif_ctx_zep->vif_lock);
446 }
447 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
448