1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 /* ****************************************************************************
20 1 头文件包含
21 **************************************************************************** */
22 #include "wal_scan.h"
23 #include "wal_cfg80211.h"
24 #include "wal_main.h"
25 #include "wal_event.h"
26 #include "hmac_ext_if.h"
27 #include "frw_timer.h"
28 #include "wal_cfg80211_apt.h"
29 #include "hdf_wifi_event.h"
30 #include "hi_task.h"
31 #include "hi_wifi_driver_wpa_if.h"
32 #include "osal_mem.h"
33
34 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
35 #ifndef _PRE_HDF_LINUX
36 #include <net/cfg80211.h>
37 #endif
38 #elif (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
39 #ifndef U64
40 #define U64 UINT64
41 #endif
42 #endif
43
44 #ifdef __cplusplus
45 #if __cplusplus
46 extern "C" {
47 #endif
48 #endif
49
50 /* ****************************************************************************
51 2 全局变量定义
52 **************************************************************************** */
53 /* ****************************************************************************
54 3 函数实现
55 **************************************************************************** */
56 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) || defined(_PRE_HDF_LINUX)
wal_free_scan_mgmt_resource(hmac_scan_stru * scan_mgmt)57 hi_void wal_free_scan_mgmt_resource(hmac_scan_stru *scan_mgmt)
58 {
59 if (scan_mgmt->request->ssids != HI_NULL) {
60 OsalMemFree(scan_mgmt->request->ssids);
61 scan_mgmt->request->ssids = HI_NULL;
62 }
63 if (scan_mgmt->request->ie != HI_NULL) {
64 OsalMemFree(scan_mgmt->request->ie);
65 scan_mgmt->request->ie = HI_NULL;
66 }
67 OsalMemFree(scan_mgmt->request);
68 scan_mgmt->request = HI_NULL;
69 }
70 #endif
71
72 /* ****************************************************************************
73 函 数 名 : wal_inform_bss_frame
74 功能描述 : 逐个上报ssid消息给内核
75 输入参数 : 无
76 输出参数 : 无
77 返 回 值 :
78 调用函数 :
79 被调函数 :
80
81 修改历史 :
82 1.日 期 : 2013年8月29日
83 作 者 : HiSilicon
84 修改内容 : 新生成函数
85
86 **************************************************************************** */
wal_inform_bss_frame(const oal_net_device_stru * netdev,wal_scanned_bss_info_stru * scanned_bss_info,hi_void * data)87 static hi_void wal_inform_bss_frame(const oal_net_device_stru *netdev, wal_scanned_bss_info_stru *scanned_bss_info,
88 hi_void *data)
89 {
90 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
91 oal_cfg80211_bss_stru *cfg80211_bss = HI_NULL;
92 #endif
93 oal_wiphy_stru *wiphy = HI_NULL;
94 oal_ieee80211_channel_stru *ieee80211_channel = HI_NULL;
95
96 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
97 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0))
98 struct timespec ts;
99 #endif
100 #endif
101
102 if ((scanned_bss_info == HI_NULL) || (data == HI_NULL)) {
103 oam_error_log2(0, OAM_SF_SCAN,
104 "{wal_inform_bss_frame::input param pointer is null, pst_scanned_bss_info[%p], p_data[%p]!}",
105 (uintptr_t)scanned_bss_info, (uintptr_t)data);
106 return;
107 }
108
109 wiphy = (oal_wiphy_stru *)data;
110
111 ieee80211_channel = oal_ieee80211_get_channel(wiphy, (hi_s32)scanned_bss_info->s_freq);
112 if (ieee80211_channel == HI_NULL) {
113 oam_warning_log1(0, OAM_SF_SCAN, "{wal_inform_bss_frame::get channel failed, wrong s_freq[%d]}",
114 (hi_s32)scanned_bss_info->s_freq);
115 return;
116 }
117
118 scanned_bss_info->l_signal = scanned_bss_info->l_signal * 100; /* 100 扩大100倍 */
119
120 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
121 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0))
122 /* 由于驱动缓存扫描结果,导致cts认证2次扫描的bss的timestamp时间一致(后一次没有扫描到) */
123 get_monotonic_boottime(&ts);
124 scanned_bss_info->mgmt->u.probe_resp.timestamp = ((hi_u64)ts.tv_sec * 1000000) /* 1000000 时间戳单位转换为s */
125 + ts.tv_nsec / 1000; /* 1000 时间戳单位转换为s */
126 #endif
127 #endif
128 /* 扫描维测 */
129 oam_info_log3(0, OAM_SF_SCAN, "{wal_inform_bss_frame::bssid:0x%x:XX:XX:XX:0x%x:0x%x}",
130 scanned_bss_info->mgmt->bssid[0], scanned_bss_info->mgmt->bssid[4], scanned_bss_info->mgmt->bssid[5]); /* 4 5 */
131
132 /* 逐个上报内核bss 信息 */
133 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) || defined(_PRE_HDF_LINUX)
134 struct WlanChannel channel = {
135 .channelId = ieee80211_channel->hw_value,
136 .centerFreq = ieee80211_channel->center_freq,
137 .flags = ieee80211_channel->flags,
138 };
139 HdfWifiEventInformBssFrame(netdev, &channel, (struct ScannedBssInfo *)scanned_bss_info);
140 #elif (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
141 cfg80211_bss = oal_cfg80211_inform_bss_frame(wiphy, ieee80211_channel, scanned_bss_info->mgmt,
142 scanned_bss_info->mgmt_len, scanned_bss_info->l_signal, GFP_ATOMIC);
143 #endif
144 #if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) && !defined(_PRE_HDF_LINUX)
145 if (cfg80211_bss != NULL) {
146 /* cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) */
147 oal_cfg80211_put_bss(wiphy, cfg80211_bss);
148 }
149 #elif (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
150 /* liteos has no cfg80211_put_bss */
151 #endif
152
153 return;
154 }
155
156 /* ****************************************************************************
157 函 数 名 : wal_inform_all_bss
158 功能描述 : 上报所有的bss到内核
159 输入参数 : oal_wiphy_stru *pst_wiphy,
160 hmac_bss_mgmt_stru *pst_bss_mgmt,
161 hi_u8 uc_vap_id
162 输出参数 : 无
163 返 回 值 :
164 调用函数 :
165 被调函数 :
166
167 修改历史 :
168 1.日 期 : 2015年7月8日
169 作 者 : HiSilicon
170 修改内容 : 新生成函数
171
172 **************************************************************************** */
wal_inform_all_bss(const oal_net_device_stru * netdev,oal_wiphy_stru * wiphy,hmac_bss_mgmt_stru * bss_mgmt,hi_u8 vap_id)173 hi_void wal_inform_all_bss(const oal_net_device_stru *netdev, oal_wiphy_stru *wiphy, hmac_bss_mgmt_stru *bss_mgmt,
174 hi_u8 vap_id)
175 {
176 hi_list *entry = HI_NULL;
177 wal_scanned_bss_info_stru scanned_bss_info;
178 hi_u32 bss_num_not_in_regdomain = 0;
179
180 #ifdef _PRE_WLAN_FEATURE_MESH
181 mac_vap_stru *mac_vap = mac_vap_get_vap_stru(vap_id);
182 if (mac_vap == HI_NULL) {
183 oam_error_log0(0, OAM_SF_SCAN, "{wal_inform_all_bss::mac_vap_get_vap_stru failed}");
184 return;
185 }
186 #else
187 hi_unref_param(vap_id);
188 #endif
189
190 /* 获取锁 */
191 oal_spin_lock(&(bss_mgmt->st_lock));
192
193 /* 遍历扫描到的bss信息 */
194 hi_list_for_each(entry, &(bss_mgmt->bss_list_head)) {
195 hmac_scanned_bss_info *scanned_bss = hi_list_entry(entry, hmac_scanned_bss_info, dlist_head);
196 hi_u8 chan = scanned_bss->bss_dscr_info.channel.chan_number;
197 enum ieee80211_band band = (enum ieee80211_band)scanned_bss->bss_dscr_info.channel.band;
198
199 /* 判断信道是不是在管制域内,如果不在,则不上报内核 */
200 if (mac_is_channel_num_valid(band, chan) != HI_SUCCESS) {
201 oam_warning_log2(vap_id, OAM_SF_SCAN, "{wal_inform_all_bss::chan=%d,band=%d not in regdomain}", chan, band);
202 bss_num_not_in_regdomain++;
203 continue;
204 }
205
206 #ifdef _PRE_WLAN_FEATURE_ANY
207 /* 支持ANY的设备进行扫描的时候,会把支持ANY的其他STA设备也扫描到,此时这些STA不应该上报内核,只上报AP */
208 if ((scanned_bss->bss_dscr_info.supp_any == HI_TRUE) && (scanned_bss->bss_dscr_info.is_any_sta == HI_TRUE)) {
209 continue;
210 }
211 #endif
212
213 /* 安全编程规则6.6例外(1) 固定长度的结构体进行内存初始化 */
214 memset_s(&scanned_bss_info, sizeof(wal_scanned_bss_info_stru), 0, sizeof(wal_scanned_bss_info_stru));
215 scanned_bss_info.l_signal = scanned_bss->bss_dscr_info.rssi;
216
217 /* 填bss所在信道的中心频率 */
218 scanned_bss_info.s_freq = (hi_s16)oal_ieee80211_channel_to_frequency(chan, band);
219
220 /* 填管理帧指针和长度 */
221 scanned_bss_info.mgmt = (oal_ieee80211_mgmt_stru *)(scanned_bss->bss_dscr_info.auc_mgmt_buff);
222 scanned_bss_info.mgmt_len = scanned_bss->bss_dscr_info.mgmt_len;
223
224 /* 获取上报的扫描结果的管理帧的帧头 */
225 mac_ieee80211_frame_stru *frame_hdr = (mac_ieee80211_frame_stru *)scanned_bss->bss_dscr_info.auc_mgmt_buff;
226
227 /* 如果扫描请求接收到的帧类型有beacon类型,统一修改为probe rsp类型上报,
228 为了解决上报内核的扫描结果beacon帧不够敏感的问题,此问题,在01出现过 */
229 frame_hdr->frame_control.sub_type =
230 (frame_hdr->frame_control.sub_type == WLAN_BEACON) ? WLAN_PROBE_RSP : frame_hdr->frame_control.sub_type;
231
232 /* 上报扫描结果给内核 */
233 /* 如果是mesh ap发起的扫描,只上报mesh ap */
234 #ifdef _PRE_WLAN_FEATURE_MESH
235 if (((mac_vap->vap_mode == WLAN_VAP_MODE_MESH) && (scanned_bss->bss_dscr_info.is_hisi_mesh == HI_TRUE)) ||
236 (mac_vap->vap_mode != WLAN_VAP_MODE_MESH)) {
237 wal_inform_bss_frame(netdev, &scanned_bss_info, wiphy);
238 }
239 #else
240 wal_inform_bss_frame(netdev, &scanned_bss_info, wiphy);
241 #endif
242 }
243
244 /* 解除锁 */
245 oal_spin_unlock(&(bss_mgmt->st_lock));
246
247 oam_warning_log2(vap_id, OAM_SF_SCAN, "{wal_inform_all_bss::%d bss not in regdomain,inform kernal bss num=%d}",
248 bss_num_not_in_regdomain, (bss_mgmt->bss_num - bss_num_not_in_regdomain));
249 }
250
251 /* ****************************************************************************
252 函 数 名 : wal_free_scan_resource
253 功能描述 : 释放申请的信道信息资源
254 输入参数 : mac_cfg80211_scan_param_stru *
255 输出参数 : 无
256 返 回 值 :
257 调用函数 :
258 被调函数 :
259
260 修改历史 :
261 1.日 期 : 2013年8月27日
262 作 者 : HiSilicon
263 修改内容 : 新生成函数
264
265 **************************************************************************** */
wal_free_scan_resource(mac_cfg80211_scan_param_stru * scan_param)266 static hi_void wal_free_scan_resource(mac_cfg80211_scan_param_stru *scan_param)
267 {
268 if (scan_param->pul_channels_2_g != HI_NULL) {
269 oal_free(scan_param->pul_channels_2_g);
270 scan_param->pul_channels_2_g = HI_NULL;
271 }
272 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
273 if (scan_param->puc_ie != HI_NULL) {
274 oal_free((hi_u8 *)(scan_param->puc_ie));
275 scan_param->puc_ie = HI_NULL;
276 }
277 #endif
278 oal_mem_free(scan_param);
279 }
280
281 /* ****************************************************************************
282 函 数 名 : wal_set_scan_channel
283 功能描述 : 提取内核下发扫描信道相关参数
284 输入参数 : 无
285 输出参数 : 无
286 返 回 值 :
287 调用函数 :
288 被调函数 :
289
290 修改历史 :
291 1.日 期 : 2013年8月27日
292 作 者 : HiSilicon
293 修改内容 : 新生成函数
294
295 **************************************************************************** */
wal_set_scan_channel(const oal_cfg80211_scan_request_stru * request,mac_cfg80211_scan_param_stru * scan_param)296 static hi_u32 wal_set_scan_channel(const oal_cfg80211_scan_request_stru *request,
297 mac_cfg80211_scan_param_stru *scan_param)
298 {
299 hi_u32 loop;
300 hi_u32 num_chan_2g = 0;
301
302 if (request->n_channels == 0) {
303 oam_error_log0(0, OAM_SF_SCAN, "{wal_get_scan_channel_num::channel number is 0 in scan request, is wrong!}");
304 return HI_FAIL;
305 }
306
307 scan_param->pul_channels_2_g = (hi_u32 *)oal_memalloc(request->n_channels * sizeof(hi_u32));
308 if (oal_unlikely(scan_param->pul_channels_2_g == HI_NULL)) {
309 oam_error_log0(0, OAM_SF_SCAN, "{wal_scan_work_func::memory is too low, fail to alloc for 2.4G channel!}");
310 return HI_ERR_CODE_ALLOC_MEM_FAIL;
311 }
312
313 for (loop = 0; loop < request->n_channels; loop++) {
314 hi_u16 us_center_freq;
315 hi_u32 chn;
316
317 us_center_freq = request->channels[loop]->center_freq;
318
319 /* 根据中心频率,计算信道号 */
320 chn = (hi_u32)oal_ieee80211_frequency_to_channel((hi_s32)us_center_freq);
321
322 if (us_center_freq <= WAL_MAX_FREQ_2G) {
323 scan_param->pul_channels_2_g[num_chan_2g++] = chn;
324 }
325 }
326
327 scan_param->num_channels_2_g = (hi_u8)num_chan_2g;
328
329 if (num_chan_2g == 0) {
330 oal_free(scan_param->pul_channels_2_g);
331 scan_param->pul_channels_2_g = HI_NULL;
332 }
333
334 return HI_SUCCESS;
335 }
336
337 /* ****************************************************************************
338 功能描述 : 设置扫描的SSID
339
340 修改历史 :
341 1.日 期 : 2013年8月28日
342 作 者 : HiSilicon
343 修改内容 : 新生成函数
344
345 **************************************************************************** */
wal_set_scan_ssid(const oal_cfg80211_scan_request_stru * request,mac_cfg80211_scan_param_stru * scan_param)346 static hi_void wal_set_scan_ssid(const oal_cfg80211_scan_request_stru *request,
347 mac_cfg80211_scan_param_stru *scan_param)
348 {
349 hi_u32 loop;
350 hi_u32 index = 0;
351 hi_u32 ssid_num;
352
353 scan_param->l_ssid_num = 0;
354 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
355 if (request->prefix_ssid_scan_flag == HI_TRUE) {
356 scan_param->l_ssid_num = request->n_ssids;
357 return;
358 }
359 #endif
360
361 /* 取内核下发的ssid的个数 */
362 ssid_num = (request->n_ssids > WLAN_SCAN_REQ_MAX_BSS) ? WLAN_SCAN_REQ_MAX_BSS : request->n_ssids;
363
364 /* 将用户下发的ssid信息拷贝到对应的结构体中 */
365 if ((ssid_num == 0) || (request->ssids == HI_NULL)) {
366 return;
367 }
368
369 for (loop = 0; loop < ssid_num; loop++) {
370 if (scan_param->ssids[index].ssid_len > OAL_IEEE80211_MAX_SSID_LEN) {
371 oam_warning_log2(0, OAM_SF_SCAN, "{wal_set_scan_ssid::ssid length [%d] is larger than %d, skip it.}",
372 scan_param->ssids[loop].ssid_len, OAL_IEEE80211_MAX_SSID_LEN);
373 continue;
374 }
375 scan_param->ssids[index].ssid_len = request->ssids[loop].ssid_len;
376 if (memcpy_s(scan_param->ssids[index].auc_ssid, OAL_IEEE80211_MAX_SSID_LEN, request->ssids[loop].ssid,
377 scan_param->ssids[loop].ssid_len) != EOK) {
378 oam_warning_log0(0, OAM_SF_SCAN, "{wal_set_scan_ssid::fail to copy ssid to scan_param, skip it!}");
379 continue;
380 }
381 index++;
382 }
383
384 scan_param->l_ssid_num = index;
385 }
386
387 /* ****************************************************************************
388 功能描述 : 等待扫描完成超时处理函数
389
390 修改历史 :
391 1.日 期 : 2015年5月19日
392 作 者 : HiSilicon
393 修改内容 : 新生成函数
394
395 **************************************************************************** */
wal_wait_for_scan_timeout_fn(hi_void * arg)396 static hi_u32 wal_wait_for_scan_timeout_fn(hi_void *arg)
397 {
398 hmac_vap_stru *hmac_vap = (hmac_vap_stru *)arg;
399 mac_vap_stru *mac_vap = hmac_vap->base_vap;
400 hmac_device_stru *hmac_dev = HI_NULL;
401 mac_device_stru *mac_dev = HI_NULL;
402 hmac_bss_mgmt_stru *bss_mgmt = HI_NULL;
403 hmac_scan_stru *scan_mgmt = HI_NULL;
404 oal_wiphy_stru *wiphy = HI_NULL;
405 oal_net_device_stru *netdev = HI_NULL;
406
407 oam_warning_log0(mac_vap->vap_id, OAM_SF_SCAN, "{wal_wait_for_scan_timeout_fn:: 5 seconds scan timeout proc.}");
408
409 /* 根据当前扫描的类型和当前vap的状态,决定切换vap的状态,扫描异常保护中,上报内核扫描状态为扫描完成 */
410 if ((mac_vap->vap_mode == WLAN_VAP_MODE_BSS_STA) && (mac_vap->vap_state == MAC_VAP_STATE_STA_WAIT_SCAN)) {
411 /* 改变vap状态到SCAN_COMP */
412 mac_vap_state_change(mac_vap, MAC_VAP_STATE_STA_SCAN_COMP);
413 }
414
415 /* 获取hmac device */
416 hmac_dev = hmac_get_device_stru();
417 mac_dev = mac_res_get_dev();
418 scan_mgmt = &(hmac_dev->scan_mgmt);
419 wiphy = mac_dev->wiphy;
420
421 /* 获取net_device */
422 netdev = hmac_vap_get_net_device(mac_vap->vap_id);
423 if (netdev == HI_NULL) {
424 oam_error_log0(0, OAM_SF_ASSOC, "{wal_mesh_close_peer_inform::get net device ptr is null!}\r\n");
425 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) || defined(_PRE_HDF_LINUX)
426 oal_spin_lock(&(scan_mgmt->st_scan_request_spinlock));
427 wal_free_scan_mgmt_resource(scan_mgmt);
428 oal_spin_unlock(&(scan_mgmt->st_scan_request_spinlock));
429 #elif (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
430 scan_mgmt->request = HI_NULL;
431 #endif
432 scan_mgmt->complete = HI_TRUE;
433 scan_mgmt->is_scanning = HI_FALSE;
434 return HI_ERR_CODE_PTR_NULL;
435 }
436
437 /* 获取扫描结果的管理结构地址 */
438 bss_mgmt = &(hmac_dev->scan_mgmt.scan_record_mgmt.bss_mgmt);
439
440 /* 对于内核下发的扫描request资源加锁 */
441 oal_spin_lock(&(scan_mgmt->st_scan_request_spinlock));
442
443 if (scan_mgmt->request != HI_NULL) {
444 /* 上报扫描到的所有的bss */
445 wal_inform_all_bss(netdev, wiphy, bss_mgmt, mac_vap->vap_id);
446
447 /* 通知 kernel scan 已经结束 */
448 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) || defined(_PRE_HDF_LINUX)
449 HdfWifiEventScanDone(netdev, (WifiScanStatus)HISI_SCAN_TIMEOUT);
450 wal_free_scan_mgmt_resource(scan_mgmt);
451 #elif (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
452 oal_cfg80211_scan_done(scan_mgmt->request, 0);
453 scan_mgmt->request = HI_NULL;
454 #endif
455 scan_mgmt->complete = HI_TRUE;
456 scan_mgmt->is_scanning = HI_FALSE;
457 }
458
459 /* 通知完内核,释放资源后解锁 */
460 oal_spin_unlock(&(scan_mgmt->st_scan_request_spinlock));
461
462 return HI_SUCCESS;
463 }
464
465 /* ****************************************************************************
466 函 数 名 : wal_process_timer_for_scan
467 功能描述 : 关闭扫描结果老化定时器,启动扫描定时器做扫描超时保护处理
468
469 修改历史 :
470 1.日 期 : 2015年5月19日
471 作 者 : HiSilicon
472 修改内容 : 新生成函数
473
474 **************************************************************************** */
wal_process_timer_for_scan(hi_u8 vap_id)475 static hi_void wal_process_timer_for_scan(hi_u8 vap_id)
476 {
477 hmac_vap_stru *hmac_vap = HI_NULL;
478
479 /* 获取hmac vap */
480 hmac_vap = hmac_vap_get_vap_stru(vap_id);
481 if (hmac_vap == HI_NULL) {
482 oam_error_log0(vap_id, OAM_SF_SCAN, "{wal_process_timer_for_scan::pst_hmac_vap is null!}");
483 return;
484 }
485 /* 关闭扫描结果老化定时器 */
486 if (hmac_vap->scan_timeout.is_registerd == HI_TRUE) {
487 frw_timer_immediate_destroy_timer(&(hmac_vap->scanresult_clean_timeout));
488 }
489 /* 启动扫描保护定时器,在指定时间没有上报扫描结果,主动上报扫描完成 */
490 frw_timer_create_timer(&(hmac_vap->scan_timeout), wal_wait_for_scan_timeout_fn, WAL_MAX_SCAN_TIME_PER_SCAN_REQ,
491 hmac_vap, HI_FALSE);
492
493 return;
494 }
495
496 /* ****************************************************************************
497 函 数 名 : wal_start_scan_req
498 功能描述 : 解析内核下发扫描命令相关参数,启动扫描
499 输入参数 : 无
500 输出参数 : 无
501 返 回 值 :
502 调用函数 :
503 被调函数 :
504
505 修改历史 :
506 1.日 期 : 2013年8月27日
507 作 者 : HiSilicon
508 修改内容 : 新生成函数
509
510 **************************************************************************** */
wal_start_scan_req(oal_net_device_stru * netdev,hmac_scan_stru * scan_mgmt)511 hi_u32 wal_start_scan_req(oal_net_device_stru *netdev, hmac_scan_stru *scan_mgmt)
512 {
513 mac_cfg80211_scan_param_stru *scan_param = HI_NULL;
514 hi_u32 ret;
515 mac_vap_stru *mac_vap = oal_net_dev_priv(netdev);
516 hi_u8 vap_id = mac_vap->vap_id;
517 oal_cfg80211_scan_request_stru *request = scan_mgmt->request;
518
519 scan_param =
520 (mac_cfg80211_scan_param_stru *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, sizeof(mac_cfg80211_scan_param_stru));
521 if (scan_param == HI_NULL) {
522 oam_error_log0(0, OAM_SF_SCAN, "{wal_start_scan_req::memory is too low, fail to alloc scan param memory!}");
523 return HI_ERR_CODE_PTR_NULL;
524 }
525 /* 安全编程规则6.6例外(3)从堆中分配内存后,赋予初值 */
526 memset_s(scan_param, sizeof(mac_cfg80211_scan_param_stru), 0, sizeof(mac_cfg80211_scan_param_stru));
527
528 /* 解析内核下发的扫描信道列表 */
529 if (wal_set_scan_channel(request, scan_param) != HI_SUCCESS) {
530 wal_free_scan_resource(scan_param);
531 return HI_FAIL;
532 }
533
534 /* 解析内核下发的ssid */
535 wal_set_scan_ssid(request, scan_param);
536
537 /* 解析内核下发的ie, Mesh ID携带在IE段中 */
538 if ((request->ie_len > 0) && (request->ie != HI_NULL)) {
539 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
540 scan_param->puc_ie = (hi_u8 *)malloc(request->ie_len);
541 if (oal_unlikely(scan_param->puc_ie == HI_NULL)) {
542 oam_error_log0(0, OAM_SF_SCAN, "{wal_start_scan_req::memory is too low, fail to alloc for scan ie!}");
543 wal_free_scan_resource(scan_param);
544 return HI_FAIL;
545 }
546
547 if (memcpy_s((hi_void *)(scan_param->puc_ie), request->ie_len, request->ie, request->ie_len) != EOK) {
548 oam_error_log0(0, OAM_SF_SCAN, "{wal_start_scan_req::fail to copy scan ie, return!}");
549 wal_free_scan_resource(scan_param);
550 return HI_FAIL;
551 }
552 #elif (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
553 scan_param->puc_ie = request->ie;
554 #endif
555
556 scan_param->ie_len = request->ie_len;
557 } else {
558 scan_param->puc_ie = HI_NULL;
559 scan_param->ie_len = 0;
560 }
561
562 scan_param->scan_type = OAL_ACTIVE_SCAN; /* active scan */
563
564 /* P2P WLAN/P2P 特性情况下,根据扫描的ssid 判断是否为p2p device 发起的扫描,
565 * ssid 为"DIRECT-"则认为是p2p device 发起的扫描解析下发扫描的device 是否为p2p device(p2p0)
566 */
567 if (is_p2p_scan_req(request)) {
568 scan_param->is_p2p0_scan = HI_TRUE;
569 }
570
571 /* 在事件前防止异步调度完成扫描后,发生同步问题 */
572 scan_mgmt->complete = HI_FALSE;
573
574 /* 抛事件,通知驱动启动扫描 */
575 ret = wal_cfg80211_start_req(netdev, &scan_param, sizeof(uintptr_t), WLAN_CFGID_CFG80211_START_SCAN, HI_TRUE);
576 if (ret != HI_SUCCESS) {
577 wal_free_scan_resource(scan_param);
578 oal_cfg80211_scan_done(scan_mgmt->request, 0);
579 scan_mgmt->complete = HI_TRUE;
580 return HI_FAIL;
581 }
582 wal_free_scan_resource(scan_param);
583 /* 关闭扫描结果老化定时器,启动扫描超时定时器 */
584 wal_process_timer_for_scan(vap_id);
585
586 return HI_SUCCESS;
587 }
588
589 /* ****************************************************************************
590 函 数 名 : wal_send_scan_abort_msg
591 功能描述 : 终止扫描
592 输入参数 : oal_net_device_stru *pst_net_dev
593 输出参数 : 无
594 返 回 值 : hi_s32
595 调用函数 :
596 被调函数 :
597
598 修改历史 :
599 1.日 期 : 2015年7月8日
600 作 者 : HiSilicon
601 修改内容 : 新生成函数
602
603 **************************************************************************** */
wal_send_scan_abort_msg(oal_net_device_stru * netdev)604 hi_u32 wal_send_scan_abort_msg(oal_net_device_stru *netdev)
605 {
606 wal_msg_write_stru write_msg;
607 hi_u32 pedding_data = 0; /* 填充数据,不使用,只是为了复用接口 */
608 hi_u32 ret;
609 wal_msg_stru *rsp_msg = HI_NULL;
610
611 /* 拋事件通知device侧终止扫描 */
612 wal_write_msg_hdr_init(&write_msg, WLAN_CFGID_SCAN_ABORT, sizeof(pedding_data));
613
614 if (memcpy_s(write_msg.auc_value, sizeof(pedding_data), (hi_s8 *)&pedding_data, sizeof(pedding_data)) != EOK) {
615 oam_error_log0(0, OAM_SF_SCAN, "{wal_send_scan_abort_msg::mem safe function err!}");
616 return HI_FAIL;
617 }
618
619 ret = wal_send_cfg_event(netdev, WAL_MSG_TYPE_WRITE, WAL_MSG_WRITE_MSG_HDR_LENGTH + sizeof(pedding_data),
620 (hi_u8 *)&write_msg, HI_TRUE, &rsp_msg);
621 if (HI_SUCCESS != wal_check_and_release_msg_resp(rsp_msg)) {
622 oam_warning_log0(0, OAM_SF_SCAN, "{wal_send_scan_abort_msg::wal_check_and_release_msg_resp fail.}");
623 }
624
625 if (ret != HI_SUCCESS) {
626 oam_warning_log1(0, OAM_SF_SCAN, "{wal_send_scan_abort_msg::fail to stop scan, error[%u]}", ret);
627 }
628
629 return ret;
630 }
631
632 /* ************** **************************************************************
633 函 数 名 : wal_force_scan_complete
634 功能描述 : 通知扫描完成
635 输入参数 : oal_net_device_stru *pst_net_dev,
636 hi_bool en_is_aborted
637 输出参数 : 无
638 返 回 值 : hi_s32
639 调用函数 :
640 被调函数 :
641
642 修改历史 :
643 1.日 期 : 2015年7月8日
644 作 者 : HiSilicon
645 修改内容 : 新生成函数
646
647 **************************************************************************** */
wal_force_scan_complete(oal_net_device_stru * netdev)648 hi_u32 wal_force_scan_complete(oal_net_device_stru *netdev)
649 {
650 mac_device_stru *mac_dev = mac_res_get_dev();
651
652 mac_vap_stru *mac_vap = oal_net_dev_priv(netdev);
653 if (mac_vap == HI_NULL) {
654 oam_warning_log0(0, OAM_SF_SCAN, "{wal_force_scan_complete::Cannot find mac_vap by net_dev!}");
655 return HI_ERR_CODE_PTR_NULL;
656 }
657
658 /* 获取hmac device */
659 hmac_device_stru *hmac_dev = hmac_get_device_stru();
660 /* stop的vap和正在扫描的vap不相同则直接返回 */
661 if (mac_vap->vap_id != hmac_dev->scan_mgmt.scan_record_mgmt.vap_id) {
662 oam_warning_log2(mac_vap->vap_id, OAM_SF_SCAN,
663 "{wal_force_scan_complete::stop_vap[%d] is different scan_vap[%d]!}", mac_vap->vap_id,
664 hmac_dev->scan_mgmt.scan_record_mgmt.vap_id);
665 return HI_SUCCESS;
666 }
667
668 hmac_scan_stru *scan_mgmt = &(hmac_dev->scan_mgmt);
669
670 /* 结束扫描的时候设置标志为非ANY扫描 */
671 scan_mgmt->scan_record_mgmt.is_any_scan = HI_FALSE;
672
673 /* 如果是来自内部的扫描 */
674 if (scan_mgmt->request == HI_NULL) {
675 /* 判断是否存在内部扫描,如果存在,也需要停止 */
676 if ((hmac_dev->scan_mgmt.is_scanning == HI_TRUE) &&
677 (mac_vap->vap_id == hmac_dev->scan_mgmt.scan_record_mgmt.vap_id)) {
678 oam_warning_log0(mac_vap->vap_id, OAM_SF_SCAN, "{wal_force_scan_complete::maybe internal scan,stop scan}");
679 /* 终止扫描 */
680 wal_send_scan_abort_msg(netdev);
681 }
682
683 return HI_SUCCESS;
684 }
685
686 /* 获取hmac vap */
687 hmac_vap_stru *hmac_vap = hmac_vap_get_vap_stru(mac_vap->vap_id);
688 if (hmac_vap == HI_NULL) {
689 oam_warning_log1(mac_vap->vap_id, OAM_SF_SCAN, "{wal_force_scan_complete::hmac_vap is null, vap_id[%d]!}",
690 mac_vap->vap_id);
691 return HI_ERR_CODE_PTR_NULL;
692 }
693
694 /* 删除等待扫描超时定时器 */
695 if (hmac_vap->scan_timeout.is_registerd == HI_TRUE) {
696 frw_timer_immediate_destroy_timer(&(hmac_vap->scan_timeout));
697 }
698
699 /* 如果是上层下发的扫描请求,则通知内核扫描结束,内部扫描不需通知 */
700 if (scan_mgmt->request != HI_NULL) {
701 /* 对于内核下发的扫描request资源加锁 */
702 oal_spin_lock(&(scan_mgmt->st_scan_request_spinlock));
703
704 /* 上报内核扫描结果 */
705 wal_inform_all_bss(netdev, mac_dev->wiphy, &(hmac_dev->scan_mgmt.scan_record_mgmt.bss_mgmt), mac_vap->vap_id);
706
707 /* 通知内核扫描终止 */
708 #if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) || defined(_PRE_HDF_LINUX)
709 HdfWifiEventScanDone(netdev, (WifiScanStatus)HISI_SCAN_SUCCESS);
710 wal_free_scan_mgmt_resource(scan_mgmt);
711 #elif (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION)
712 oal_cfg80211_scan_done(scan_mgmt->request, HI_TRUE);
713 scan_mgmt->request = HI_NULL;
714 #endif
715 scan_mgmt->complete = HI_TRUE;
716
717 /* 通知完内核,释放资源后解锁 */
718 oal_spin_unlock(&(scan_mgmt->st_scan_request_spinlock));
719
720 /* 下发device终止扫描 */
721 wal_send_scan_abort_msg(netdev);
722
723 oam_info_log1(mac_vap->vap_id, OAM_SF_SCAN, "{wal_force_scan_complete::force to stop scan of vap_id[%d]}",
724 mac_vap->vap_id);
725 }
726
727 return HI_SUCCESS;
728 }
729
730 #ifdef __cplusplus
731 #if __cplusplus
732 }
733 #endif
734 #endif
735