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