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 "system/fmac_api.h"
19 #include "system/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 = nrf_wifi_osal_mem_zalloc(sizeof(*scan_info) +
113 			     (num_scan_channels *
114 			      sizeof(scan_info->scan_params.center_frequency[0])));
115 
116 	if (!scan_info) {
117 		LOG_ERR("%s: Unable to allocate memory for scan_info (size: %d bytes)",
118 			__func__,
119 		       sizeof(*scan_info) + (num_scan_channels *
120 					     sizeof(scan_info->scan_params.center_frequency[0])));
121 		goto out;
122 	}
123 
124 	memset(scan_info, 0, sizeof(*scan_info) + (num_scan_channels *
125 		sizeof(scan_info->scan_params.center_frequency[0])));
126 
127 	static uint8_t skip_local_admin_mac = IS_ENABLED(CONFIG_WIFI_NRF70_SKIP_LOCAL_ADMIN_MAC);
128 
129 	scan_info->scan_params.skip_local_admin_macs = skip_local_admin_mac;
130 
131 	scan_info->scan_reason = SCAN_DISPLAY;
132 
133 	if (params) {
134 		if (params->scan_type == WIFI_SCAN_TYPE_PASSIVE) {
135 			scan_info->scan_params.passive_scan = 1;
136 		}
137 
138 		scan_info->scan_params.bands = params->bands;
139 
140 		if (params->dwell_time_active < 0) {
141 			LOG_ERR("%s: Invalid dwell_time_active %d", __func__,
142 				params->dwell_time_active);
143 			goto out;
144 		} else {
145 			scan_info->scan_params.dwell_time_active = params->dwell_time_active;
146 		}
147 
148 		if (params->dwell_time_passive < 0) {
149 			LOG_ERR("%s: Invalid dwell_time_passive %d", __func__,
150 				params->dwell_time_passive);
151 			goto out;
152 		} else {
153 			scan_info->scan_params.dwell_time_passive = params->dwell_time_passive;
154 		}
155 
156 		if ((params->max_bss_cnt < 0) ||
157 		    (params->max_bss_cnt > WIFI_MGMT_SCAN_MAX_BSS_CNT)) {
158 			LOG_ERR("%s: Invalid max_bss_cnt %d", __func__,
159 				params->max_bss_cnt);
160 			goto out;
161 		} else {
162 			vif_ctx_zep->max_bss_cnt = params->max_bss_cnt;
163 		}
164 
165 		for (i = 0; i < NRF_WIFI_SCAN_MAX_NUM_SSIDS; i++) {
166 			if (!(params->ssids[i]) || !strlen(params->ssids[i])) {
167 				break;
168 			}
169 
170 			memcpy(scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid,
171 			       params->ssids[i],
172 			       sizeof(scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid));
173 
174 			scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid_len =
175 				strlen(scan_info->scan_params.scan_ssids[i].nrf_wifi_ssid);
176 
177 			scan_info->scan_params.num_scan_ssids++;
178 		}
179 
180 		for (i = 0; i < CONFIG_WIFI_MGMT_SCAN_CHAN_MAX_MANUAL; i++) {
181 			if (!params->band_chan[i].channel) {
182 				break;
183 			}
184 
185 			band = nrf_wifi_map_zep_band_to_rpu(params->band_chan[i].band);
186 
187 			if (band == NRF_WIFI_BAND_INVALID) {
188 				LOG_ERR("%s: Unsupported band %d", __func__,
189 					params->band_chan[i].band);
190 				goto out;
191 			}
192 
193 			scan_info->scan_params.center_frequency[k++] = nrf_wifi_utils_chan_to_freq(
194 				band, params->band_chan[i].channel);
195 
196 			if (scan_info->scan_params.center_frequency[k - 1] == -1) {
197 				LOG_ERR("%s: Invalid channel %d", __func__,
198 					 params->band_chan[i].channel);
199 				goto out;
200 			}
201 		}
202 
203 		scan_info->scan_params.num_scan_channels = k;
204 	}
205 
206 	vif_ctx_zep->scan_res_cnt = 0;
207 
208 #ifdef CONFIG_NRF70_PASSIVE_SCAN_ONLY
209 	scan_info->scan_params.passive_scan = 1;
210 #endif /* CONFIG_NRF70_PASSIVE_SCAN_ONLY */
211 
212 	status = nrf_wifi_sys_fmac_scan(rpu_ctx_zep->rpu_ctx, vif_ctx_zep->vif_idx, scan_info);
213 
214 	if (status != NRF_WIFI_STATUS_SUCCESS) {
215 		LOG_ERR("%s: nrf_wifi_sys_fmac_scan failed", __func__);
216 		goto out;
217 	}
218 
219 	vif_ctx_zep->scan_type = SCAN_DISPLAY;
220 	vif_ctx_zep->scan_in_progress = true;
221 
222 	k_work_schedule(&vif_ctx_zep->scan_timeout_work,
223 		K_SECONDS(CONFIG_WIFI_NRF70_SCAN_TIMEOUT_S));
224 
225 	ret = 0;
226 out:
227 	if (scan_info) {
228 		nrf_wifi_osal_mem_free(scan_info);
229 	}
230 	k_mutex_unlock(&vif_ctx_zep->vif_lock);
231 	return ret;
232 }
233 
nrf_wifi_disp_scan_res_get_zep(struct nrf_wifi_vif_ctx_zep * vif_ctx_zep)234 enum nrf_wifi_status nrf_wifi_disp_scan_res_get_zep(struct nrf_wifi_vif_ctx_zep *vif_ctx_zep)
235 {
236 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
237 	struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
238 
239 	rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
240 	if (!rpu_ctx_zep) {
241 		LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
242 		return NRF_WIFI_STATUS_FAIL;
243 	}
244 
245 	k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
246 	if (!rpu_ctx_zep->rpu_ctx) {
247 		LOG_DBG("%s: RPU context not initialized", __func__);
248 		goto out;
249 	}
250 
251 	status = nrf_wifi_sys_fmac_scan_res_get(rpu_ctx_zep->rpu_ctx,
252 					    vif_ctx_zep->vif_idx,
253 					    SCAN_DISPLAY);
254 
255 	if (status != NRF_WIFI_STATUS_SUCCESS) {
256 		LOG_ERR("%s: nrf_wifi_sys_fmac_scan failed", __func__);
257 		goto out;
258 	}
259 
260 	status = NRF_WIFI_STATUS_SUCCESS;
261 out:
262 	k_mutex_unlock(&vif_ctx_zep->vif_lock);
263 	return status;
264 }
265 
drv_to_wifi_mgmt_mfp(unsigned char mfp_flag)266 static inline enum wifi_mfp_options drv_to_wifi_mgmt_mfp(unsigned char mfp_flag)
267 {
268 	if (!mfp_flag) {
269 		return WIFI_MFP_DISABLE;
270 	}
271 	if (mfp_flag & NRF_WIFI_MFP_REQUIRED) {
272 		return WIFI_MFP_REQUIRED;
273 	}
274 	if (mfp_flag & NRF_WIFI_MFP_CAPABLE) {
275 		return WIFI_MFP_OPTIONAL;
276 	}
277 
278 	return WIFI_MFP_UNKNOWN;
279 }
drv_to_wifi_mgmt(int drv_security_type)280 static inline enum wifi_security_type drv_to_wifi_mgmt(int drv_security_type)
281 {
282 	switch (drv_security_type) {
283 	case NRF_WIFI_OPEN:
284 		return WIFI_SECURITY_TYPE_NONE;
285 	case NRF_WIFI_WEP:
286 		return WIFI_SECURITY_TYPE_WEP;
287 	case NRF_WIFI_WPA:
288 		return WIFI_SECURITY_TYPE_WPA_PSK;
289 	case NRF_WIFI_WPA2:
290 		return WIFI_SECURITY_TYPE_PSK;
291 	case NRF_WIFI_WPA2_256:
292 		return WIFI_SECURITY_TYPE_PSK_SHA256;
293 	case NRF_WIFI_WPA3:
294 		return WIFI_SECURITY_TYPE_SAE;
295 	case NRF_WIFI_WAPI:
296 		return WIFI_SECURITY_TYPE_WAPI;
297 	case NRF_WIFI_EAP:
298 		return WIFI_SECURITY_TYPE_EAP;
299 	default:
300 		return WIFI_SECURITY_TYPE_UNKNOWN;
301 	}
302 }
303 
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)304 void nrf_wifi_event_proc_disp_scan_res_zep(void *vif_ctx,
305 				struct nrf_wifi_umac_event_new_scan_display_results *scan_res,
306 				unsigned int event_len,
307 				bool more_res)
308 {
309 	struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
310 	struct umac_display_results *r = NULL;
311 	struct wifi_scan_result res;
312 	uint16_t max_bss_cnt = 0;
313 	unsigned int i = 0;
314 	scan_result_cb_t cb = NULL;
315 
316 	vif_ctx_zep = vif_ctx;
317 
318 	cb = (scan_result_cb_t)vif_ctx_zep->disp_scan_cb;
319 
320 	/* Delayed event (after scan timeout) or rogue event after scan done */
321 	if (!cb) {
322 		return;
323 	}
324 
325 	max_bss_cnt = vif_ctx_zep->max_bss_cnt ?
326 		vif_ctx_zep->max_bss_cnt : CONFIG_NRF_WIFI_SCAN_MAX_BSS_CNT;
327 
328 	for (i = 0; i < scan_res->event_bss_count; i++) {
329 		/* Limit the scan results to the configured maximum */
330 		if ((max_bss_cnt > 0) &&
331 		    (vif_ctx_zep->scan_res_cnt >= max_bss_cnt)) {
332 			break;
333 		}
334 
335 		memset(&res, 0x0, sizeof(res));
336 
337 		r = &scan_res->display_results[i];
338 
339 		res.ssid_length = MIN(sizeof(res.ssid), r->ssid.nrf_wifi_ssid_len);
340 
341 		res.band = r->nwk_band;
342 
343 		res.channel = r->nwk_channel;
344 
345 		res.security = drv_to_wifi_mgmt(r->security_type);
346 
347 		res.mfp = drv_to_wifi_mgmt_mfp(r->mfp_flag);
348 
349 		memcpy(res.ssid,
350 		       r->ssid.nrf_wifi_ssid,
351 		       res.ssid_length);
352 
353 		memcpy(res.mac,	r->mac_addr, NRF_WIFI_ETH_ADDR_LEN);
354 		res.mac_length = NRF_WIFI_ETH_ADDR_LEN;
355 
356 		if (r->signal.signal_type == NRF_WIFI_SIGNAL_TYPE_MBM) {
357 			int val = (r->signal.signal.mbm_signal);
358 
359 			res.rssi = (val / 100);
360 		} else if (r->signal.signal_type == NRF_WIFI_SIGNAL_TYPE_UNSPEC) {
361 			res.rssi = (r->signal.signal.unspec_signal);
362 		}
363 
364 		vif_ctx_zep->disp_scan_cb(vif_ctx_zep->zep_net_if_ctx,
365 					  0,
366 					  &res);
367 
368 		vif_ctx_zep->scan_res_cnt++;
369 
370 		/* NET_MGMT dropping events if too many are queued */
371 		k_yield();
372 	}
373 
374 	if (more_res == false) {
375 		vif_ctx_zep->disp_scan_cb(vif_ctx_zep->zep_net_if_ctx, 0, NULL);
376 		vif_ctx_zep->scan_in_progress = false;
377 		vif_ctx_zep->disp_scan_cb = NULL;
378 		k_work_cancel_delayable(&vif_ctx_zep->scan_timeout_work);
379 	}
380 }
381 
382 
383 #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)384 void nrf_wifi_rx_bcn_prb_resp_frm(void *vif_ctx,
385 				  void *nwb,
386 				  unsigned short frequency,
387 				  signed short signal)
388 {
389 	struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = vif_ctx;
390 	struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
391 	struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
392 	struct wifi_raw_scan_result bcn_prb_resp_info;
393 	int frame_length = 0;
394 	int val = signal;
395 
396 	vif_ctx_zep = vif_ctx;
397 
398 	if (!vif_ctx_zep) {
399 		LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
400 		return;
401 	}
402 
403 	if (!vif_ctx_zep->scan_in_progress) {
404 		/*LOG_INF("%s: Scan not in progress : raw scan data not available", __func__);*/
405 		return;
406 	}
407 
408 	rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
409 
410 	if (!rpu_ctx_zep) {
411 		LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
412 		return;
413 	}
414 
415 	k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
416 	if (!rpu_ctx_zep->rpu_ctx) {
417 		LOG_DBG("%s: RPU context not initialized", __func__);
418 		goto out;
419 	}
420 
421 	fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
422 
423 	frame_length = nrf_wifi_osal_nbuf_data_size(nwb);
424 
425 	if (frame_length > CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH) {
426 		nrf_wifi_osal_mem_cpy(&bcn_prb_resp_info.data,
427 				      nrf_wifi_osal_nbuf_data_get(nwb),
428 				      CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH);
429 
430 	} else {
431 		nrf_wifi_osal_mem_cpy(&bcn_prb_resp_info.data,
432 				      nrf_wifi_osal_nbuf_data_get(nwb),
433 				      frame_length);
434 	}
435 
436 	bcn_prb_resp_info.rssi = MBM_TO_DBM(val);
437 	bcn_prb_resp_info.frequency = frequency;
438 	bcn_prb_resp_info.frame_length = frame_length;
439 
440 	wifi_mgmt_raise_raw_scan_result_event(vif_ctx_zep->zep_net_if_ctx,
441 					      &bcn_prb_resp_info);
442 
443 out:
444 	k_mutex_unlock(&vif_ctx_zep->vif_lock);
445 }
446 #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */
447