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