• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright: Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  * Description: PS处理
15  * Date: 2023-01-28 15:24
16  */
17 
18 #ifndef __HMAC_BTCOEX_PS_C__
19 #define __HMAC_BTCOEX_PS_C__
20 
21 #include "hmac_scan.h"
22 #include "hmac_fcs.h"
23 #include "msg_btcoex_rom.h"
24 #include "hmac_btcoex.h"
25 #include "frw_util_notifier.h"
26 #include "hmac_feature_interface.h"
27 #include "hmac_btcoex_ps.h"
28 
29 #ifdef __cplusplus
30 #if __cplusplus
31     extern "C" {
32 #endif
33 #endif
34 #undef THIS_FILE_ID
35 #define THIS_FILE_ID DIAG_FILE_ID_WIFI_HOST_HMAC_BTCOEX_PS_C
36 
37 #undef THIS_MOD_ID
38 #define THIS_MOD_ID DIAG_MOD_ID_WIFI_HOST
39 /*****************************************************************************
40  函 数 名  : hmac_btcoex_encap_preempt_frame
41  功能描述  : 根据指定的PS位封null data帧
42 *****************************************************************************/
hmac_btcoex_encap_preempt_frame(hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user)43 OSAL_STATIC osal_void hmac_btcoex_encap_preempt_frame(hmac_vap_stru *hmac_vap, const hmac_user_stru *hmac_user)
44 {
45     hal_to_dmac_device_stru *hal_device = hmac_vap->hal_device;
46     osal_u32 qosnull_seq_num = 0;
47 
48     if (hal_device == OSAL_NULL) {
49         oam_warning_log1(0, 0, "vap_id[%d] {hmac_btcoex_encap_preempt_frame:: HAL_DEVICE null}", hmac_vap->vap_id);
50         return;
51     }
52 
53     /* 初始化dmac vap对应的preempt字段,包括写给硬件的premmpt帧地址和premmpt帧的参数 */
54     (osal_void)memset_s(&(hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param),
55         sizeof(hmac_vap_btcoex_null_preempt_stru), 0, sizeof(hmac_vap_btcoex_null_preempt_stru));
56 
57     switch (hmac_btcoex_get_vap_info(hmac_vap)->all_abort_preempt_type) {
58         case HAL_BTCOEX_HW_POWSAVE_NOFRAME:
59         case HAL_BTCOEX_HW_POWSAVE_SELFCTS:
60             break;
61 
62         case HAL_BTCOEX_HW_POWSAVE_NULLDATA: {
63             /* 填写帧头,其中from ds为1,to ds为0,ps=1 因此frame control的第二个字节为12 */
64             mac_ieee80211_frame_stru *mac_header = (mac_ieee80211_frame_stru *) \
65                 hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.null_qosnull_frame;
66             mac_null_data_encap(hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.null_qosnull_frame,
67                 WLAN_PROTOCOL_VERSION | WLAN_FC0_TYPE_DATA | WLAN_FC0_SUBTYPE_NODATA | 0x1100,
68                 hmac_user->user_mac_addr,
69                 mac_mib_get_station_id(hmac_vap));
70 
71             /* 22表示seq num位 */
72             hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.null_qosnull_frame[22] = 0;
73             /* 23表示frag位 */
74             hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.null_qosnull_frame[23] = 0;
75             mac_header->frame_control.power_mgmt = 1;
76             break;
77         }
78 
79         case HAL_BTCOEX_HW_POWSAVE_QOSNULL: {
80             hmac_btcoex_qosnull_frame_stru *mac_header = (hmac_btcoex_qosnull_frame_stru *) \
81                 hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.null_qosnull_frame;
82             mac_null_data_encap(hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.null_qosnull_frame,
83                 WLAN_PROTOCOL_VERSION | WLAN_FC0_TYPE_DATA | WLAN_FC0_SUBTYPE_QOS_NULL |
84                     0x1100, hmac_user->user_mac_addr,
85                 mac_mib_get_station_id(hmac_vap));
86 
87             mac_header->frame_control.power_mgmt = 1;
88             mac_header->qc_tid = WLAN_TIDNO_COEX_QOSNULL;
89             mac_header->qc_eosp = 0;
90 
91             /* 设置seq的序列号 */
92             hal_get_btcoex_abort_qos_null_seq_num(hal_device, &qosnull_seq_num);
93             mac_header->sc_seq_num = (osal_u16)(qosnull_seq_num + 1);
94             hal_set_btcoex_abort_qos_null_seq_num(hal_device, mac_header->sc_seq_num);
95 
96             /* 协议规定单播的QOS NULL DATA只允许normal ack 共存里面要设置0是对方会回ack */
97             mac_header->qc_ack_polocy = WLAN_TX_NORMAL_ACK;
98             break;
99         }
100 
101         default:
102             oam_error_log2(0, OAM_SF_COEX, "vap_id[%d] {hmac_btcoex_encap_preempt_frame::sw_preempt_type[%d] error}",
103                 hmac_vap->vap_id, hmac_btcoex_get_vap_info(hmac_vap)->all_abort_preempt_type);
104             return;
105     }
106 
107     oam_warning_log2(0, OAM_SF_COEX, "vap_id[%d] {hmac_btcoex_encap_preempt_frame::sw_preempt_type[%d]!}",
108         hmac_vap->vap_id, hmac_btcoex_get_vap_info(hmac_vap)->all_abort_preempt_type);
109 }
110 
111 /*****************************************************************************
112  函 数 名  : hmac_btcoex_set_preempt_frame_param
113  功能描述  : 配置preempt帧的参数类型,注意pst_mac_user要保证不为空
114 *****************************************************************************/
hmac_btcoex_set_preempt_frame_param(hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user)115 OSAL_STATIC osal_void hmac_btcoex_set_preempt_frame_param(hmac_vap_stru *hmac_vap, const hmac_user_stru *hmac_user)
116 {
117     osal_u16 preempt_param_val = 0;
118 
119     switch (hmac_btcoex_get_vap_info(hmac_vap)->all_abort_preempt_type) {
120         case HAL_BTCOEX_HW_POWSAVE_NOFRAME:
121             /* 增加接口通用性,NOFRAME直接返回,写对应寄存器类型为0即可 */
122             return;
123 
124         case HAL_BTCOEX_HW_POWSAVE_SELFCTS:
125             break;
126 
127         case HAL_BTCOEX_HW_POWSAVE_NULLDATA:
128             hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.cfg_coex_tx_peer_index = hmac_user->lut_index;
129 
130             /* null配置peer idx */
131             preempt_param_val = preempt_param_val |
132                                 hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.cfg_coex_tx_peer_index;
133             break;
134 
135         case HAL_BTCOEX_HW_POWSAVE_QOSNULL:
136             hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.cfg_coex_tx_peer_index =  hmac_user->lut_index;
137             hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.cfg_coex_tx_qos_null_tid =
138                 WLAN_TIDNO_COEX_QOSNULL;
139 
140             /* qos null需要配置tid */
141             preempt_param_val = preempt_param_val | /* 8表示左移8位以取cfg_coex_tx_qos_null_tidde的低8位 */
142                 (hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.cfg_coex_tx_qos_null_tid << 8);
143             /* qos null配置peer idx */
144             preempt_param_val = preempt_param_val |
145                                 hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.cfg_coex_tx_peer_index;
146             break;
147 
148         default:
149             oam_error_log2(0, OAM_SF_COEX,
150                 "vap_id[%d] {hmac_btcoex_set_preempt_frame_param::sw_preempt_type[%d] error}", hmac_vap->vap_id,
151                 hmac_btcoex_get_vap_info(hmac_vap)->all_abort_preempt_type);
152             return;
153     }
154 
155     /* 03的self cts的时候也需要vap index; 02看软件开哪些vap里从0~4找,最先找到的vap的mac地址作为self cts的地址 */
156     hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.cfg_coex_tx_vap_index = hmac_vap->hal_vap->vap_id;
157 
158     /* 三类帧都需要配置vap index, self cts的时候也需要vap index(pilot才会做,软件先写好,后续注意验证) */
159     preempt_param_val = preempt_param_val |
160         (hmac_btcoex_get_vap_info(hmac_vap)->null_preempt_param.cfg_coex_tx_vap_index << 12); /* 12表示左移12位 */
161 
162     hal_set_btcoex_abort_preempt_frame_param(preempt_param_val);
163 
164     oam_warning_log3(0, OAM_SF_COEX,
165         "vap_id[%d] {hmac_btcoex_set_preempt_frame_param::SUCC sw_preempt_type[%d] preempt_param_val[%d]!}",
166         hmac_vap->vap_id, hmac_btcoex_get_vap_info(hmac_vap)->all_abort_preempt_type, preempt_param_val);
167 }
168 
169 /*****************************************************************************
170  函 数 名  : hmac_btcoex_init_preempt
171  功能描述  : preempt机制初始化
172              1.单VAP的话, AP和STA三种帧都可以发送,ap和sta都默认self-cts, 后续根据调试情况来调整
173              2.只要多个vap的都用self cts,sta和p2p gc同存也要用self cts,
174                 因为发null帧只能让一个ap不给我们发帧;
175 *****************************************************************************/
hmac_btcoex_init_preempt(hmac_vap_stru * hmac_vap,const hmac_user_stru * hmac_user,osal_u8 preempt_enable)176 osal_void hmac_btcoex_init_preempt(hmac_vap_stru *hmac_vap, const hmac_user_stru *hmac_user, osal_u8 preempt_enable)
177 {
178     hmac_vap_btcoex_stru *hmac_vap_btcoex = hmac_btcoex_get_vap_info(hmac_vap);
179     osal_s32 ret;
180 
181     if (hmac_vap_btcoex == OSAL_NULL) {
182         oam_error_log0(0, OAM_SF_CFG, "hmac_btcoex_init_preempt::hmac_vap_btcoex is null.");
183         return;
184     }
185 
186     /* 初始化为不发preempt帧 */
187     if (preempt_enable == OSAL_FALSE) {
188         hmac_vap_btcoex->all_abort_preempt_type = HAL_BTCOEX_HW_POWSAVE_NOFRAME;
189     } else {
190         hmac_vap_btcoex->all_abort_preempt_type = HAL_BTCOEX_HW_POWSAVE_NULLDATA;
191     }
192 
193     /* encap preempt帧 */
194     hmac_btcoex_encap_preempt_frame(hmac_vap, hmac_user);
195     /* 配置premmpt帧的参数 */
196     hmac_btcoex_set_preempt_frame_param(hmac_vap, hmac_user);
197     /* 写入null qos null帧地址 */
198     if ((hmac_vap_btcoex->all_abort_preempt_type == HAL_BTCOEX_HW_POWSAVE_NULLDATA) ||
199         (hmac_vap_btcoex->all_abort_preempt_type == HAL_BTCOEX_HW_POWSAVE_QOSNULL)) {
200         frw_msg msg_info = {0};
201         btcoex_null_preempt_stru btcoex_null_preempt;
202 
203         (osal_void)memcpy_s(btcoex_null_preempt.null_qosnull_frame, WLAN_COEX_PKT_LEN,
204             hmac_vap_btcoex->null_preempt_param.null_qosnull_frame, WLAN_COEX_PKT_LEN);
205         btcoex_null_preempt.cfg_coex_tx_vap_index = hmac_vap_btcoex->null_preempt_param.cfg_coex_tx_vap_index;
206         btcoex_null_preempt.cfg_coex_tx_qos_null_tid = hmac_vap_btcoex->null_preempt_param.cfg_coex_tx_qos_null_tid;
207         btcoex_null_preempt.cfg_coex_tx_peer_index = hmac_vap_btcoex->null_preempt_param.cfg_coex_tx_peer_index;
208 
209         frw_msg_init((osal_u8 *)&btcoex_null_preempt, sizeof(btcoex_null_preempt_stru), OSAL_NULL, 0, &msg_info);
210         ret = frw_send_msg_to_device(0, WLAN_MSG_H2D_C_CFG_SET_BTCOEX_ABORT_NULL, &msg_info, OSAL_TRUE);
211         if (ret != OAL_SUCC) {
212             oam_warning_log1(0, OAM_SF_CFG, "hmac_btcoex_init_preempt:send btcoex abort null to device fail[%d]", ret);
213         }
214     }
215 
216     /* 6. 配置芯片premmpt类型 */
217     hal_set_btcoex_tx_abort_preempt_type(hmac_vap_btcoex->all_abort_preempt_type);
218 }
219 
220 /*****************************************************************************
221  函 数 名  : hmac_btcoex_update_ps_frame_param
222  功能描述  : 更新ps相关参数
223 *****************************************************************************/
hmac_btcoex_update_ps_frame_param(hal_to_dmac_device_stru * hal_device,hal_chip_stru * hal_chip,mac_btcoex_ps_frame_info_stru * ps_param)224 static osal_void hmac_btcoex_update_ps_frame_param(hal_to_dmac_device_stru *hal_device,
225     hal_chip_stru *hal_chip, mac_btcoex_ps_frame_info_stru *ps_param)
226 {
227     unref_param(hal_chip);
228 
229     if (hal_device->btcoex_sw_preempt.coex_pri_forbit == OSAL_FALSE) {
230         ps_param->protect_coex_pri = hal_device->btcoex_sw_preempt.protect_coex_pri;
231     } else {
232         ps_param->protect_coex_pri = HAL_FCS_PROTECT_COEX_PRI_NORMAL;
233     }
234 
235     /* 这里等效fcs_service_type条件判断,这个变量耦合太多,建议删除 */
236     /* 非self-CTS duration参数也会统一设置但实际不会使用 */
237     if (hal_btcoex_btble_status()->bt_status.bt_status.bt_ldac == OSAL_TRUE) {
238         ps_param->duration = MAC_FCS_CTS_MAX_BTCOEX_LDAC_DURATION;
239         ps_param->timeout = MAC_FCS_DEFAULT_PROTECT_TIME_OUT;
240         ps_param->wait_timeout = MAC_ONE_PACKET_TIME_OUT;
241     } else {
242         ps_param->duration = MAC_FCS_CTS_MAX_BTCOEX_NOR_DURATION;
243         ps_param->timeout = MAC_FCS_DEFAULT_PROTECT_TIME_OUT3;
244         ps_param->wait_timeout = MAC_ONE_PACKET_TIME_OUT3;
245     }
246 }
247 
248 /*****************************************************************************
249  函 数 名  : hmac_btcoex_set_ps_flag
250  功能描述  : BTCOEX同步ps状态标志给device侧
251 *****************************************************************************/
hmac_btcoex_set_ps_flag(hal_to_dmac_device_stru * hal_device)252 osal_void hmac_btcoex_set_ps_flag(hal_to_dmac_device_stru *hal_device)
253 {
254     osal_s32 ret;
255     mac_btcoex_ps_flag_info_stru ps_flags = {0};
256     frw_msg msg = {0};
257 
258     if (hal_device == OSAL_NULL) {
259         return;
260     }
261 
262     if ((hal_device->btcoex_sw_preempt.ps_stop == OSAL_TRUE) ||
263         (hal_device->btcoex_sw_preempt.sw_preempt_mode.ps_on == OSAL_FALSE) ||
264         (hal_device->btcoex_sw_preempt.ps_pause == OSAL_TRUE)) {
265         ps_flags.one_pkt_en = OSAL_FALSE;
266     } else {
267         ps_flags.one_pkt_en = OSAL_TRUE;
268     }
269 
270     ps_flags.dis_abort = OSAL_TRUE;
271     ps_flags.reply_cts = hal_device->btcoex_sw_preempt.sw_preempt_mode.reply_cts;
272     ps_flags.rsp_frame_ps = hal_device->btcoex_sw_preempt.sw_preempt_mode.rsp_frame_ps;
273 
274     oam_info_log3(0, OAM_SF_COEX, "{hmac_btcoex_set_ps_flag:: enable=%d, cts=%d, rsp_ps=%d}",
275         ps_flags.one_pkt_en, ps_flags.reply_cts, ps_flags.rsp_frame_ps);
276 
277     frw_msg_init((osal_u8 *)&ps_flags, sizeof(ps_flags), OSAL_NULL, 0, &msg);
278     ret = frw_send_msg_to_device(0, WLAN_MSG_H2D_C_CFG_SET_BTCOEX_PS_FLAG, &msg, OSAL_TRUE);
279     if (ret != OAL_SUCC) {
280         oam_error_log1(0, OAM_SF_COEX, "{hmac_btcoex_set_ps_flag send msg fail, ret=%d}", ret);
281     }
282     return;
283 }
284 
285 /*****************************************************************************
286  函 数 名  : hmac_btcoex_et_vap_ps_frame
287  功能描述  : BTCOEX同步ps frame内容给device侧
288 *****************************************************************************/
hmac_btcoex_set_vap_ps_frame(hmac_vap_stru * hmac_vap,osal_u32 enable)289 osal_void hmac_btcoex_set_vap_ps_frame(hmac_vap_stru *hmac_vap, osal_u32 enable)
290 {
291     osal_s32 ret;
292     mac_btcoex_ps_frame_info_stru ps_frame = {0};
293     frw_msg msg = {0};
294     hal_one_packet_cfg_stru one_packet_cfg_tmp = {0};
295     hmac_user_stru *hmac_user = OSAL_NULL;
296     hal_chip_stru *hal_chip = hal_get_chip_stru();
297     hal_to_dmac_device_stru *hal_device = OSAL_NULL;
298 
299     unref_param(enable);
300     if ((hmac_vap == OSAL_NULL) || (hmac_vap->hal_vap == OSAL_NULL) ||
301         (hal_chip == OSAL_NULL) || (hmac_vap->hal_device == OSAL_NULL)) {
302         oam_error_log0(0, OAM_SF_COEX, "{hmac_btcoex_set_vap_ps_frame:: null pointer}");
303         return;
304     }
305 
306     hal_device = hmac_vap->hal_device;
307 
308     /* user_nums只能表示接入。最好判断设备已经接入并完成认证 */
309     ps_frame.is_vap_param = OAL_TRUE;
310     ps_frame.is_valid = OAL_TRUE;
311     if (!is_sta(hmac_vap) || (hmac_vap->user_nums == 0)) {
312         ps_frame.is_valid = OAL_FALSE;
313     }
314 
315     hmac_user = (hmac_user_stru *)mac_res_get_hmac_user_etc(hmac_vap->assoc_vap_id);
316     if (hmac_user == OSAL_NULL) {
317         ps_frame.is_valid = OAL_FALSE;
318     }
319 
320     if (ps_frame.is_valid == OAL_TRUE) {
321         ps_frame.protect_cnt     = mac_fcs_get_protect_cnt(hmac_vap);
322         ps_frame.cfg_one_pkt_tx_vap_index = hmac_vap->hal_vap->vap_id;
323         ps_frame.cfg_one_pkt_tx_peer_index = hmac_user->lut_index;
324 
325         /* data_rate和tx_mode信息最终方案需要由算法模块提供 */
326         ps_frame.tx_data_rate    = hmac_fcs_set_prot_datarate(hmac_vap);
327         one_packet_cfg_tmp.tx_data_rate = ps_frame.tx_data_rate;
328         ps_frame.tx_mode         = hmac_fcs_get_prot_mode(hmac_vap, &one_packet_cfg_tmp);
329 
330         if (hmac_btcoex_get_vap_info(hmac_vap)->ps_type == HAL_FCS_PROTECT_TYPE_SELF_CTS) {
331             ps_frame.protect_type = HAL_FCS_PROTECT_TYPE_SELF_CTS;
332         } else {
333             ps_frame.protect_type = HAL_FCS_PROTECT_TYPE_NULL_DATA;
334         }
335     }
336 
337     // device相关的ps frame参数
338     ps_frame.is_dev_param = OAL_TRUE;
339     hmac_btcoex_update_ps_frame_param(hal_device, hal_chip, &ps_frame);
340 
341     oam_info_log3(0, OAM_SF_COEX, "{hmac_btcoex_set_vap_ps_frame:: valid=%d, vap_id=%d, lut_index=%d}",
342         ps_frame.is_valid, ps_frame.cfg_one_pkt_tx_vap_index, ps_frame.cfg_one_pkt_tx_peer_index);
343 
344     frw_msg_init((osal_u8 *)&ps_frame, sizeof(ps_frame), OSAL_NULL, 0, &msg);
345     ret = frw_send_msg_to_device(hmac_vap->vap_id, WLAN_MSG_H2D_C_CFG_SET_BTCOEX_PS_FRAME, &msg, OSAL_TRUE);
346     if (ret != OAL_SUCC) {
347         oam_error_log1(0, OAM_SF_COEX, "{hmac_btcoex_set_vap_ps_frame send msg fail, ret=%d}", ret);
348     }
349 }
350 
351 /*****************************************************************************
352  函 数 名  : hmac_btcoex_set_dev_ps_frame
353  功能描述  : BTCOEX同步ps frame内容给device侧
354 *****************************************************************************/
hmac_btcoex_set_dev_ps_frame(hal_to_dmac_device_stru * hal_device)355 osal_void hmac_btcoex_set_dev_ps_frame(hal_to_dmac_device_stru *hal_device)
356 {
357     osal_s32 ret;
358     hal_chip_stru *hal_chip = hal_get_chip_stru();
359     mac_btcoex_ps_frame_info_stru ps_frame = {0};
360     frw_msg msg = {0};
361 
362     // device相关的ps frame参数
363     ps_frame.is_dev_param = OAL_TRUE;
364     hmac_btcoex_update_ps_frame_param(hal_device, hal_chip, &ps_frame);
365 
366     oam_info_log2(0, OAM_SF_COEX, "{hmac_btcoex_set_dev_ps_frame:: coex_pri=%d duration=%d}",
367         ps_frame.protect_coex_pri, ps_frame.duration);
368 
369     frw_msg_init((osal_u8 *)&ps_frame, sizeof(ps_frame), OSAL_NULL, 0, &msg);
370     ret = frw_send_msg_to_device(0, WLAN_MSG_H2D_C_CFG_SET_BTCOEX_PS_FRAME, &msg, OSAL_TRUE);
371     if (ret != OAL_SUCC) {
372         oam_error_log1(0, OAM_SF_COEX, "{hmac_btcoex_set_dev_ps_frame send msg fail, ret=%d}",
373             ret);
374     }
375 }
376 
377 /*****************************************************************************
378  函 数 名  : hmac_btcoex_switch_ps
379  功能描述  : BTCOEX通知device进行ps状态切换
380 *****************************************************************************/
hmac_btcoex_switch_ps(hal_to_dmac_device_stru * hal_device,hmac_btcoex_ps_switch_enum_uint8 status)381 OSAL_STATIC osal_void hmac_btcoex_switch_ps(hal_to_dmac_device_stru *hal_device,
382     hmac_btcoex_ps_switch_enum_uint8 status)
383 {
384     osal_s32 ret;
385     frw_msg msg = {0};
386 
387     unref_param(hal_device);
388     frw_msg_init((osal_u8 *)&status, sizeof(status), OSAL_NULL, 0, &msg);
389     ret = frw_send_msg_to_device(0, WLAN_MSG_H2D_C_CFG_BTCOEX_SIWTCH_PS, &msg, OSAL_TRUE);
390     if (ret != OAL_SUCC) {
391         oam_error_log2(0, OAM_SF_COEX, "{hmac_btcoex_switch_ps send msg fail, status=%u ret=%d}",
392             status, ret);
393     }
394 
395     return;
396 }
397 
398 /*****************************************************************************
399  函 数 名  : hmac_btcoex_preempt_sub_type_notify
400  功能描述  : 外部触发,切换sw preempt sub type
401 *****************************************************************************/
hmac_btcoex_set_sw_preempt_type(hal_to_dmac_device_stru * hal_device,hal_coex_sw_preempt_subtype_uint8 type)402 OSAL_STATIC osal_u32 hmac_btcoex_set_sw_preempt_type(hal_to_dmac_device_stru *hal_device,
403     hal_coex_sw_preempt_subtype_uint8 type)
404 {
405     hal_device->btcoex_sw_preempt.sw_preempt_type = type;
406 
407     if ((type == HAL_BTCOEX_SW_POWSAVE_SCAN_BEGIN) ||
408         (type == HAL_BTCOEX_SW_POWSAVE_SCAN_WAIT) ||
409         (type == HAL_BTCOEX_SW_POWSAVE_SCAN_ABORT) ||
410         (type == HAL_BTCOEX_SW_POWSAVE_SCAN_END)) {
411         /* 通知device侧ps状态被打断 */
412         hmac_btcoex_switch_ps(hal_device, HMAC_BTCOEX_PS_ABORT);
413     }
414 
415     return OSAL_SUCCESS;
416 }
417 
418 /*****************************************************************************
419  函 数 名  : hmac_btcoex_ps_timeout_update_time
420  功能描述  : ps机制更新timeout超时时间,音乐数传,page inquiry下超时时间配置需要不同
421 *****************************************************************************/
hmac_btcoex_ps_timeout_update_time(hal_to_dmac_device_stru * hal_device)422 osal_void hmac_btcoex_ps_timeout_update_time(hal_to_dmac_device_stru *hal_device)
423 {
424     hal_btcoex_ps_status_enum_uint8 ps_status = HAL_BTCOEX_PS_STATUE_BUTT;
425 
426     /* 获取当前ps业务状态 */
427     hal_btcoex_get_ps_service_status(hal_device, &ps_status);
428 
429     switch (ps_status) {
430         case HAL_BTCOEX_PS_STATUE_ACL:
431             hal_device->btcoex_sw_preempt.timeout_ms = BTCOEX_POWSAVE_TIMEOUT_LEVEL0;
432             break;
433 
434         case HAL_BTCOEX_PS_STATUE_LDAC:
435         case HAL_BTCOEX_PS_STATUE_LDAC_ACL:
436         case HAL_BTCOEX_PS_STATUE_PAGE_INQ:
437             hal_device->btcoex_sw_preempt.timeout_ms = BTCOEX_POWSAVE_TIMEOUT_LEVEL1;
438             break;
439 
440         case HAL_BTCOEX_PS_STATUE_PAGE_ACL:
441         case HAL_BTCOEX_PS_STATUE_LDAC_PAGE:
442         case HAL_BTCOEX_PS_STATUE_TRIPLE:
443             hal_device->btcoex_sw_preempt.timeout_ms = BTCOEX_POWSAVE_TIMEOUT_LEVEL2;
444             break;
445 
446         default:
447             oam_warning_log1(0, OAM_SF_COEX, "{hmac_btcoex_ps_timeout_update_time::ps_status[%d] error.}",
448                 ps_status);
449     }
450 }
451 
452 /*****************************************************************************
453  函 数 名  : hmac_btcoex_ps_stop_check_and_notify
454  功能描述  : 获取ps是否禁止标记
455              (1)dbac启动和停止 (2)单ap模式 (3)sco电话启动和结束 (4)5G工作
456              其中单ap模式,5g工作逻辑在关联和去关联时候也要单独判断
457 *****************************************************************************/
hmac_btcoex_ps_stop_check_and_notify(hal_to_dmac_device_stru * hal_device)458 osal_void hmac_btcoex_ps_stop_check_and_notify(hal_to_dmac_device_stru *hal_device)
459 {
460     hmac_device_stru *hmac_device = hmac_res_get_mac_dev_etc(0);
461     hmac_vap_stru *hmac_vap = OSAL_NULL;
462     oal_bool_enum_uint8 sco_status = OSAL_FALSE;
463     oal_bool_enum_uint8 ps_stop = OSAL_FALSE; /* 初始是打开ps */
464     osal_u8 vap_idx, up_vap_num, up_ap_num, up_sta_num, up_2g_num, up_5g_num;
465     osal_u8             mac_vap_id[WLAN_SERVICE_VAP_MAX_NUM_PER_DEVICE] = {0};
466 
467     up_ap_num = up_sta_num = up_2g_num = up_5g_num = 0;
468 
469     if (hal_device == OSAL_NULL) {
470         oam_warning_log0(0, OAM_SF_COEX, "{hmac_btcoex_ps_stop_check_and_notify: hal_device is null ptr.}");
471         return;
472     }
473 
474     /* 1.电话场景 */
475     hal_btcoex_get_bt_sco_status(hal_device, &sco_status);
476     if ((sco_status == OSAL_TRUE) || (mac_is_dbac_running(hmac_device) == OSAL_TRUE)) {
477         ps_stop = OSAL_TRUE;
478     }
479 
480     /* Hal Device处于work状态vap个数 */
481     up_vap_num = hal_device_find_all_up_vap(hal_device, mac_vap_id, WLAN_SERVICE_VAP_MAX_NUM_PER_DEVICE);
482     for (vap_idx = 0; vap_idx < up_vap_num; vap_idx++) {
483         hmac_vap = (hmac_vap_stru *)mac_res_get_hmac_vap(mac_vap_id[vap_idx]);
484         if (hmac_vap == OSAL_NULL) {
485             continue;
486         }
487 
488         /* 关联用户数不为0 */
489         if (hmac_vap->user_nums != 0) {
490             (is_ap(hmac_vap)) ? (up_ap_num++) : (up_sta_num++);
491             (mac_btcoex_check_valid_vap(hmac_vap) == OSAL_TRUE) ? (up_2g_num++) : (up_5g_num++);
492         }
493     }
494 
495     /* 3.单ap模式 4.5g模式 5.siso c1 */
496     if ((up_ap_num != 0 && up_sta_num == 0) || (up_5g_num != 0 && up_2g_num == 0) ||
497         ((hal_device->cfg_cap_info->phy_chain == WLAN_PHY_CHAIN_ONE) &&
498         (hal_device->hal_m2s_fsm.oal_fsm.cur_state == HAL_M2S_STATE_SISO))) {
499         ps_stop = OSAL_TRUE;
500     }
501 
502     /* 刷新ps能力 */
503     hal_device->btcoex_sw_preempt.ps_stop = ps_stop;
504     hmac_btcoex_set_ps_flag(hal_device);
505 
506     hal_set_btcoex_wifi_status_notify(HAL_BTCOEX_WIFI_STATE_PS_STOP, (osal_u32)ps_stop);
507 
508     hal_coex_sw_irq_set(HAL_COEX_SW_IRQ_BT);
509 
510     oam_warning_log_alter(0, OAM_SF_COEX,
511         "{hmac_btcoex_ps_stop_check_and_notify::ap[%d]sta[%d]5g[%d]2g[%d]sco[%d]dbac[%d]chain[%d]m2s[%d] ps_stop[%d]!}",
512         /* 9代表9后面有9个待打印参数 */
513         9, up_ap_num, up_sta_num, up_5g_num, up_2g_num, sco_status,
514         mac_is_dbac_running(hmac_device), hal_device->cfg_cap_info->phy_chain,
515         hal_device->hal_m2s_fsm.oal_fsm.cur_state,
516         hal_device->btcoex_sw_preempt.ps_stop);
517 }
518 
519 /*****************************************************************************
520  函 数 名  : hmac_btcoex_ps_pause_check_and_notify
521  功能描述  : 获取ps是否暂停标记,单wifi侧
522              (1)漫游过程中需要暂停
523 *****************************************************************************/
hmac_btcoex_ps_pause_check_and_notify(osal_void * notify_data)524 OSAL_STATIC osal_bool hmac_btcoex_ps_pause_check_and_notify(osal_void *notify_data)
525 {
526     hmac_vap_stru *hmac_vap = OSAL_NULL;
527     oal_bool_enum_uint8 ps_pause = OSAL_FALSE; /* 初始是不暂停ps */
528     hal_to_dmac_device_stru *hal_device = ((hmac_vap_stru *)notify_data)->hal_device;
529     osal_u8 vap_idx;
530     osal_u8 up_vap_num;
531     osal_u8 mac_vap_id[WLAN_SERVICE_VAP_MAX_NUM_PER_DEVICE] = {0};
532 
533     /* Hal Device处于work状态vap个数 */
534     up_vap_num = hal_device_find_all_up_vap(hal_device, mac_vap_id, WLAN_SERVICE_VAP_MAX_NUM_PER_DEVICE);
535     for (vap_idx = 0; vap_idx < up_vap_num; vap_idx++) {
536         hmac_vap = (hmac_vap_stru *)mac_res_get_hmac_vap(mac_vap_id[vap_idx]);
537         if (hmac_vap == OSAL_NULL) {
538             continue;
539         }
540 
541         /* 1.处于漫游过程中需要暂停ps */
542         if (hmac_vap->vap_state == MAC_VAP_STATE_ROAMING) {
543             ps_pause = OSAL_TRUE;
544         }
545     }
546 
547     /* 刷新ps能力 */
548     hal_device->btcoex_sw_preempt.ps_pause = ps_pause;
549     hmac_btcoex_set_ps_flag(hal_device);
550 
551     oam_warning_log2(0, OAM_SF_COEX,
552         "{hmac_btcoex_ps_pause_check_and_notify::ps_pause[%d]up_vap_num[%d]!}",
553         hal_device->btcoex_sw_preempt.ps_pause, up_vap_num);
554     return OSAL_TRUE;
555 }
556 
hmac_btcoex_pow_save_scan_state(hmac_device_stru * hmac_device,hal_to_dmac_device_stru * h2d_device)557 OSAL_STATIC osal_void hmac_btcoex_pow_save_scan_state(hmac_device_stru *hmac_device,
558     hal_to_dmac_device_stru *h2d_device)
559 {
560     switch (h2d_device->btcoex_sw_preempt.sw_preempt_type) {
561         case HAL_BTCOEX_SW_POWSAVE_SCAN_BEGIN:
562             /* 如果扫描一开始被ps打断,此时ps来恢复继续扫描 */
563             hmac_scan_begin(hmac_device, h2d_device);
564             break;
565 
566         case HAL_BTCOEX_SW_POWSAVE_SCAN_WAIT:
567             /* 如果扫描临时回home channel继续工作被打断,此时ps来恢复继续回home channel工作 */
568             hmac_scan_switch_home_channel_work(hmac_device, h2d_device);
569             oam_warning_log0(0, OAM_SF_COEX,
570                 "{hmac_btcoex_pow_save_scan_state::hmac_scan_switch_home_channel_work start.}");
571             break;
572 
573         case HAL_BTCOEX_SW_POWSAVE_SCAN_END:
574             /* 如果扫描结束被打断,此时ps来恢复继续扫描 */
575             oam_warning_log0(0, OAM_SF_COEX,
576                 "{hmac_btcoex_pow_save_scan_state::hmac_scan_handle_switch_channel_back start.}");
577             hmac_scan_prepare_end(hmac_device, h2d_device);
578             break;
579 
580         case HAL_BTCOEX_SW_POWSAVE_SCAN_ABORT:
581             /* abort状态一定是,在save状态时候scan baort,类似于ps=0要恢复ps=1的配置,因为scan
582              * abort提前resume了,此处不需要处理  */
583             oam_warning_log0(0, OAM_SF_COEX, "{hmac_btcoex_pow_save_scan_state::scan is already abort and resume.}");
584             break;
585 
586         case HAL_BTCOEX_SW_POWSAVE_IDLE:
587             /* 可能是状态1事件没有及时处理下半部,又来了状态0,此时处于扫描,恢复交给扫描来做即可 */
588             oam_warning_log0(0, OAM_SF_COEX, "{hmac_btcoex_pow_save_scan_state::HAL_BTCOEX_SW_POWSAVE_IDLE.}");
589             break;
590 
591         case HAL_BTCOEX_SW_POWSAVE_WORK:
592             /* 如果扫描期间来了1又来了0,此时恢复交给扫描自己恢复,ps=0不做处理 */
593             break;
594 
595         default:
596             oam_warning_log1(0, OAM_SF_COEX, "{hmac_btcoex_pow_save_scan_state::sw_preempt_type[%d] error.}",
597                 h2d_device->btcoex_sw_preempt.sw_preempt_type);
598     }
599 
600     return;
601 }
602 
hmac_btcoex_pow_save_other_state(hal_to_dmac_device_stru * h2d_device)603 OSAL_STATIC osal_void hmac_btcoex_pow_save_other_state(hal_to_dmac_device_stru *h2d_device)
604 {
605     switch (h2d_device->btcoex_sw_preempt.sw_preempt_type) {
606         case HAL_BTCOEX_SW_POWSAVE_PSM_END:
607             /* 先执行了低功耗恢复,不要做操作 */
608             oam_warning_log0(0, OAM_SF_COEX, "{hmac_btcoex_pow_save_other_state:: powerdown already resume.}");
609             break;
610 
611         case HAL_BTCOEX_SW_POWSAVE_IDLE:
612             /* 可能是低功耗ps=1事件才开始执行,此时读取寄存器状态=0,当前是0状态,就按照0来处理即可,
613              * 会连续来两个0的事件处理
614              */
615             oam_warning_log0(0, OAM_SF_COEX, "{hmac_btcoex_pow_save_other_state:: current is normal!.}");
616             break;
617 
618         case HAL_BTCOEX_SW_POWSAVE_SCAN_ABORT:
619             /* 强制scan abort恢复了,此处不需要恢复 */
620             oam_warning_log0(0, OAM_SF_COEX,
621                 "{hmac_btcoex_pow_save_other_state:: work state scan abort already resume.}");
622             break;
623 
624         case HAL_BTCOEX_SW_POWSAVE_WORK:
625             /* 恢复发送和接收 */
626             if (h2d_device->btcoex_sw_preempt.sw_preempt_subtype == HAL_BTCOEX_SW_POWSAVE_SUB_IDLE) {
627                 h2d_device->btcoex_sw_preempt.sw_preempt_subtype = HAL_BTCOEX_SW_POWSAVE_SUB_ACTIVE;
628                 oam_warning_log0(0, OAM_SF_COEX,
629                     "{hmac_btcoex_pow_save_other_state:: work HAL_BTCOEX_SW_POWSAVE_SUB_IDLE.}");
630             } else if (h2d_device->btcoex_sw_preempt.sw_preempt_subtype == HAL_BTCOEX_SW_POWSAVE_SUB_SCAN) {
631                 h2d_device->btcoex_sw_preempt.sw_preempt_subtype = HAL_BTCOEX_SW_POWSAVE_SUB_ACTIVE;
632                 oam_warning_log0(0, OAM_SF_COEX,
633                     "{hmac_btcoex_pow_save_other_state:: work HAL_BTCOEX_SW_POWSAVE_SUB_SCAN.}");
634             }
635             break;
636 
637         default:
638             oam_warning_log1(0, OAM_SF_COEX, "{hmac_btcoex_pow_save_other_state::sw_preempt_type[%d] error.}",
639                 h2d_device->btcoex_sw_preempt.sw_preempt_type);
640     }
641 
642     return;
643 }
644 
645 /*****************************************************************************
646  函 数 名  : hmac_btcoex_pow_save_callback
647  功能描述  : 软件preempt机制下恢复节能定时处理函数
648 *****************************************************************************/
hmac_btcoex_pow_save_callback(osal_void * arg)649 osal_u32 hmac_btcoex_pow_save_callback(osal_void *arg)
650 {
651     hal_to_dmac_device_stru *h2d_device = (hal_to_dmac_device_stru *)arg;
652     hmac_device_stru *hmac_device = hmac_res_get_mac_dev_etc(0);
653 
654     if (h2d_device == OSAL_NULL) {
655         oam_warning_log0(0, OAM_SF_COEX, "{hmac_btcoex_pow_save_callback::h2d_device is null.}");
656         return OAL_FAIL;
657     }
658     /* 在scan状态时候,扫描不进入低功耗,此时不用担心低功耗,如果扫描来时 */
659     if (h2d_device->hal_dev_fsm.oal_fsm.cur_state == HAL_DEVICE_SCAN_STATE) {
660         hmac_btcoex_pow_save_scan_state(hmac_device, h2d_device);
661     } else {
662         hmac_btcoex_pow_save_other_state(h2d_device);
663     }
664     hmac_btcoex_switch_ps(h2d_device, HMAC_BTCOEX_PS_TIMOUT); /* 通知device侧处理ps超时 */
665     /* preempt机制置为NONE形式 */
666     h2d_device->btcoex_sw_preempt.sw_preempt_type = HAL_BTCOEX_SW_POWSAVE_TIMEOUT;
667     h2d_device->btcoex_sw_preempt.ps_timeout_cnt++;
668 
669     oam_warning_log0(0, OAM_SF_COEX, "{hmac_btcoex_pow_save_callback::time is up.}");
670 
671     return OAL_SUCC;
672 }
673 
hmac_btcoex_ps_on_proc(hmac_device_stru * hmac_device,hal_to_dmac_device_stru * h2d_device,hal_chip_stru * hal_chip)674 osal_void hmac_btcoex_ps_on_proc(hmac_device_stru *hmac_device,
675     hal_to_dmac_device_stru *h2d_device, hal_chip_stru *hal_chip)
676 {
677     unref_param(hmac_device);
678     unref_param(hal_chip);
679 
680     /* preempt机制置为软件形式 */
681     h2d_device->btcoex_sw_preempt.sw_preempt_type = HAL_BTCOEX_SW_POWSAVE_WORK;
682 
683     /* 在scan状态时候 */
684     if (h2d_device->hal_dev_fsm.oal_fsm.cur_state == HAL_DEVICE_SCAN_STATE) {
685         /* 在扫描执行过程中,不需要处理,扫描时对端已经处于节能状态并在tx
686          pause状态,扫描结束时需要考虑是不是由ps来恢复,低功耗是200ms,
687          即使扫描由ps来恢复,也来得及,ps等于0肯定在低功耗前来到或者恢复之后,不会被低功耗打断
688         */
689         h2d_device->btcoex_sw_preempt.sw_preempt_subtype = HAL_BTCOEX_SW_POWSAVE_SUB_SCAN;
690     } else {
691         /* sta模式可能一开始还没关联上,处于非up状态,后续启动成up状态,ps=0时候恢复不生效,
692          * 直接判断不处理即可,如果处于低功耗状态(主要是work状态下的awake子状态,
693          * 收到ps中断, 仍然对端在睡眠状态),wifi不需要特殊处理,执行pause不需要发ps帧,
694          * 等低功耗自己来处理ps状态.sta vap进行发送pause,并通知对端缓存数据暂停发送数据,
695          * 处于idle状态,空发一帧也没关系 */
696         /* 1.先默认为active状态,能保证低功耗饿死时,中断ps=1也能唤醒 */
697         h2d_device->btcoex_sw_preempt.sw_preempt_subtype = HAL_BTCOEX_SW_POWSAVE_SUB_ACTIVE;
698     }
699 
700     /* 状态变迁,启动定时器完成ps操作,防止扫描置状态之后,出现wifi不醒来 */
701     if (h2d_device->btcoex_powersave_timer.is_registerd == OSAL_TRUE) {
702         frw_destroy_timer_entry(&(h2d_device->btcoex_powersave_timer));
703     }
704 
705     /* ps机制启动时,需要根据当前状态,刷新超时定时器时间 */
706     hmac_btcoex_ps_timeout_update_time(h2d_device);
707     frw_create_timer_entry(&(h2d_device->btcoex_powersave_timer), hmac_btcoex_pow_save_callback,
708         h2d_device->btcoex_sw_preempt.timeout_ms, (osal_void *)h2d_device, OSAL_FALSE);
709 }
710 
hmac_btcoex_ps_off_scan_state_proc(hmac_device_stru * hmac_device,hal_to_dmac_device_stru * h2d_device)711 osal_void hmac_btcoex_ps_off_scan_state_proc(hmac_device_stru *hmac_device, hal_to_dmac_device_stru *h2d_device)
712 {
713     switch (h2d_device->btcoex_sw_preempt.sw_preempt_type) {
714         case HAL_BTCOEX_SW_POWSAVE_SCAN_BEGIN:
715             /* 如果扫描一开始被ps打断,此时ps来恢复继续扫描 */
716             hmac_scan_begin(hmac_device, h2d_device);
717             break;
718 
719         case HAL_BTCOEX_SW_POWSAVE_SCAN_WAIT:
720             /* 如果扫描临时回home channel继续工作被打断,此时ps来恢复继续回home channel工作 */
721             hmac_scan_switch_home_channel_work(hmac_device, h2d_device);
722             oam_warning_log0(0, OAM_SF_COEX,
723                 "{hmac_btcoex_ps_off_scan_state_proc::hmac_scan_switch_home_channel_work start.}");
724             break;
725 
726         case HAL_BTCOEX_SW_POWSAVE_SCAN_END:
727             /* 如果扫描结束被打断,此时ps来恢复继续扫描 */
728             oam_warning_log0(0, OAM_SF_COEX,
729                 "{hmac_btcoex_ps_off_scan_state_proc::hmac_scan_handle_switch_channel_back start.}");
730             hmac_scan_prepare_end(hmac_device, h2d_device);
731             break;
732 
733         case HAL_BTCOEX_SW_POWSAVE_SCAN_ABORT:
734             /* abort状态一定是,在save状态时候scan baort,类似于ps=0要恢复ps=1的配置,因为scan
735              * abort提前resume了,此处不需要处理  */
736             oam_warning_log0(0, OAM_SF_COEX,
737                 "{hmac_btcoex_ps_off_scan_state_proc::scan is already abort and resume.}");
738 
739             /* abort已经强制置为恢复,此次不保护,vap已经vap了不需要做操作 */
740             /* 恢复发送和接收 */
741             break;
742 
743         case HAL_BTCOEX_SW_POWSAVE_IDLE:
744             /* 可能是状态1事件没有及时处理下半部,又来了状态0,此时处于扫描,恢复交给扫描来做即可 */
745             oam_warning_log0(0, OAM_SF_COEX,
746                 "{hmac_btcoex_ps_off_scan_state_proc::HAL_BTCOEX_SW_POWSAVE_IDLE.}");
747             break;
748 
749         case HAL_BTCOEX_SW_POWSAVE_WORK:
750             /* 如果扫描期间来了1又来了0,此时恢复交给扫描自己恢复,ps=0不做处理 */
751             break;
752 
753         case HAL_BTCOEX_SW_POWSAVE_TIMEOUT:
754             /* time is up, 或者低功耗已经提前恢复,属于正常 */
755             break;
756 
757         default:
758             oam_warning_log1(0, OAM_SF_COEX, "{hmac_btcoex_ps_off_scan_state_proc::sw_preempt_type[%d] error.}",
759                 h2d_device->btcoex_sw_preempt.sw_preempt_type);
760     }
761 }
762 
hmac_btcoex_ps_off_no_scan_state_proc(hal_to_dmac_device_stru * h2d_device)763 osal_void hmac_btcoex_ps_off_no_scan_state_proc(hal_to_dmac_device_stru *h2d_device)
764 {
765     switch (h2d_device->btcoex_sw_preempt.sw_preempt_type) {
766         case HAL_BTCOEX_SW_POWSAVE_PSM_END:
767             /* 先执行了低功耗恢复,不要做操作 */
768             oam_warning_log0(0, OAM_SF_COEX,
769                 "{hmac_btcoex_ps_off_no_scan_state_proc:: powerdown has already resume.}");
770             break;
771 
772         case HAL_BTCOEX_SW_POWSAVE_IDLE:
773             /* 可能是低功耗ps=1事件才开始执行,此时读取寄存器状态=0,
774                当前是0状态,就按照0来处理即可,会连续来两个0的事件处理 */
775             oam_warning_log0(0, OAM_SF_COEX, "{hmac_btcoex_ps_off_no_scan_state_proc:: current is normal!.}");
776             break;
777 
778         case HAL_BTCOEX_SW_POWSAVE_SCAN_ABORT:
779             /* 强制scan abort恢复了,此处不需要恢复 */
780             oam_warning_log0(0, OAM_SF_COEX,
781                 "{hmac_btcoex_ps_off_no_scan_state_proc:: work state scan abort already resume.}");
782             break;
783 
784         case HAL_BTCOEX_SW_POWSAVE_WORK:
785             /* 恢复发送和接收 */
786             if (h2d_device->btcoex_sw_preempt.sw_preempt_subtype == HAL_BTCOEX_SW_POWSAVE_SUB_IDLE) {
787                 h2d_device->btcoex_sw_preempt.sw_preempt_subtype = HAL_BTCOEX_SW_POWSAVE_SUB_ACTIVE;
788                 oam_warning_log0(0, OAM_SF_COEX,
789                     "{hmac_btcoex_ps_off_no_scan_state_proc:: work HAL_BTCOEX_SW_POWSAVE_SUB_IDLE.}");
790             } else if (h2d_device->btcoex_sw_preempt.sw_preempt_subtype == HAL_BTCOEX_SW_POWSAVE_SUB_SCAN) {
791                 h2d_device->btcoex_sw_preempt.sw_preempt_subtype = HAL_BTCOEX_SW_POWSAVE_SUB_ACTIVE;
792                 oam_warning_log0(0, OAM_SF_COEX,
793                     "{hmac_btcoex_ps_off_no_scan_state_proc:: work HAL_BTCOEX_SW_POWSAVE_SUB_SCAN.}");
794             }
795             break;
796 
797         case HAL_BTCOEX_SW_POWSAVE_TIMEOUT:
798             /* time is up, 或者低功耗已经提前恢复,属于正常 */
799             break;
800 
801         default:
802             oam_warning_log1(0, OAM_SF_COEX,
803                 "{hmac_btcoex_ps_off_no_scan_state_proc::sw_preempt_type[%d] error.}",
804                 h2d_device->btcoex_sw_preempt.sw_preempt_type);
805     }
806 }
807 
808 /*****************************************************************************
809  函 数 名  : hmac_btcoex_one_pkt_type_and_duration_update
810  功能描述  : one pkt帧类型刷新,兼容性设备只能识别self-cts帧
811 *****************************************************************************/
hmac_btcoex_one_pkt_type_and_duration_update(const mac_fcs_mgr_stru * fcs_mgr,hal_one_packet_cfg_stru * one_packet_cfg,hmac_vap_stru * hmac_vap)812 OSAL_STATIC osal_void hmac_btcoex_one_pkt_type_and_duration_update(const mac_fcs_mgr_stru *fcs_mgr,
813     hal_one_packet_cfg_stru *one_packet_cfg, hmac_vap_stru *hmac_vap)
814 {
815     /* 针对sta模式下才刷新帧类型 */
816     if (!is_sta(hmac_vap)) {
817         return;
818     }
819 
820     /* 如果是非null帧类型,也即是self-cts类型,需要刷新duration */
821     if (hmac_btcoex_get_vap_info(hmac_vap)->ps_type == HAL_FCS_PROTECT_TYPE_SELF_CTS) {
822         /* 刷新帧类型和duration时间 */
823         one_packet_cfg->protect_type = HAL_FCS_PROTECT_TYPE_SELF_CTS;
824 
825         if (fcs_mgr->fcs_service_type == HAL_FCS_SERVICE_TYPE_BTCOEX_LDAC) {
826             one_packet_cfg->duration = MAC_FCS_CTS_MAX_BTCOEX_LDAC_DURATION;
827         } else {
828             one_packet_cfg->duration = MAC_FCS_CTS_MAX_BTCOEX_NOR_DURATION;
829         }
830     }
831 }
832 
hmac_btcoex_ps_init(osal_void)833 osal_u32 hmac_btcoex_ps_init(osal_void)
834 {
835     /* notify注册 */
836     frw_util_notifier_register_with_priority(WLAN_UTIL_NOTIFIER_EVENT_ROAM_ACTIVE,
837         hmac_btcoex_ps_pause_check_and_notify, WLAN_UTIL_NOTIFIER_PRIORITY_MAX);
838     frw_util_notifier_register_with_priority(WLAN_UTIL_NOTIFIER_EVENT_ROAM_DEACTIVE,
839         hmac_btcoex_ps_pause_check_and_notify, WLAN_UTIL_NOTIFIER_PRIORITY_MAX);
840     /* 对外接口注册 */
841     hmac_feature_hook_register(HMAC_FHOOK_BTCOEX_PS_SET_SW_PREEMPT_TYPE, hmac_btcoex_set_sw_preempt_type);
842     hmac_feature_hook_register(HMAC_FHOOK_BTCOEX_PS_ONE_PKT_TYPE_UPDATE, hmac_btcoex_one_pkt_type_and_duration_update);
843     hmac_feature_hook_register(HMAC_FHOOK_BTCOEX_PS_STOP_CHECK, hmac_btcoex_ps_stop_check_and_notify);
844     return OAL_SUCC;
845 }
846 
hmac_btcoex_ps_deinit(osal_void)847 osal_void hmac_btcoex_ps_deinit(osal_void)
848 {
849     /* notify去注册 */
850     frw_util_notifier_unregister_with_priority(WLAN_UTIL_NOTIFIER_EVENT_ROAM_ACTIVE,
851         hmac_btcoex_ps_pause_check_and_notify, WLAN_UTIL_NOTIFIER_PRIORITY_MAX);
852     frw_util_notifier_unregister_with_priority(WLAN_UTIL_NOTIFIER_EVENT_ROAM_DEACTIVE,
853         hmac_btcoex_ps_pause_check_and_notify, WLAN_UTIL_NOTIFIER_PRIORITY_MAX);
854     /* 对外接口去注册 */
855     hmac_feature_hook_unregister(HMAC_FHOOK_BTCOEX_PS_SET_SW_PREEMPT_TYPE);
856     hmac_feature_hook_unregister(HMAC_FHOOK_BTCOEX_PS_ONE_PKT_TYPE_UPDATE);
857     hmac_feature_hook_unregister(HMAC_FHOOK_BTCOEX_PS_STOP_CHECK);
858     return;
859 }
860 
861 #ifdef __cplusplus
862 #if __cplusplus
863 }
864 #endif
865 #endif
866 
867 #endif
868