1 /******************************************************************************
\r
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
\r
5 * This program is free software; you can redistribute it and/or modify it
\r
6 * under the terms of version 2 of the GNU General Public License as
\r
7 * published by the Free Software Foundation.
\r
9 * This program is distributed in the hope that it will be useful, but WITHOUT
\r
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
14 * You should have received a copy of the GNU General Public License along with
\r
15 * this program; if not, write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
\r
19 ******************************************************************************/
\r
22 #include <drv_types.h>
\r
25 #ifdef CONFIG_AP_MODE
\r
27 extern unsigned char RTW_WPA_OUI[];
\r
28 extern unsigned char WMM_OUI[];
\r
29 extern unsigned char WPS_OUI[];
\r
30 extern unsigned char P2P_OUI[];
\r
31 extern unsigned char WFD_OUI[];
\r
33 void init_mlme_ap_info(_adapter *padapter)
\r
35 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
36 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
37 struct sta_priv *pstapriv = &padapter->stapriv;
\r
38 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
\r
41 _rtw_spinlock_init(&pmlmepriv->bcn_update_lock);
\r
44 _rtw_init_queue(&pacl_list->acl_node_q);
\r
46 //pmlmeext->bstart_bss = _FALSE;
\r
48 start_ap_mode(padapter);
\r
51 void free_mlme_ap_info(_adapter *padapter)
\r
54 struct sta_info *psta=NULL;
\r
55 struct sta_priv *pstapriv = &padapter->stapriv;
\r
56 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
57 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
58 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
60 //stop_ap_mode(padapter);
\r
62 pmlmepriv->update_bcn = _FALSE;
\r
63 pmlmeext->bstart_bss = _FALSE;
\r
65 rtw_sta_flush(padapter);
\r
67 pmlmeinfo->state = _HW_STATE_NOLINK_;
\r
69 //free_assoc_sta_resources
\r
70 rtw_free_all_stainfo(padapter);
\r
72 //free bc/mc sta_info
\r
73 psta = rtw_get_bcmc_stainfo(padapter);
\r
74 _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
75 rtw_free_stainfo(padapter, psta);
\r
76 _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
79 _rtw_spinlock_free(&pmlmepriv->bcn_update_lock);
\r
83 static void update_BCNTIM(_adapter *padapter)
\r
85 struct sta_priv *pstapriv = &padapter->stapriv;
\r
86 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
87 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
88 WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
\r
89 unsigned char *pie = pnetwork_mlmeext->IEs;
\r
91 //DBG_871X("%s\n", __FUNCTION__);
\r
94 //if(pstapriv->tim_bitmap)
\r
97 u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
\r
99 uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;
\r
101 tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
\r
103 p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
\r
104 if (p != NULL && tim_ielen>0)
\r
108 premainder_ie = p+tim_ielen;
\r
110 tim_ie_offset = (sint)(p -pie);
\r
112 remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
\r
114 //append TIM IE from dst_ie offset
\r
121 //calucate head_len
\r
122 offset = _FIXED_IE_LENGTH_;
\r
124 /* get ssid_ie len */
\r
125 p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
\r
127 offset += tmp_len+2;
\r
129 // get supported rates len
\r
130 p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
\r
133 offset += tmp_len+2;
\r
136 //DS Parameter Set IE, len=3
\r
139 premainder_ie = pie + offset;
\r
141 remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;
\r
143 //append TIM IE from offset
\r
144 dst_ie = pie + offset;
\r
149 if(remainder_ielen>0)
\r
151 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
\r
152 if(pbackup_remainder_ie && premainder_ie)
\r
153 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
\r
156 *dst_ie++=_TIM_IE_;
\r
158 if((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fe))
\r
163 *dst_ie++= tim_ielen;
\r
165 *dst_ie++=0;//DTIM count
\r
166 *dst_ie++=1;//DTIM peroid
\r
168 if(pstapriv->tim_bitmap&BIT(0))//for bc/mc frames
\r
169 *dst_ie++ = BIT(0);//bitmap ctrl
\r
177 if(pstapriv->tim_bitmap&0x00fe)
\r
178 pvb = (u8)tim_bitmap_le;
\r
179 else if(pstapriv->tim_bitmap&0xff00)
\r
180 pvb = (u8)(tim_bitmap_le>>8);
\r
182 pvb = (u8)tim_bitmap_le;
\r
187 else if(tim_ielen==5)
\r
189 _rtw_memcpy(dst_ie, &tim_bitmap_le, 2);
\r
193 //copy remainder IE
\r
194 if(pbackup_remainder_ie)
\r
196 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
\r
198 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
\r
201 offset = (uint)(dst_ie - pie);
\r
202 pnetwork_mlmeext->IELength = offset + remainder_ielen;
\r
207 void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)
\r
209 PNDIS_802_11_VARIABLE_IEs pIE;
\r
210 u8 bmatch = _FALSE;
\r
211 u8 *pie = pnetwork->IEs;
\r
212 u8 *p=NULL, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
\r
213 u32 i, offset, ielen, ie_offset, remainder_ielen = 0;
\r
215 for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;)
\r
217 pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
\r
219 if (pIE->ElementID > index)
\r
223 else if(pIE->ElementID == index) // already exist the same IE
\r
226 ielen = pIE->Length;
\r
232 ielen = pIE->Length;
\r
233 i += (pIE->Length + 2);
\r
236 if (p != NULL && ielen>0)
\r
240 premainder_ie = p+ielen;
\r
242 ie_offset = (sint)(p -pie);
\r
244 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
\r
249 dst_ie = (p+ielen);
\r
255 if(remainder_ielen>0)
\r
257 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
\r
258 if(pbackup_remainder_ie && premainder_ie)
\r
259 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
\r
265 _rtw_memcpy(dst_ie, data, len);
\r
268 //copy remainder IE
\r
269 if(pbackup_remainder_ie)
\r
271 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
\r
273 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
\r
276 offset = (uint)(dst_ie - pie);
\r
277 pnetwork->IELength = offset + remainder_ielen;
\r
280 void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)
\r
282 u8 *p, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
\r
283 uint offset, ielen, ie_offset, remainder_ielen = 0;
\r
284 u8 *pie = pnetwork->IEs;
\r
286 p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);
\r
287 if (p != NULL && ielen>0)
\r
291 premainder_ie = p+ielen;
\r
293 ie_offset = (sint)(p -pie);
\r
295 remainder_ielen = pnetwork->IELength - ie_offset - ielen;
\r
303 if(remainder_ielen>0)
\r
305 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
\r
306 if(pbackup_remainder_ie && premainder_ie)
\r
307 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
\r
310 //copy remainder IE
\r
311 if(pbackup_remainder_ie)
\r
313 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
\r
315 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
\r
318 offset = (uint)(dst_ie - pie);
\r
319 pnetwork->IELength = offset + remainder_ielen;
\r
323 u8 chk_sta_is_alive(struct sta_info *psta);
\r
324 u8 chk_sta_is_alive(struct sta_info *psta)
\r
327 #ifdef DBG_EXPIRATION_CHK
\r
328 DBG_871X("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"
\r
329 , MAC_ARG(psta->hwaddr)
\r
330 , psta->rssi_stat.UndecoratedSmoothedPWDB
\r
331 //, STA_RX_PKTS_ARG(psta)
\r
332 , STA_RX_PKTS_DIFF_ARG(psta)
\r
334 , psta->state&WIFI_SLEEP_STATE?"PS, ":""
\r
335 , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":""
\r
340 //if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta))
\r
341 if((psta->sta_stats.last_rx_data_pkts + psta->sta_stats.last_rx_ctrl_pkts) == (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts))
\r
344 if(psta->state&WIFI_SLEEP_STATE)
\r
353 sta_update_last_rx_pkts(psta);
\r
358 void expire_timeout_chk(_adapter *padapter)
\r
361 _list *phead, *plist;
\r
362 u8 updated = _FALSE;
\r
363 struct sta_info *psta=NULL;
\r
364 struct sta_priv *pstapriv = &padapter->stapriv;
\r
365 u8 chk_alive_num = 0;
\r
366 char chk_alive_list[NUM_STA];
\r
370 _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
\r
372 phead = &pstapriv->auth_list;
\r
373 plist = get_next(phead);
\r
376 #ifdef DBG_EXPIRATION_CHK
\r
377 if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
\r
378 DBG_871X(FUNC_NDEV_FMT" auth_list, cnt:%u\n"
\r
379 , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt);
\r
382 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
\r
384 psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);
\r
386 plist = get_next(plist);
\r
389 #ifdef CONFIG_ATMEL_RC_PATCH
\r
390 if (_TRUE == _rtw_memcmp((void *)(pstapriv->atmel_rc_pattern), (void *)(psta->hwaddr), ETH_ALEN))
\r
392 if (psta->flag_atmel_rc)
\r
395 if(psta->expire_to>0)
\r
398 if (psta->expire_to == 0)
\r
400 rtw_list_delete(&psta->auth_list);
\r
401 pstapriv->auth_list_cnt--;
\r
403 DBG_871X("auth expire %02X%02X%02X%02X%02X%02X\n",
\r
404 psta->hwaddr[0],psta->hwaddr[1],psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5]);
\r
406 _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
\r
408 _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
409 rtw_free_stainfo(padapter, psta);
\r
410 _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
412 _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
\r
418 _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
\r
422 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
424 phead = &pstapriv->asoc_list;
\r
425 plist = get_next(phead);
\r
428 #ifdef DBG_EXPIRATION_CHK
\r
429 if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
\r
430 DBG_871X(FUNC_NDEV_FMT" asoc_list, cnt:%u\n"
\r
431 , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->asoc_list_cnt);
\r
434 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
\r
436 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
\r
437 plist = get_next(plist);
\r
438 #ifdef CONFIG_ATMEL_RC_PATCH
\r
439 DBG_871X("%s:%d psta=%p, %02x,%02x||%02x,%02x \n\n", __func__, __LINE__,
\r
440 psta,pstapriv->atmel_rc_pattern[0], pstapriv->atmel_rc_pattern[5], psta->hwaddr[0], psta->hwaddr[5]);
\r
441 if (_TRUE == _rtw_memcmp((void *)pstapriv->atmel_rc_pattern, (void *)(psta->hwaddr), ETH_ALEN))
\r
443 if (psta->flag_atmel_rc)
\r
445 DBG_871X("%s: debug line:%d \n", __func__, __LINE__);
\r
447 #ifdef CONFIG_AUTO_AP_MODE
\r
451 if (chk_sta_is_alive(psta) || !psta->expire_to) {
\r
452 psta->expire_to = pstapriv->expire_to;
\r
453 psta->keep_alive_trycnt = 0;
\r
454 #ifdef CONFIG_TX_MCAST2UNI
\r
455 psta->under_exist_checking = 0;
\r
456 #endif // CONFIG_TX_MCAST2UNI
\r
461 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
\r
462 #ifdef CONFIG_80211N_HT
\r
463 #ifdef CONFIG_TX_MCAST2UNI
\r
464 if ( (psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking) ) {
\r
465 // check sta by delba(addba) for 11n STA
\r
466 // ToDo: use CCX report to check for all STAs
\r
467 //DBG_871X("asoc check by DELBA/ADDBA! (pstapriv->expire_to=%d s)(psta->expire_to=%d s), [%02x, %d]\n", pstapriv->expire_to*2, psta->expire_to*2, psta->htpriv.agg_enable_bitmap, psta->under_exist_checking);
\r
469 if ( psta->expire_to <= (pstapriv->expire_to - 50 ) ) {
\r
470 DBG_871X("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);
\r
471 psta->under_exist_checking = 0;
\r
472 psta->expire_to = 0;
\r
473 } else if ( psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking==0)) {
\r
474 DBG_871X("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);
\r
475 psta->under_exist_checking = 1;
\r
476 //tear down TX AMPDU
\r
477 send_delba(padapter, 1, psta->hwaddr);// // originator
\r
478 psta->htpriv.agg_enable_bitmap = 0x0;//reset
\r
479 psta->htpriv.candidate_tid_bitmap = 0x0;//reset
\r
482 #endif //CONFIG_TX_MCAST2UNI
\r
483 #endif //CONFIG_80211N_HT
\r
484 #endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK
\r
486 if (psta->expire_to <= 0)
\r
488 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
490 if (padapter->registrypriv.wifi_spec == 1)
\r
492 psta->expire_to = pstapriv->expire_to;
\r
496 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
\r
497 #ifdef CONFIG_80211N_HT
\r
499 #define KEEP_ALIVE_TRYCNT (3)
\r
501 if(psta->keep_alive_trycnt > 0 && psta->keep_alive_trycnt <= KEEP_ALIVE_TRYCNT)
\r
503 if(psta->state & WIFI_STA_ALIVE_CHK_STATE)
\r
504 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
\r
506 psta->keep_alive_trycnt = 0;
\r
509 else if((psta->keep_alive_trycnt > KEEP_ALIVE_TRYCNT) && !(psta->state & WIFI_STA_ALIVE_CHK_STATE))
\r
511 psta->keep_alive_trycnt = 0;
\r
513 if((psta->htpriv.ht_option==_TRUE) && (psta->htpriv.ampdu_enable==_TRUE))
\r
515 uint priority = 1; //test using BK
\r
518 //issued = (psta->htpriv.agg_enable_bitmap>>priority)&0x1;
\r
519 issued |= (psta->htpriv.candidate_tid_bitmap>>priority)&0x1;
\r
523 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE))
\r
525 psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
\r
527 if (psta->state & WIFI_SLEEP_STATE)
\r
528 psta->expire_to = 2; // 2x2=4 sec
\r
530 psta->expire_to = 1; // 2 sec
\r
532 psta->state |= WIFI_STA_ALIVE_CHK_STATE;
\r
534 //add_ba_hdl(padapter, (u8*)paddbareq_parm);
\r
536 DBG_871X("issue addba_req to check if sta alive, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);
\r
538 issue_action_BA(padapter, psta->hwaddr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)priority);
\r
540 _set_timer(&psta->addba_retry_timer, ADDBA_TO);
\r
542 psta->keep_alive_trycnt++;
\r
548 if(psta->keep_alive_trycnt > 0 && psta->state & WIFI_STA_ALIVE_CHK_STATE)
\r
550 psta->keep_alive_trycnt = 0;
\r
551 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
\r
552 DBG_871X("change to another methods to check alive if staion is at ps mode\n");
\r
555 #endif //CONFIG_80211N_HT
\r
556 #endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK
\r
557 if (psta->state & WIFI_SLEEP_STATE) {
\r
558 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
\r
559 //to check if alive by another methods if staion is at ps mode.
\r
560 psta->expire_to = pstapriv->expire_to;
\r
561 psta->state |= WIFI_STA_ALIVE_CHK_STATE;
\r
563 //DBG_871X("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->hwaddr));
\r
565 //to update bcn with tim_bitmap for this station
\r
566 pstapriv->tim_bitmap |= BIT(psta->aid);
\r
567 update_beacon(padapter, _TIM_IE_, NULL, _TRUE);
\r
569 if(!pmlmeext->active_keep_alive_check)
\r
573 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
\r
574 if (pmlmeext->active_keep_alive_check) {
\r
575 int stainfo_offset;
\r
577 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
\r
578 if (stainfo_offset_valid(stainfo_offset)) {
\r
579 chk_alive_list[chk_alive_num++] = stainfo_offset;
\r
584 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
\r
585 rtw_list_delete(&psta->asoc_list);
\r
586 pstapriv->asoc_list_cnt--;
\r
587 DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
\r
588 updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING);
\r
592 /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
\r
593 if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)
\r
594 && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)
\r
596 DBG_871X("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__
\r
597 , MAC_ARG(psta->hwaddr)
\r
598 , psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt);
\r
599 wakeup_sta_to_xmit(padapter, psta);
\r
604 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
606 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
\r
607 if (chk_alive_num) {
\r
609 u8 backup_oper_channel=0;
\r
610 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
611 /* switch to correct channel of current network before issue keep-alive frames */
\r
612 if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
\r
613 backup_oper_channel = rtw_get_oper_ch(padapter);
\r
614 SelectChannel(padapter, pmlmeext->cur_channel);
\r
617 /* issue null data to check sta alive*/
\r
618 for (i = 0; i < chk_alive_num; i++) {
\r
621 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
\r
622 #ifdef CONFIG_ATMEL_RC_PATCH
\r
623 if (_TRUE == _rtw_memcmp( pstapriv->atmel_rc_pattern, psta->hwaddr, ETH_ALEN))
\r
625 if (psta->flag_atmel_rc)
\r
628 if(!(psta->state &_FW_LINKED))
\r
631 if (psta->state & WIFI_SLEEP_STATE)
\r
632 ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);
\r
634 ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);
\r
636 psta->keep_alive_trycnt++;
\r
637 if (ret == _SUCCESS)
\r
639 DBG_871X("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr));
\r
640 psta->expire_to = pstapriv->expire_to;
\r
641 psta->keep_alive_trycnt = 0;
\r
644 else if (psta->keep_alive_trycnt <= 3)
\r
646 DBG_871X("ack check for asoc expire, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);
\r
647 psta->expire_to = 1;
\r
651 psta->keep_alive_trycnt = 0;
\r
652 DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
\r
653 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
654 if (rtw_is_list_empty(&psta->asoc_list)==_FALSE) {
\r
655 rtw_list_delete(&psta->asoc_list);
\r
656 pstapriv->asoc_list_cnt--;
\r
657 updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING);
\r
659 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
663 if (backup_oper_channel>0) /* back to the original operation channel */
\r
664 SelectChannel(padapter, backup_oper_channel);
\r
666 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
\r
668 associated_clients_update(padapter, updated);
\r
671 void add_RATid(_adapter *padapter, struct sta_info *psta, u8 rssi_level)
\r
675 unsigned char sta_band = 0, shortGIrate = _FALSE;
\r
676 unsigned int tx_ra_bitmap=0;
\r
677 struct ht_priv *psta_ht = NULL;
\r
678 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
679 WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
\r
681 #ifdef CONFIG_80211N_HT
\r
683 psta_ht = &psta->htpriv;
\r
686 #endif //CONFIG_80211N_HT
\r
688 if(!(psta->state & _FW_LINKED))
\r
692 if(get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)
\r
694 //is this a 2r STA?
\r
695 if((pstat->tx_ra_bitmap & 0x0ff00000) != 0 && !(priv->pshare->has_2r_sta & BIT(pstat->aid)))
\r
697 priv->pshare->has_2r_sta |= BIT(pstat->aid);
\r
698 if(rtw_read16(padapter, 0x102501f6) != 0xffff)
\r
700 rtw_write16(padapter, 0x102501f6, 0xffff);
\r
701 reset_1r_sta_RA(priv, 0xffff);
\r
702 Switch_1SS_Antenna(priv, 3);
\r
705 else// bg or 1R STA?
\r
707 if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && priv->pshare->has_2r_sta == 0)
\r
709 if(rtw_read16(padapter, 0x102501f6) != 0x7777)
\r
711 rtw_write16(padapter, 0x102501f6,0x7777);
\r
712 reset_1r_sta_RA(priv, 0x7777);
\r
713 Switch_1SS_Antenna(priv, 2);
\r
720 if ((pstat->rssi_level < 1) || (pstat->rssi_level > 3))
\r
722 if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper)
\r
723 pstat->rssi_level = 1;
\r
724 else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) ||
\r
725 ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) &&
\r
726 (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) &&
\r
727 (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))))
\r
728 pstat->rssi_level = 2;
\r
730 pstat->rssi_level = 3;
\r
733 // rate adaptive by rssi
\r
734 if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len)
\r
736 if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R))
\r
738 switch (pstat->rssi_level) {
\r
740 pstat->tx_ra_bitmap &= 0x100f0000;
\r
743 pstat->tx_ra_bitmap &= 0x100ff000;
\r
746 if (priv->pshare->is_40m_bw)
\r
747 pstat->tx_ra_bitmap &= 0x100ff005;
\r
749 pstat->tx_ra_bitmap &= 0x100ff001;
\r
756 switch (pstat->rssi_level) {
\r
758 pstat->tx_ra_bitmap &= 0x1f0f0000;
\r
761 pstat->tx_ra_bitmap &= 0x1f0ff000;
\r
764 if (priv->pshare->is_40m_bw)
\r
765 pstat->tx_ra_bitmap &= 0x000ff005;
\r
767 pstat->tx_ra_bitmap &= 0x000ff001;
\r
772 // Don't need to mask high rates due to new rate adaptive parameters
\r
773 //if (pstat->is_broadcom_sta) // use MCS12 as the highest rate vs. Broadcom sta
\r
774 // pstat->tx_ra_bitmap &= 0x81ffffff;
\r
776 // NIC driver will report not supporting MCS15 and MCS14 in asoc req
\r
777 //if (pstat->is_rtl8190_sta && !pstat->is_2t_mimo_sta)
\r
778 // pstat->tx_ra_bitmap &= 0x83ffffff; // if Realtek 1x2 sta, don't use MCS15 and MCS14
\r
781 else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat))
\r
783 switch (pstat->rssi_level) {
\r
785 pstat->tx_ra_bitmap &= 0x00000f00;
\r
788 pstat->tx_ra_bitmap &= 0x00000ff0;
\r
791 pstat->tx_ra_bitmap &= 0x00000ff5;
\r
797 pstat->tx_ra_bitmap &= 0x0000000d;
\r
800 // disable tx short GI when station cannot rx MCS15(AP is 2T2R)
\r
801 // disable tx short GI when station cannot rx MCS7 (AP is 1T2R or 1T1R)
\r
802 // if there is only 1r STA and we are 2T2R, DO NOT mask SGI rate
\r
803 if ((!(pstat->tx_ra_bitmap & 0x8000000) && (priv->pshare->has_2r_sta > 0) && (get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)) ||
\r
804 (!(pstat->tx_ra_bitmap & 0x80000) && (get_rf_mimo_mode(padapter) != RTL8712_RF_2T2R)))
\r
806 pstat->tx_ra_bitmap &= ~BIT(28);
\r
810 rtw_hal_update_sta_rate_mask(padapter, psta);
\r
811 tx_ra_bitmap = psta->ra_mask;
\r
813 shortGIrate = query_ra_short_GI(psta);
\r
815 if ( pcur_network->Configuration.DSConfig > 14 ) {
\r
817 if (tx_ra_bitmap & 0xffff000)
\r
818 sta_band |= WIRELESS_11_5N ;
\r
820 if (tx_ra_bitmap & 0xff0)
\r
821 sta_band |= WIRELESS_11A;
\r
824 #ifdef CONFIG_80211AC_VHT
\r
825 if (psta->vhtpriv.vht_option) {
\r
826 sta_band = WIRELESS_11_5AC;
\r
831 if (tx_ra_bitmap & 0xffff000)
\r
832 sta_band |= WIRELESS_11_24N;
\r
834 if (tx_ra_bitmap & 0xff0)
\r
835 sta_band |= WIRELESS_11G;
\r
837 if (tx_ra_bitmap & 0x0f)
\r
838 sta_band |= WIRELESS_11B;
\r
841 psta->wireless_mode = sta_band;
\r
842 psta->raid = rtw_hal_networktype_to_raid(padapter, psta);
\r
844 if (psta->aid < NUM_STA)
\r
848 arg[0] = psta->mac_id;
\r
849 arg[1] = psta->raid;
\r
850 arg[2] = shortGIrate;
\r
851 arg[3] = psta->init_rate;
\r
853 DBG_871X("%s=> mac_id:%d , raid:%d , shortGIrate=%d, bitmap=0x%x\n",
\r
854 __FUNCTION__ , psta->mac_id, psta->raid ,shortGIrate, tx_ra_bitmap);
\r
856 rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);
\r
860 DBG_871X("station aid %d exceed the max number\n", psta->aid);
\r
865 void update_bmc_sta(_adapter *padapter)
\r
868 unsigned char network_type;
\r
869 int supportRateNum = 0;
\r
870 unsigned int tx_ra_bitmap=0;
\r
871 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
872 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
873 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
874 WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
\r
875 struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);
\r
879 psta->aid = 0;//default set to 0
\r
880 //psta->mac_id = psta->aid+4;
\r
881 psta->mac_id = psta->aid + 1;//mac_id=1 for bc/mc stainfo
\r
883 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
\r
885 psta->qos_option = 0;
\r
886 #ifdef CONFIG_80211N_HT
\r
887 psta->htpriv.ht_option = _FALSE;
\r
888 #endif //CONFIG_80211N_HT
\r
890 psta->ieee8021x_blocked = 0;
\r
892 _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
\r
894 //psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this.
\r
896 //prepare for add_RATid
\r
897 supportRateNum = rtw_get_rateset_len((u8*)&pcur_network->SupportedRates);
\r
898 network_type = rtw_check_network_type((u8*)&pcur_network->SupportedRates, supportRateNum, pcur_network->Configuration.DSConfig);
\r
899 if (IsSupportedTxCCK(network_type)) {
\r
900 network_type = WIRELESS_11B;
\r
902 else if (network_type == WIRELESS_INVALID) { // error handling
\r
903 if ( pcur_network->Configuration.DSConfig > 14 )
\r
904 network_type = WIRELESS_11A;
\r
906 network_type = WIRELESS_11B;
\r
908 update_sta_basic_rate(psta, network_type);
\r
909 psta->wireless_mode = network_type;
\r
911 rtw_hal_update_sta_rate_mask(padapter, psta);
\r
912 tx_ra_bitmap = psta->ra_mask;
\r
914 psta->raid = rtw_hal_networktype_to_raid(padapter,psta);
\r
917 rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);
\r
919 //if(pHalData->fw_ractrl == _TRUE)
\r
923 arg[0] = psta->mac_id;
\r
924 arg[1] = psta->raid;
\r
926 arg[3] = psta->init_rate;
\r
928 DBG_871X("%s=> mac_id:%d , raid:%d , bitmap=0x%x\n",
\r
929 __FUNCTION__ , psta->mac_id, psta->raid , tx_ra_bitmap);
\r
931 rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);
\r
934 rtw_sta_media_status_rpt(padapter, psta, 1);
\r
936 _enter_critical_bh(&psta->lock, &irqL);
\r
937 psta->state = _FW_LINKED;
\r
938 _exit_critical_bh(&psta->lock, &irqL);
\r
943 DBG_871X("add_RATid_bmc_sta error!\n");
\r
949 //AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode
\r
950 //MAC_ID = AID+1 for sta in ap/adhoc mode
\r
951 //MAC_ID = 1 for bc/mc for sta/ap/adhoc
\r
952 //MAC_ID = 0 for bssid for sta/ap/adhoc
\r
953 //CAM_ID = //0~3 for default key, cmd_id=macid + 3, macid=aid+1;
\r
955 void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta)
\r
958 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
959 struct security_priv *psecuritypriv = &padapter->securitypriv;
\r
960 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
961 #ifdef CONFIG_80211N_HT
\r
962 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
\r
963 struct ht_priv *phtpriv_sta = &psta->htpriv;
\r
964 #endif //CONFIG_80211N_HT
\r
965 u8 cur_ldpc_cap=0, cur_stbc_cap=0, cur_beamform_cap=0;
\r
966 //set intf_tag to if1
\r
967 //psta->intf_tag = 0;
\r
969 DBG_871X("%s\n",__FUNCTION__);
\r
971 //psta->mac_id = psta->aid+4;
\r
972 //psta->mac_id = psta->aid+1;//alloc macid when call rtw_alloc_stainfo(),
\r
973 //release macid when call rtw_free_stainfo()
\r
976 rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,psta,_TRUE);
\r
978 if(psecuritypriv->dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)
\r
979 psta->ieee8021x_blocked = _TRUE;
\r
981 psta->ieee8021x_blocked = _FALSE;
\r
987 VCS_update(padapter, psta);
\r
988 #ifdef CONFIG_80211N_HT
\r
990 if(phtpriv_sta->ht_option)
\r
992 //check if sta supports rx ampdu
\r
993 phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
\r
995 //check if sta support s Short GI 20M
\r
996 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
\r
998 phtpriv_sta->sgi_20m = _TRUE;
\r
1000 //check if sta support s Short GI 40M
\r
1001 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))
\r
1003 phtpriv_sta->sgi_40m = _TRUE;
\r
1007 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))
\r
1009 phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
\r
1010 psta->bw_mode = CHANNEL_WIDTH_40;
\r
1014 psta->bw_mode = CHANNEL_WIDTH_20;
\r
1017 psta->qos_option = _TRUE;
\r
1019 // B0 Config LDPC Coding Capability
\r
1020 if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) &&
\r
1021 GET_HT_CAPABILITY_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap)))
\r
1023 SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));
\r
1024 DBG_871X("Enable HT Tx LDPC for STA(%d)\n",psta->aid);
\r
1027 // B7 B8 B9 Config STBC setting
\r
1028 if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) &&
\r
1029 GET_HT_CAPABILITY_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap)))
\r
1031 SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX) );
\r
1032 DBG_871X("Enable HT Tx STBC for STA(%d)\n",psta->aid);
\r
1035 #ifdef CONFIG_BEAMFORMING
\r
1036 // Config Tx beamforming setting
\r
1037 if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) &&
\r
1038 GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP((u8 *)(&phtpriv_sta->ht_cap)))
\r
1040 SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
\r
1043 if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&
\r
1044 GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP((u8 *)(&phtpriv_sta->ht_cap)))
\r
1046 SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
\r
1049 if (cur_beamform_cap) {
\r
1050 DBG_871X("Client STA(%d) HT Beamforming Cap = 0x%02X\n", psta->aid, cur_beamform_cap);
\r
1052 #endif //CONFIG_BEAMFORMING
\r
1056 phtpriv_sta->ampdu_enable = _FALSE;
\r
1058 phtpriv_sta->sgi_20m = _FALSE;
\r
1059 phtpriv_sta->sgi_40m = _FALSE;
\r
1060 psta->bw_mode = CHANNEL_WIDTH_20;
\r
1061 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
\r
1064 phtpriv_sta->ldpc_cap = cur_ldpc_cap;
\r
1065 phtpriv_sta->stbc_cap = cur_stbc_cap;
\r
1066 phtpriv_sta->beamform_cap = cur_beamform_cap;
\r
1069 send_delba(padapter, 0, psta->hwaddr);// recipient
\r
1072 send_delba(padapter, 1, psta->hwaddr);// // originator
\r
1073 phtpriv_sta->agg_enable_bitmap = 0x0;//reset
\r
1074 phtpriv_sta->candidate_tid_bitmap = 0x0;//reset
\r
1075 #endif //CONFIG_80211N_HT
\r
1077 #ifdef CONFIG_80211AC_VHT
\r
1078 update_sta_vht_info_apmode(padapter, psta);
\r
1081 update_ldpc_stbc_cap(psta);
\r
1083 //todo: init other variables
\r
1085 _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
\r
1089 //add_RATid(padapter, psta);//move to ap_sta_info_defer_update()
\r
1092 _enter_critical_bh(&psta->lock, &irqL);
\r
1093 psta->state |= _FW_LINKED;
\r
1094 _exit_critical_bh(&psta->lock, &irqL);
\r
1099 static void update_ap_info(_adapter *padapter, struct sta_info *psta)
\r
1101 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
1102 WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
\r
1103 struct security_priv *psecuritypriv = &padapter->securitypriv;
\r
1104 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
1105 #ifdef CONFIG_80211N_HT
\r
1106 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
\r
1107 #endif //CONFIG_80211N_HT
\r
1110 psta->wireless_mode = pmlmeext->cur_wireless_mode;
\r
1112 psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates);
\r
1113 _rtw_memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen);
\r
1115 #ifdef CONFIG_80211N_HT
\r
1117 if(phtpriv_ap->ht_option)
\r
1119 //check if sta supports rx ampdu
\r
1120 //phtpriv_ap->ampdu_enable = phtpriv_ap->ampdu_enable;
\r
1122 //check if sta support s Short GI 20M
\r
1123 if((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
\r
1125 phtpriv_ap->sgi_20m = _TRUE;
\r
1127 //check if sta support s Short GI 40M
\r
1128 if((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))
\r
1130 phtpriv_ap->sgi_40m = _TRUE;
\r
1133 psta->qos_option = _TRUE;
\r
1137 phtpriv_ap->ampdu_enable = _FALSE;
\r
1139 phtpriv_ap->sgi_20m = _FALSE;
\r
1140 phtpriv_ap->sgi_40m = _FALSE;
\r
1143 psta->bw_mode = pmlmeext->cur_bwmode;
\r
1144 phtpriv_ap->ch_offset = pmlmeext->cur_ch_offset;
\r
1146 phtpriv_ap->agg_enable_bitmap = 0x0;//reset
\r
1147 phtpriv_ap->candidate_tid_bitmap = 0x0;//reset
\r
1149 _rtw_memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv));
\r
1151 #ifdef CONFIG_80211AC_VHT
\r
1152 _rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));
\r
1153 #endif //CONFIG_80211AC_VHT
\r
1155 #endif //CONFIG_80211N_HT
\r
1158 static void update_hw_ht_param(_adapter *padapter)
\r
1160 unsigned char max_AMPDU_len;
\r
1161 unsigned char min_MPDU_spacing;
\r
1162 struct registry_priv *pregpriv = &padapter->registrypriv;
\r
1163 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
1164 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
1166 DBG_871X("%s\n", __FUNCTION__);
\r
1169 //handle A-MPDU parameter field
\r
1171 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
\r
1172 AMPDU_para [4:2]:Min MPDU Start Spacing
\r
1174 max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
\r
1176 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;
\r
1178 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
\r
1180 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
\r
1183 // Config SM Power Save setting
\r
1185 pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
\r
1186 if(pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
\r
1189 //update the MCS rates
\r
1190 for (i = 0; i < 16; i++)
\r
1192 pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];
\r
1194 DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n",__FUNCTION__);
\r
1198 // Config current HT Protection mode.
\r
1200 //pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
\r
1204 void start_bss_network(_adapter *padapter, u8 *pbuf)
\r
1207 u8 val8, cur_channel, cur_bwmode, cur_ch_offset;
\r
1211 struct registry_priv *pregpriv = &padapter->registrypriv;
\r
1212 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
1213 struct security_priv* psecuritypriv=&(padapter->securitypriv);
\r
1214 WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
\r
1215 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
1216 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
1217 WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
\r
1218 struct HT_info_element *pht_info=NULL;
\r
1220 struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
\r
1221 #endif //CONFIG_P2P
\r
1222 u8 cbw40_enable=0;
\r
1223 u8 change_band = _FALSE;
\r
1225 //DBG_871X("%s\n", __FUNCTION__);
\r
1227 bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;
\r
1228 cur_channel = pnetwork->Configuration.DSConfig;
\r
1229 cur_bwmode = CHANNEL_WIDTH_20;
\r
1230 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
\r
1233 //check if there is wps ie,
\r
1234 //if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd,
\r
1235 //and at first time the security ie ( RSN/WPA IE) will not include in beacon.
\r
1236 if(NULL == rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))
\r
1238 pmlmeext->bstart_bss = _TRUE;
\r
1241 //todo: update wmm, ht cap
\r
1242 //pmlmeinfo->WMM_enable;
\r
1243 //pmlmeinfo->HT_enable;
\r
1244 if(pmlmepriv->qospriv.qos_option)
\r
1245 pmlmeinfo->WMM_enable = _TRUE;
\r
1246 #ifdef CONFIG_80211N_HT
\r
1247 if(pmlmepriv->htpriv.ht_option)
\r
1249 pmlmeinfo->WMM_enable = _TRUE;
\r
1250 pmlmeinfo->HT_enable = _TRUE;
\r
1251 //pmlmeinfo->HT_info_enable = _TRUE;
\r
1252 //pmlmeinfo->HT_caps_enable = _TRUE;
\r
1254 update_hw_ht_param(padapter);
\r
1256 #endif //#CONFIG_80211N_HT
\r
1258 #ifdef CONFIG_80211AC_VHT
\r
1259 if(pmlmepriv->vhtpriv.vht_option) {
\r
1260 pmlmeinfo->VHT_enable = _TRUE;
\r
1261 update_hw_vht_param(padapter);
\r
1263 #endif //CONFIG_80211AC_VHT
\r
1265 if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at first time
\r
1267 //WEP Key will be set before this function, do not clear CAM.
\r
1268 if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
\r
1269 flush_all_cam_entry(padapter); //clear CAM
\r
1272 //set MSR to AP_Mode
\r
1273 Set_MSR(padapter, _HW_STATE_AP_);
\r
1276 rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
\r
1278 //Set EDCA param reg
\r
1279 #ifdef CONFIG_CONCURRENT_MODE
\r
1280 acparm = 0x005ea42b;
\r
1282 acparm = 0x002F3217; // VO
\r
1284 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
\r
1285 acparm = 0x005E4317; // VI
\r
1286 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
\r
1287 //acparm = 0x00105320; // BE
\r
1288 acparm = 0x005ea42b;
\r
1289 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
\r
1290 acparm = 0x0000A444; // BK
\r
1291 rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
\r
1294 val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
\r
1295 rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
\r
1297 //Beacon Control related register
\r
1298 rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
\r
1300 rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
\r
1302 if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at first time
\r
1304 //u32 initialgain;
\r
1306 //initialgain = 0x1e;
\r
1309 //disable dynamic functions, such as high power, DIG
\r
1310 //Save_DM_Func_Flag(padapter);
\r
1311 //Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);
\r
1313 //turn on all dynamic functions
\r
1314 Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);
\r
1316 //rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
\r
1319 #ifdef CONFIG_80211N_HT
\r
1320 //set channel, bwmode
\r
1321 p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
\r
1324 pht_info = (struct HT_info_element *)(p+2);
\r
1326 if (cur_channel > 14) {
\r
1327 if ((pregpriv->bw_mode & 0xf0) > 0)
\r
1330 if ((pregpriv->bw_mode & 0x0f) > 0)
\r
1334 if ((cbw40_enable) && (pht_info->infos[0] & BIT(2)))
\r
1336 //switch to the 40M Hz mode
\r
1337 //pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
\r
1338 cur_bwmode = CHANNEL_WIDTH_40;
\r
1339 switch (pht_info->infos[0] & 0x3)
\r
1342 //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
\r
1343 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
\r
1347 //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
\r
1348 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
\r
1352 //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
\r
1353 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
\r
1360 #endif //CONFIG_80211N_HT
\r
1362 #ifdef CONFIG_80211AC_VHT
\r
1363 p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTOperation, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
\r
1366 if(GET_VHT_OPERATION_ELE_CHL_WIDTH(p+2) >= 1) {
\r
1367 cur_bwmode = CHANNEL_WIDTH_80;
\r
1372 #ifdef CONFIG_DUALMAC_CONCURRENT
\r
1373 dc_set_ap_channel_bandwidth(padapter, cur_channel, cur_ch_offset, cur_bwmode);
\r
1374 #else //!CONFIG_DUALMAC_CONCURRENT
\r
1375 #ifdef CONFIG_CONCURRENT_MODE
\r
1376 //TODO: need to judge the phy parameters on concurrent mode for single phy
\r
1377 concurrent_set_ap_chbw(padapter, cur_channel, cur_ch_offset, cur_bwmode);
\r
1378 #else //!CONFIG_CONCURRENT_MODE
\r
1379 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
\r
1380 DBG_871X("CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);
\r
1381 pmlmeext->cur_channel = cur_channel;
\r
1382 pmlmeext->cur_bwmode = cur_bwmode;
\r
1383 pmlmeext->cur_ch_offset = cur_ch_offset;
\r
1384 #endif //!CONFIG_CONCURRENT_MODE
\r
1385 #endif //!CONFIG_DUALMAC_CONCURRENT
\r
1387 pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;
\r
1389 //let pnetwork_mlmeext == pnetwork_mlme.
\r
1390 _rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
\r
1392 //update cur_wireless_mode
\r
1393 update_wireless_mode(padapter);
\r
1395 //update RRSR after set channel and bandwidth
\r
1396 UpdateBrateTbl(padapter, pnetwork->SupportedRates);
\r
1397 rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
\r
1399 //udpate capability after cur_wireless_mode updated
\r
1400 update_capinfo(padapter, rtw_get_capability((WLAN_BSSID_EX *)pnetwork));
\r
1404 _rtw_memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.Ssid, pnetwork->Ssid.SsidLength);
\r
1405 pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.SsidLength;
\r
1406 #endif //CONFIG_P2P
\r
1408 if(_TRUE == pmlmeext->bstart_bss)
\r
1410 update_beacon(padapter, _TIM_IE_, NULL, _TRUE);
\r
1412 #ifndef CONFIG_INTERRUPT_BASED_TXBCN //other case will tx beacon when bcn interrupt coming in.
\r
1413 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
\r
1414 //issue beacon frame
\r
1415 if(send_beacon(padapter)==_FAIL)
\r
1417 DBG_871X("issue_beacon, fail!\n");
\r
1420 #endif //!CONFIG_INTERRUPT_BASED_TXBCN
\r
1425 //update bc/mc sta_info
\r
1426 update_bmc_sta(padapter);
\r
1428 //pmlmeext->bstart_bss = _TRUE;
\r
1432 int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf, int len)
\r
1436 u8 *pHT_caps_ie=NULL;
\r
1437 u8 *pHT_info_ie=NULL;
\r
1438 struct sta_info *psta = NULL;
\r
1439 u16 cap, ht_cap=_FALSE;
\r
1441 int group_cipher, pairwise_cipher;
\r
1442 u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
\r
1443 int supportRateNum = 0;
\r
1444 u8 OUI1[] = {0x00, 0x50, 0xf2,0x01};
\r
1445 u8 wps_oui[4]={0x0,0x50,0xf2,0x04};
\r
1446 u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
\r
1447 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
1448 struct security_priv *psecuritypriv = &padapter->securitypriv;
\r
1449 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
1450 WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
\r
1451 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1452 u8 *ie = pbss_network->IEs;
\r
1453 u8 vht_cap=_FALSE;
\r
1456 /* Supported rates */
\r
1458 /* WLAN_EID_COUNTRY */
\r
1459 /* ERP Information element */
\r
1460 /* Extended supported rates */
\r
1462 /* Wi-Fi Wireless Multimedia Extensions */
\r
1463 /* ht_capab, ht_oper */
\r
1466 DBG_871X("%s, len=%d\n", __FUNCTION__, len);
\r
1468 if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
\r
1475 pbss_network->IELength = len;
\r
1477 _rtw_memset(ie, 0, MAX_IE_SZ);
\r
1479 _rtw_memcpy(ie, pbuf, pbss_network->IELength);
\r
1482 if(pbss_network->InfrastructureMode!=Ndis802_11APMode)
\r
1485 pbss_network->Rssi = 0;
\r
1487 _rtw_memcpy(pbss_network->MacAddress, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
1490 p = rtw_get_beacon_interval_from_ie(ie);//ie + 8; // 8: TimeStamp, 2: Beacon Interval 2:Capability
\r
1491 //pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p);
\r
1492 pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);
\r
1495 //cap = *(unsigned short *)rtw_get_capability_from_ie(ie);
\r
1496 //cap = le16_to_cpu(cap);
\r
1497 cap = RTW_GET_LE16(ie);
\r
1500 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength -_BEACON_IE_OFFSET_));
\r
1503 _rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
\r
1504 _rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
\r
1505 pbss_network->Ssid.SsidLength = ie_len;
\r
1510 pbss_network->Configuration.Length = 0;
\r
1511 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
\r
1513 channel = *(p + 2);
\r
1515 pbss_network->Configuration.DSConfig = channel;
\r
1518 _rtw_memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
\r
1519 // get supported rates
\r
1520 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
\r
1523 _rtw_memcpy(supportRate, p+2, ie_len);
\r
1524 supportRateNum = ie_len;
\r
1527 //get ext_supported rates
\r
1528 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);
\r
1531 _rtw_memcpy(supportRate+supportRateNum, p+2, ie_len);
\r
1532 supportRateNum += ie_len;
\r
1536 network_type = rtw_check_network_type(supportRate, supportRateNum, channel);
\r
1538 rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
\r
1542 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
\r
1545 ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);
\r
1548 //update privacy/security
\r
1550 pbss_network->Privacy = 1;
\r
1552 pbss_network->Privacy = 0;
\r
1554 psecuritypriv->wpa_psk = 0;
\r
1557 group_cipher = 0; pairwise_cipher = 0;
\r
1558 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
\r
1559 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
\r
1560 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
\r
1563 if(rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
\r
1565 psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
\r
1567 psecuritypriv->dot8021xalg = 1;//psk, todo:802.1x
\r
1568 psecuritypriv->wpa_psk |= BIT(1);
\r
1570 psecuritypriv->wpa2_group_cipher = group_cipher;
\r
1571 psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
\r
1573 switch(group_cipher)
\r
1575 case WPA_CIPHER_NONE:
\r
1576 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
\r
1578 case WPA_CIPHER_WEP40:
\r
1579 psecuritypriv->wpa2_group_cipher = _WEP40_;
\r
1581 case WPA_CIPHER_TKIP:
\r
1582 psecuritypriv->wpa2_group_cipher = _TKIP_;
\r
1584 case WPA_CIPHER_CCMP:
\r
1585 psecuritypriv->wpa2_group_cipher = _AES_;
\r
1587 case WPA_CIPHER_WEP104:
\r
1588 psecuritypriv->wpa2_group_cipher = _WEP104_;
\r
1592 switch(pairwise_cipher)
\r
1594 case WPA_CIPHER_NONE:
\r
1595 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
\r
1597 case WPA_CIPHER_WEP40:
\r
1598 psecuritypriv->wpa2_pairwise_cipher = _WEP40_;
\r
1600 case WPA_CIPHER_TKIP:
\r
1601 psecuritypriv->wpa2_pairwise_cipher = _TKIP_;
\r
1603 case WPA_CIPHER_CCMP:
\r
1604 psecuritypriv->wpa2_pairwise_cipher = _AES_;
\r
1606 case WPA_CIPHER_WEP104:
\r
1607 psecuritypriv->wpa2_pairwise_cipher = _WEP104_;
\r
1617 group_cipher = 0; pairwise_cipher = 0;
\r
1618 psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
\r
1619 psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
\r
1620 for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))
\r
1622 p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
\r
1623 if ((p) && (_rtw_memcmp(p+2, OUI1, 4)))
\r
1625 if(rtw_parse_wpa_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
\r
1627 psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
\r
1629 psecuritypriv->dot8021xalg = 1;//psk, todo:802.1x
\r
1631 psecuritypriv->wpa_psk |= BIT(0);
\r
1633 psecuritypriv->wpa_group_cipher = group_cipher;
\r
1634 psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
\r
1637 switch(group_cipher)
\r
1639 case WPA_CIPHER_NONE:
\r
1640 psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
\r
1642 case WPA_CIPHER_WEP40:
\r
1643 psecuritypriv->wpa_group_cipher = _WEP40_;
\r
1645 case WPA_CIPHER_TKIP:
\r
1646 psecuritypriv->wpa_group_cipher = _TKIP_;
\r
1648 case WPA_CIPHER_CCMP:
\r
1649 psecuritypriv->wpa_group_cipher = _AES_;
\r
1651 case WPA_CIPHER_WEP104:
\r
1652 psecuritypriv->wpa_group_cipher = _WEP104_;
\r
1656 switch(pairwise_cipher)
\r
1658 case WPA_CIPHER_NONE:
\r
1659 psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
\r
1661 case WPA_CIPHER_WEP40:
\r
1662 psecuritypriv->wpa_pairwise_cipher = _WEP40_;
\r
1664 case WPA_CIPHER_TKIP:
\r
1665 psecuritypriv->wpa_pairwise_cipher = _TKIP_;
\r
1667 case WPA_CIPHER_CCMP:
\r
1668 psecuritypriv->wpa_pairwise_cipher = _AES_;
\r
1670 case WPA_CIPHER_WEP104:
\r
1671 psecuritypriv->wpa_pairwise_cipher = _WEP104_;
\r
1681 if ((p == NULL) || (ie_len == 0))
\r
1690 pmlmepriv->qospriv.qos_option = 0;
\r
1691 if(pregistrypriv->wmm_enable)
\r
1693 for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))
\r
1695 p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
\r
1696 if((p) && _rtw_memcmp(p+2, WMM_PARA_IE, 6))
\r
1698 pmlmepriv->qospriv.qos_option = 1;
\r
1700 *(p+8) |= BIT(7);//QoS Info, support U-APSD
\r
1702 /* disable all ACM bits since the WMM admission control is not supported */
\r
1703 *(p + 10) &= ~BIT(4); /* BE */
\r
1704 *(p + 14) &= ~BIT(4); /* BK */
\r
1705 *(p + 18) &= ~BIT(4); /* VI */
\r
1706 *(p + 22) &= ~BIT(4); /* VO */
\r
1711 if ((p == NULL) || (ie_len == 0))
\r
1717 #ifdef CONFIG_80211N_HT
\r
1718 //parsing HT_CAP_IE
\r
1719 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
\r
1723 HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor=0;
\r
1724 struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2);
\r
1729 network_type |= WIRELESS_11_24N;
\r
1731 rtw_ht_use_default_setting(padapter);
\r
1733 if (pmlmepriv->htpriv.sgi_20m == _FALSE)
\r
1734 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_20);
\r
1736 if (pmlmepriv->htpriv.sgi_40m == _FALSE)
\r
1737 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_40);
\r
1739 if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX))
\r
1741 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_LDPC_CODING);
\r
1744 if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX))
\r
1746 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_TX_STBC);
\r
1749 if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX))
\r
1751 pht_cap->cap_info &= ~(IEEE80211_HT_CAP_RX_STBC_3R);
\r
1754 pht_cap->ampdu_params_info &= ~(IEEE80211_HT_CAP_AMPDU_FACTOR|IEEE80211_HT_CAP_AMPDU_DENSITY);
\r
1756 if((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
\r
1757 (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
\r
1759 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));
\r
1763 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);
\r
1766 rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
\r
1767 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor); //set Max Rx AMPDU size to 64K
\r
1769 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
\r
1770 if(rf_type == RF_1T1R)
\r
1772 pht_cap->supp_mcs_set[0] = 0xff;
\r
1773 pht_cap->supp_mcs_set[1] = 0x0;
\r
1776 #ifdef CONFIG_BEAMFORMING
\r
1777 // Use registry value to enable HT Beamforming.
\r
1778 // ToDo: use configure file to set these capability.
\r
1779 pht_cap->tx_BF_cap_info = 0;
\r
1782 if(TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE))
\r
1784 // Transmit NDP Capable
\r
1785 SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(pht_cap, 1);
\r
1786 // Explicit Compressed Steering Capable
\r
1787 SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pht_cap, 1);
\r
1788 // Compressed Steering Number Antennas
\r
1789 SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, 1);
\r
1793 if(TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE))
\r
1795 // Receive NDP Capable
\r
1796 SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(pht_cap, 1);
\r
1797 // Explicit Compressed Beamforming Feedback Capable
\r
1798 SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pht_cap, 2);
\r
1800 #endif //CONFIG_BEAMFORMING
\r
1802 _rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);
\r
1806 //parsing HT_INFO_IE
\r
1807 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
\r
1812 #endif //CONFIG_80211N_HT
\r
1813 switch(network_type)
\r
1815 case WIRELESS_11B:
\r
1816 pbss_network->NetworkTypeInUse = Ndis802_11DS;
\r
1818 case WIRELESS_11G:
\r
1819 case WIRELESS_11BG:
\r
1820 case WIRELESS_11G_24N:
\r
1821 case WIRELESS_11BG_24N:
\r
1822 pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
\r
1824 case WIRELESS_11A:
\r
1825 pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
\r
1828 pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
\r
1832 pmlmepriv->cur_network.network_type = network_type;
\r
1834 #ifdef CONFIG_80211N_HT
\r
1835 pmlmepriv->htpriv.ht_option = _FALSE;
\r
1837 if( (psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
\r
1838 (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP))
\r
1841 //ht_cap = _FALSE;
\r
1845 if(pregistrypriv->ht_enable && ht_cap==_TRUE)
\r
1847 pmlmepriv->htpriv.ht_option = _TRUE;
\r
1848 pmlmepriv->qospriv.qos_option = 1;
\r
1850 if(pregistrypriv->ampdu_enable==1)
\r
1852 pmlmepriv->htpriv.ampdu_enable = _TRUE;
\r
1855 HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie);
\r
1857 HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie);
\r
1861 #ifdef CONFIG_80211AC_VHT
\r
1863 //Parsing VHT CAP IE
\r
1864 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
\r
1869 //Parsing VHT OPERATION IE
\r
1872 pmlmepriv->vhtpriv.vht_option = _FALSE;
\r
1873 // if channel in 5G band, then add vht ie .
\r
1874 if ((pbss_network->Configuration.DSConfig > 14) &&
\r
1875 (pmlmepriv->htpriv.ht_option == _TRUE) &&
\r
1876 (pregistrypriv->vht_enable))
\r
1878 if(vht_cap == _TRUE)
\r
1880 pmlmepriv->vhtpriv.vht_option = _TRUE;
\r
1882 else if(pregistrypriv->vht_enable == 2) // auto enabled
\r
1884 u8 cap_len, operation_len;
\r
1886 rtw_vht_use_default_setting(padapter);
\r
1888 // VHT Capabilities element
\r
1889 cap_len = rtw_build_vht_cap_ie(padapter, pbss_network->IEs + pbss_network->IELength);
\r
1890 pbss_network->IELength += cap_len;
\r
1892 // VHT Operation element
\r
1893 operation_len = rtw_build_vht_operation_ie(padapter, pbss_network->IEs + pbss_network->IELength, pbss_network->Configuration.DSConfig);
\r
1894 pbss_network->IELength += operation_len;
\r
1896 pmlmepriv->vhtpriv.vht_option = _TRUE;
\r
1899 #endif //CONFIG_80211AC_VHT
\r
1901 pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX *)pbss_network);
\r
1903 //issue beacon to start bss network
\r
1904 //start_bss_network(padapter, (u8*)pbss_network);
\r
1905 rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK);
\r
1908 //alloc sta_info for ap itself
\r
1909 psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
\r
1912 psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
\r
1913 if (psta == NULL)
\r
1919 // update AP's sta info
\r
1920 update_ap_info(padapter, psta);
\r
1922 psta->state |= WIFI_AP_STATE; //Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724
\r
1923 rtw_indicate_connect( padapter);
\r
1925 pmlmepriv->cur_network.join_res = _TRUE;//for check if already set beacon
\r
1927 //update bc/mc sta_info
\r
1928 //update_bmc_sta(padapter);
\r
1934 void rtw_set_macaddr_acl(_adapter *padapter, int mode)
\r
1936 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1937 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
\r
1939 DBG_871X("%s, mode=%d\n", __func__, mode);
\r
1941 pacl_list->mode = mode;
\r
1944 int rtw_acl_add_sta(_adapter *padapter, u8 *addr)
\r
1947 _list *plist, *phead;
\r
1948 u8 added = _FALSE;
\r
1950 struct rtw_wlan_acl_node *paclnode;
\r
1951 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1952 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
\r
1953 _queue *pacl_node_q =&pacl_list->acl_node_q;
\r
1955 DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));
\r
1957 if((NUM_ACL-1) < pacl_list->num)
\r
1961 _enter_critical_bh(&(pacl_node_q->lock), &irqL);
\r
1963 phead = get_list_head(pacl_node_q);
\r
1964 plist = get_next(phead);
\r
1966 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
\r
1968 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
\r
1969 plist = get_next(plist);
\r
1971 if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN))
\r
1973 if(paclnode->valid == _TRUE)
\r
1976 DBG_871X("%s, sta has been added\n", __func__);
\r
1982 _exit_critical_bh(&(pacl_node_q->lock), &irqL);
\r
1985 if(added == _TRUE)
\r
1989 _enter_critical_bh(&(pacl_node_q->lock), &irqL);
\r
1991 for(i=0; i< NUM_ACL; i++)
\r
1993 paclnode = &pacl_list->aclnode[i];
\r
1995 if(paclnode->valid == _FALSE)
\r
1997 _rtw_init_listhead(&paclnode->list);
\r
1999 _rtw_memcpy(paclnode->addr, addr, ETH_ALEN);
\r
2001 paclnode->valid = _TRUE;
\r
2003 rtw_list_insert_tail(&paclnode->list, get_list_head(pacl_node_q));
\r
2011 DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);
\r
2013 _exit_critical_bh(&(pacl_node_q->lock), &irqL);
\r
2018 int rtw_acl_remove_sta(_adapter *padapter, u8 *addr)
\r
2021 _list *plist, *phead;
\r
2023 struct rtw_wlan_acl_node *paclnode;
\r
2024 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2025 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
\r
2026 _queue *pacl_node_q =&pacl_list->acl_node_q;
\r
2027 u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; //Baddr is used for clearing acl_list
\r
2029 DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));
\r
2031 _enter_critical_bh(&(pacl_node_q->lock), &irqL);
\r
2033 phead = get_list_head(pacl_node_q);
\r
2034 plist = get_next(phead);
\r
2036 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
\r
2038 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
\r
2039 plist = get_next(plist);
\r
2041 if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN) || _rtw_memcmp(baddr, addr, ETH_ALEN))
\r
2043 if(paclnode->valid == _TRUE)
\r
2045 paclnode->valid = _FALSE;
\r
2047 rtw_list_delete(&paclnode->list);
\r
2054 _exit_critical_bh(&(pacl_node_q->lock), &irqL);
\r
2056 DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);
\r
2062 u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta)
\r
2064 struct cmd_obj* ph2c;
\r
2065 struct set_stakey_parm *psetstakey_para;
\r
2066 struct cmd_priv *pcmdpriv=&padapter->cmdpriv;
\r
2069 ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
\r
2070 if ( ph2c == NULL){
\r
2075 psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm));
\r
2076 if(psetstakey_para==NULL){
\r
2077 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
\r
2082 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
\r
2085 psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
\r
2087 _rtw_memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);
\r
2089 _rtw_memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
\r
2092 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
\r
2100 static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx)
\r
2103 struct cmd_obj* pcmd;
\r
2104 struct setkey_parm *psetkeyparm;
\r
2105 struct cmd_priv *pcmdpriv=&(padapter->cmdpriv);
\r
2108 //DBG_871X("%s\n", __FUNCTION__);
\r
2110 pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
\r
2115 psetkeyparm=(struct setkey_parm*)rtw_zmalloc(sizeof(struct setkey_parm));
\r
2116 if(psetkeyparm==NULL){
\r
2117 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
\r
2122 _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));
\r
2124 psetkeyparm->keyid=(u8)keyid;
\r
2125 if (is_wep_enc(alg))
\r
2126 padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);
\r
2128 psetkeyparm->algorithm = alg;
\r
2130 psetkeyparm->set_tx = set_tx;
\r
2141 case _TKIP_WTMIC_:
\r
2147 _rtw_memcpy(&(psetkeyparm->key[0]), key, keylen);
\r
2149 pcmd->cmdcode = _SetKey_CMD_;
\r
2150 pcmd->parmbuf = (u8 *)psetkeyparm;
\r
2151 pcmd->cmdsz = (sizeof(struct setkey_parm));
\r
2156 _rtw_init_listhead(&pcmd->list);
\r
2158 res = rtw_enqueue_cmd(pcmdpriv, pcmd);
\r
2165 int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid)
\r
2167 DBG_871X("%s\n", __FUNCTION__);
\r
2169 return rtw_ap_set_key(padapter, key, alg, keyid, 1);
\r
2172 int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx)
\r
2185 alg =_NO_PRIVACY_;
\r
2188 DBG_871X("%s\n", __FUNCTION__);
\r
2190 return rtw_ap_set_key(padapter, key, alg, keyid, set_tx);
\r
2193 #ifdef CONFIG_NATIVEAP_MLME
\r
2195 static void update_bcn_fixed_ie(_adapter *padapter)
\r
2197 DBG_871X("%s\n", __FUNCTION__);
\r
2201 static void update_bcn_erpinfo_ie(_adapter *padapter)
\r
2203 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
2204 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2205 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
2206 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
\r
2207 unsigned char *p, *ie = pnetwork->IEs;
\r
2210 DBG_871X("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable);
\r
2212 if(!pmlmeinfo->ERP_enable)
\r
2216 p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
\r
2219 PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p;
\r
2221 if (pmlmepriv->num_sta_non_erp == 1)
\r
2222 pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION;
\r
2224 pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION);
\r
2226 if(pmlmepriv->num_sta_no_short_preamble > 0)
\r
2227 pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
\r
2229 pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);
\r
2231 ERP_IE_handler(padapter, pIE);
\r
2236 static void update_bcn_htcap_ie(_adapter *padapter)
\r
2238 DBG_871X("%s\n", __FUNCTION__);
\r
2242 static void update_bcn_htinfo_ie(_adapter *padapter)
\r
2244 DBG_871X("%s\n", __FUNCTION__);
\r
2248 static void update_bcn_rsn_ie(_adapter *padapter)
\r
2250 DBG_871X("%s\n", __FUNCTION__);
\r
2254 static void update_bcn_wpa_ie(_adapter *padapter)
\r
2256 DBG_871X("%s\n", __FUNCTION__);
\r
2260 static void update_bcn_wmm_ie(_adapter *padapter)
\r
2262 DBG_871X("%s\n", __FUNCTION__);
\r
2266 static void update_bcn_wps_ie(_adapter *padapter)
\r
2268 u8 *pwps_ie=NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie=NULL;
\r
2269 uint wps_ielen=0, wps_offset, remainder_ielen;
\r
2270 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
2271 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2272 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
2273 WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
\r
2274 unsigned char *ie = pnetwork->IEs;
\r
2275 u32 ielen = pnetwork->IELength;
\r
2278 DBG_871X("%s\n", __FUNCTION__);
\r
2280 pwps_ie = rtw_get_wps_ie(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
\r
2282 if(pwps_ie==NULL || wps_ielen==0)
\r
2285 pwps_ie_src = pmlmepriv->wps_beacon_ie;
\r
2286 if(pwps_ie_src == NULL)
\r
2289 wps_offset = (uint)(pwps_ie-ie);
\r
2291 premainder_ie = pwps_ie + wps_ielen;
\r
2293 remainder_ielen = ielen - wps_offset - wps_ielen;
\r
2295 if(remainder_ielen>0)
\r
2297 pbackup_remainder_ie = rtw_malloc(remainder_ielen);
\r
2298 if(pbackup_remainder_ie)
\r
2299 _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
\r
2302 wps_ielen = (uint)pwps_ie_src[1];//to get ie data len
\r
2303 if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)
\r
2305 _rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);
\r
2306 pwps_ie += (wps_ielen+2);
\r
2308 if(pbackup_remainder_ie)
\r
2309 _rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
\r
2312 pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;
\r
2315 if(pbackup_remainder_ie)
\r
2316 rtw_mfree(pbackup_remainder_ie, remainder_ielen);
\r
2318 // deal with the case without set_tx_beacon_cmd() in update_beacon()
\r
2319 #if defined( CONFIG_INTERRUPT_BASED_TXBCN ) || defined( CONFIG_PCI_HCI )
\r
2320 if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
\r
2323 rtw_get_wps_attr_content(pwps_ie_src, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8*)(&sr), NULL);
\r
2326 set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
\r
2327 DBG_871X("%s, set WIFI_UNDER_WPS\n", __func__);
\r
2333 static void update_bcn_p2p_ie(_adapter *padapter)
\r
2338 static void update_bcn_vendor_spec_ie(_adapter *padapter, u8*oui)
\r
2340 DBG_871X("%s\n", __FUNCTION__);
\r
2342 if(_rtw_memcmp(RTW_WPA_OUI, oui, 4))
\r
2344 update_bcn_wpa_ie(padapter);
\r
2346 else if(_rtw_memcmp(WMM_OUI, oui, 4))
\r
2348 update_bcn_wmm_ie(padapter);
\r
2350 else if(_rtw_memcmp(WPS_OUI, oui, 4))
\r
2352 update_bcn_wps_ie(padapter);
\r
2354 else if(_rtw_memcmp(P2P_OUI, oui, 4))
\r
2356 update_bcn_p2p_ie(padapter);
\r
2360 DBG_871X("unknown OUI type!\n");
\r
2366 void update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)
\r
2369 struct mlme_priv *pmlmepriv;
\r
2370 struct mlme_ext_priv *pmlmeext;
\r
2371 //struct mlme_ext_info *pmlmeinfo;
\r
2373 //DBG_871X("%s\n", __FUNCTION__);
\r
2378 pmlmepriv = &(padapter->mlmepriv);
\r
2379 pmlmeext = &(padapter->mlmeextpriv);
\r
2380 //pmlmeinfo = &(pmlmeext->mlmext_info);
\r
2382 if(_FALSE == pmlmeext->bstart_bss)
\r
2385 _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
\r
2391 update_bcn_fixed_ie(padapter);//8: TimeStamp, 2: Beacon Interval 2:Capability
\r
2397 update_BCNTIM(padapter);
\r
2401 case _ERPINFO_IE_:
\r
2403 update_bcn_erpinfo_ie(padapter);
\r
2407 case _HT_CAPABILITY_IE_:
\r
2409 update_bcn_htcap_ie(padapter);
\r
2415 update_bcn_rsn_ie(padapter);
\r
2419 case _HT_ADD_INFO_IE_:
\r
2421 update_bcn_htinfo_ie(padapter);
\r
2425 case _VENDOR_SPECIFIC_IE_:
\r
2427 update_bcn_vendor_spec_ie(padapter, oui);
\r
2435 pmlmepriv->update_bcn = _TRUE;
\r
2437 _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
\r
2439 #ifndef CONFIG_INTERRUPT_BASED_TXBCN
\r
2440 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
\r
2443 //send_beacon(padapter);//send_beacon must execute on TSR level
\r
2444 set_tx_beacon_cmd(padapter);
\r
2448 //PCI will issue beacon when BCN interrupt occurs.
\r
2451 #endif //!CONFIG_INTERRUPT_BASED_TXBCN
\r
2455 #ifdef CONFIG_80211N_HT
\r
2459 Set to 0 (HT pure) under the followign conditions
\r
2460 - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
\r
2461 - all STAs in the BSS are 20 MHz HT in 20 MHz BSS
\r
2462 Set to 1 (HT non-member protection) if there may be non-HT STAs
\r
2463 in both the primary and the secondary channel
\r
2464 Set to 2 if only HT STAs are associated in BSS,
\r
2465 however and at least one 20 MHz HT STA is associated
\r
2466 Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
\r
2467 (currently non-GF HT station is considered as non-HT STA also)
\r
2469 static int rtw_ht_operation_update(_adapter *padapter)
\r
2471 u16 cur_op_mode, new_op_mode;
\r
2472 int op_mode_changes = 0;
\r
2473 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
2474 struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv;
\r
2476 if(pmlmepriv->htpriv.ht_option == _TRUE)
\r
2479 //if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
\r
2482 DBG_871X("%s current operation mode=0x%X\n",
\r
2483 __FUNCTION__, pmlmepriv->ht_op_mode);
\r
2485 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
\r
2486 && pmlmepriv->num_sta_ht_no_gf) {
\r
2487 pmlmepriv->ht_op_mode |=
\r
2488 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
\r
2489 op_mode_changes++;
\r
2490 } else if ((pmlmepriv->ht_op_mode &
\r
2491 HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
\r
2492 pmlmepriv->num_sta_ht_no_gf == 0) {
\r
2493 pmlmepriv->ht_op_mode &=
\r
2494 ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
\r
2495 op_mode_changes++;
\r
2498 if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
\r
2499 (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {
\r
2500 pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
\r
2501 op_mode_changes++;
\r
2502 } else if ((pmlmepriv->ht_op_mode &
\r
2503 HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
\r
2504 (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {
\r
2505 pmlmepriv->ht_op_mode &=
\r
2506 ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
\r
2507 op_mode_changes++;
\r
2510 /* Note: currently we switch to the MIXED op mode if HT non-greenfield
\r
2511 * station is associated. Probably it's a theoretical case, since
\r
2512 * it looks like all known HT STAs support greenfield.
\r
2515 if (pmlmepriv->num_sta_no_ht ||
\r
2516 (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))
\r
2517 new_op_mode = OP_MODE_MIXED;
\r
2518 else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH)
\r
2519 && pmlmepriv->num_sta_ht_20mhz)
\r
2520 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
\r
2521 else if (pmlmepriv->olbc_ht)
\r
2522 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
\r
2524 new_op_mode = OP_MODE_PURE;
\r
2526 cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
\r
2527 if (cur_op_mode != new_op_mode) {
\r
2528 pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
\r
2529 pmlmepriv->ht_op_mode |= new_op_mode;
\r
2530 op_mode_changes++;
\r
2533 DBG_871X("%s new operation mode=0x%X changes=%d\n",
\r
2534 __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes);
\r
2536 return op_mode_changes;
\r
2540 #endif /* CONFIG_80211N_HT */
\r
2542 void associated_clients_update(_adapter *padapter, u8 updated)
\r
2544 //update associcated stations cap.
\r
2545 if(updated == _TRUE)
\r
2548 _list *phead, *plist;
\r
2549 struct sta_info *psta=NULL;
\r
2550 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2552 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
2554 phead = &pstapriv->asoc_list;
\r
2555 plist = get_next(phead);
\r
2557 //check asoc_queue
\r
2558 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
\r
2560 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
\r
2562 plist = get_next(plist);
\r
2564 VCS_update(padapter, psta);
\r
2567 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
2573 /* called > TSR LEVEL for USB or SDIO Interface*/
\r
2574 void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta)
\r
2576 u8 beacon_updated = _FALSE;
\r
2577 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
2578 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2582 if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
\r
2583 !psta->no_short_preamble_set) {
\r
2584 psta->no_short_preamble_set = 1;
\r
2585 pmlmepriv->num_sta_no_short_preamble++;
\r
2586 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
\r
2587 (pmlmepriv->num_sta_no_short_preamble == 1))
\r
2588 ieee802_11_set_beacons(hapd->iface);
\r
2593 if(!(psta->flags & WLAN_STA_SHORT_PREAMBLE))
\r
2595 if(!psta->no_short_preamble_set)
\r
2597 psta->no_short_preamble_set = 1;
\r
2599 pmlmepriv->num_sta_no_short_preamble++;
\r
2601 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
\r
2602 (pmlmepriv->num_sta_no_short_preamble == 1))
\r
2604 beacon_updated = _TRUE;
\r
2605 update_beacon(padapter, 0xFF, NULL, _TRUE);
\r
2612 if(psta->no_short_preamble_set)
\r
2614 psta->no_short_preamble_set = 0;
\r
2616 pmlmepriv->num_sta_no_short_preamble--;
\r
2618 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
\r
2619 (pmlmepriv->num_sta_no_short_preamble == 0))
\r
2621 beacon_updated = _TRUE;
\r
2622 update_beacon(padapter, 0xFF, NULL, _TRUE);
\r
2629 if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) {
\r
2630 psta->nonerp_set = 1;
\r
2631 pmlmepriv->num_sta_non_erp++;
\r
2632 if (pmlmepriv->num_sta_non_erp == 1)
\r
2633 ieee802_11_set_beacons(hapd->iface);
\r
2637 if(psta->flags & WLAN_STA_NONERP)
\r
2639 if(!psta->nonerp_set)
\r
2641 psta->nonerp_set = 1;
\r
2643 pmlmepriv->num_sta_non_erp++;
\r
2645 if (pmlmepriv->num_sta_non_erp == 1)
\r
2647 beacon_updated = _TRUE;
\r
2648 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
\r
2655 if(psta->nonerp_set)
\r
2657 psta->nonerp_set = 0;
\r
2659 pmlmepriv->num_sta_non_erp--;
\r
2661 if (pmlmepriv->num_sta_non_erp == 0)
\r
2663 beacon_updated = _TRUE;
\r
2664 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
\r
2672 if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) &&
\r
2673 !psta->no_short_slot_time_set) {
\r
2674 psta->no_short_slot_time_set = 1;
\r
2675 pmlmepriv->num_sta_no_short_slot_time++;
\r
2676 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
\r
2677 (pmlmepriv->num_sta_no_short_slot_time == 1))
\r
2678 ieee802_11_set_beacons(hapd->iface);
\r
2682 if(!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT))
\r
2684 if(!psta->no_short_slot_time_set)
\r
2686 psta->no_short_slot_time_set = 1;
\r
2688 pmlmepriv->num_sta_no_short_slot_time++;
\r
2690 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
\r
2691 (pmlmepriv->num_sta_no_short_slot_time == 1))
\r
2693 beacon_updated = _TRUE;
\r
2694 update_beacon(padapter, 0xFF, NULL, _TRUE);
\r
2701 if(psta->no_short_slot_time_set)
\r
2703 psta->no_short_slot_time_set = 0;
\r
2705 pmlmepriv->num_sta_no_short_slot_time--;
\r
2707 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
\r
2708 (pmlmepriv->num_sta_no_short_slot_time == 0))
\r
2710 beacon_updated = _TRUE;
\r
2711 update_beacon(padapter, 0xFF, NULL, _TRUE);
\r
2716 #ifdef CONFIG_80211N_HT
\r
2718 if (psta->flags & WLAN_STA_HT)
\r
2720 u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
\r
2722 DBG_871X("HT: STA " MAC_FMT " HT Capabilities "
\r
2723 "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);
\r
2725 if (psta->no_ht_set) {
\r
2726 psta->no_ht_set = 0;
\r
2727 pmlmepriv->num_sta_no_ht--;
\r
2730 if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
\r
2731 if (!psta->no_ht_gf_set) {
\r
2732 psta->no_ht_gf_set = 1;
\r
2733 pmlmepriv->num_sta_ht_no_gf++;
\r
2735 DBG_871X("%s STA " MAC_FMT " - no "
\r
2736 "greenfield, num of non-gf stations %d\n",
\r
2737 __FUNCTION__, MAC_ARG(psta->hwaddr),
\r
2738 pmlmepriv->num_sta_ht_no_gf);
\r
2741 if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {
\r
2742 if (!psta->ht_20mhz_set) {
\r
2743 psta->ht_20mhz_set = 1;
\r
2744 pmlmepriv->num_sta_ht_20mhz++;
\r
2746 DBG_871X("%s STA " MAC_FMT " - 20 MHz HT, "
\r
2747 "num of 20MHz HT STAs %d\n",
\r
2748 __FUNCTION__, MAC_ARG(psta->hwaddr),
\r
2749 pmlmepriv->num_sta_ht_20mhz);
\r
2755 if (!psta->no_ht_set) {
\r
2756 psta->no_ht_set = 1;
\r
2757 pmlmepriv->num_sta_no_ht++;
\r
2759 if(pmlmepriv->htpriv.ht_option == _TRUE) {
\r
2760 DBG_871X("%s STA " MAC_FMT
\r
2761 " - no HT, num of non-HT stations %d\n",
\r
2762 __FUNCTION__, MAC_ARG(psta->hwaddr),
\r
2763 pmlmepriv->num_sta_no_ht);
\r
2767 if (rtw_ht_operation_update(padapter) > 0)
\r
2769 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
\r
2770 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
\r
2773 #endif /* CONFIG_80211N_HT */
\r
2775 //update associcated stations cap.
\r
2776 associated_clients_update(padapter, beacon_updated);
\r
2778 DBG_871X("%s, updated=%d\n", __func__, beacon_updated);
\r
2782 u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta)
\r
2784 u8 beacon_updated = _FALSE;
\r
2785 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
2786 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2789 return beacon_updated;
\r
2791 if (psta->no_short_preamble_set) {
\r
2792 psta->no_short_preamble_set = 0;
\r
2793 pmlmepriv->num_sta_no_short_preamble--;
\r
2794 if (pmlmeext->cur_wireless_mode > WIRELESS_11B
\r
2795 && pmlmepriv->num_sta_no_short_preamble == 0)
\r
2797 beacon_updated = _TRUE;
\r
2798 update_beacon(padapter, 0xFF, NULL, _TRUE);
\r
2802 if (psta->nonerp_set) {
\r
2803 psta->nonerp_set = 0;
\r
2804 pmlmepriv->num_sta_non_erp--;
\r
2805 if (pmlmepriv->num_sta_non_erp == 0)
\r
2807 beacon_updated = _TRUE;
\r
2808 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
\r
2812 if (psta->no_short_slot_time_set) {
\r
2813 psta->no_short_slot_time_set = 0;
\r
2814 pmlmepriv->num_sta_no_short_slot_time--;
\r
2815 if (pmlmeext->cur_wireless_mode > WIRELESS_11B
\r
2816 && pmlmepriv->num_sta_no_short_slot_time == 0)
\r
2818 beacon_updated = _TRUE;
\r
2819 update_beacon(padapter, 0xFF, NULL, _TRUE);
\r
2823 #ifdef CONFIG_80211N_HT
\r
2825 if (psta->no_ht_gf_set) {
\r
2826 psta->no_ht_gf_set = 0;
\r
2827 pmlmepriv->num_sta_ht_no_gf--;
\r
2830 if (psta->no_ht_set) {
\r
2831 psta->no_ht_set = 0;
\r
2832 pmlmepriv->num_sta_no_ht--;
\r
2835 if (psta->ht_20mhz_set) {
\r
2836 psta->ht_20mhz_set = 0;
\r
2837 pmlmepriv->num_sta_ht_20mhz--;
\r
2840 if (rtw_ht_operation_update(padapter) > 0)
\r
2842 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
\r
2843 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
\r
2846 #endif /* CONFIG_80211N_HT */
\r
2848 //update associcated stations cap.
\r
2849 //associated_clients_update(padapter, beacon_updated); //move it to avoid deadlock
\r
2851 DBG_871X("%s, updated=%d\n", __func__, beacon_updated);
\r
2853 return beacon_updated;
\r
2857 u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason)
\r
2860 u8 beacon_updated = _FALSE;
\r
2861 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
2862 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2863 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2866 return beacon_updated;
\r
2868 if (active == _TRUE)
\r
2870 #ifdef CONFIG_80211N_HT
\r
2871 //tear down Rx AMPDU
\r
2872 send_delba(padapter, 0, psta->hwaddr);// recipient
\r
2874 //tear down TX AMPDU
\r
2875 send_delba(padapter, 1, psta->hwaddr);// // originator
\r
2877 #endif //CONFIG_80211N_HT
\r
2879 issue_deauth(padapter, psta->hwaddr, reason);
\r
2882 psta->htpriv.agg_enable_bitmap = 0x0;//reset
\r
2883 psta->htpriv.candidate_tid_bitmap = 0x0;//reset
\r
2886 //report_del_sta_event(padapter, psta->hwaddr, reason);
\r
2888 //clear cam entry / key
\r
2889 rtw_clearstakey_cmd(padapter, psta, _TRUE);
\r
2892 _enter_critical_bh(&psta->lock, &irqL);
\r
2893 psta->state &= ~_FW_LINKED;
\r
2894 _exit_critical_bh(&psta->lock, &irqL);
\r
2896 #ifdef CONFIG_IOCTL_CFG80211
\r
2898 #ifdef COMPAT_KERNEL_RELEASE
\r
2899 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
\r
2900 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
\r
2901 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
\r
2902 #else //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
\r
2903 /* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */
\r
2904 #endif //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
\r
2906 #endif //CONFIG_IOCTL_CFG80211
\r
2908 rtw_indicate_sta_disassoc_event(padapter, psta);
\r
2911 report_del_sta_event(padapter, psta->hwaddr, reason);
\r
2913 beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
\r
2915 _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
2916 rtw_free_stainfo(padapter, psta);
\r
2917 _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
2920 return beacon_updated;
\r
2924 int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)
\r
2927 _list *phead, *plist;
\r
2929 struct sta_info *psta = NULL;
\r
2930 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2931 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2932 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
2933 u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
\r
2935 if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
\r
2938 DBG_871X(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
\r
2939 FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
\r
2941 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
2942 phead = &pstapriv->asoc_list;
\r
2943 plist = get_next(phead);
\r
2945 /* for each sta in asoc_queue */
\r
2946 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
\r
2948 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
\r
2949 plist = get_next(plist);
\r
2951 issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);
\r
2952 psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
\r
2954 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
2956 issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);
\r
2961 int rtw_sta_flush(_adapter *padapter)
\r
2964 _list *phead, *plist;
\r
2966 struct sta_info *psta = NULL;
\r
2967 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2968 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2969 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
2970 u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
\r
2972 DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
\r
2974 if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
\r
2978 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
2979 phead = &pstapriv->asoc_list;
\r
2980 plist = get_next(phead);
\r
2982 //free sta asoc_queue
\r
2983 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
\r
2985 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
\r
2987 plist = get_next(plist);
\r
2989 rtw_list_delete(&psta->asoc_list);
\r
2990 pstapriv->asoc_list_cnt--;
\r
2992 //_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
2993 ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING);
\r
2994 //_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
2996 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
2999 issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
\r
3001 associated_clients_update(padapter, _TRUE);
\r
3007 /* called > TSR LEVEL for USB or SDIO Interface*/
\r
3008 void sta_info_update(_adapter *padapter, struct sta_info *psta)
\r
3010 int flags = psta->flags;
\r
3011 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
3015 if(WLAN_STA_WME&flags)
\r
3016 psta->qos_option = 1;
\r
3018 psta->qos_option = 0;
\r
3020 if(pmlmepriv->qospriv.qos_option == 0)
\r
3021 psta->qos_option = 0;
\r
3024 #ifdef CONFIG_80211N_HT
\r
3025 //update 802.11n ht cap.
\r
3026 if(WLAN_STA_HT&flags)
\r
3028 psta->htpriv.ht_option = _TRUE;
\r
3029 psta->qos_option = 1;
\r
3033 psta->htpriv.ht_option = _FALSE;
\r
3036 if(pmlmepriv->htpriv.ht_option == _FALSE)
\r
3037 psta->htpriv.ht_option = _FALSE;
\r
3040 #ifdef CONFIG_80211AC_VHT
\r
3041 //update 802.11AC vht cap.
\r
3042 if(WLAN_STA_VHT&flags)
\r
3044 psta->vhtpriv.vht_option = _TRUE;
\r
3048 psta->vhtpriv.vht_option = _FALSE;
\r
3051 if(pmlmepriv->vhtpriv.vht_option == _FALSE)
\r
3052 psta->vhtpriv.vht_option = _FALSE;
\r
3056 update_sta_info_apmode(padapter, psta);
\r
3061 /* called >= TSR LEVEL for USB or SDIO Interface*/
\r
3062 void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta)
\r
3064 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
3065 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
3067 if(psta->state & _FW_LINKED)
\r
3069 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
\r
3072 add_RATid(padapter, psta, 0);//DM_RATR_STA_INIT
\r
3075 /* restore hw setting from sw data structures */
\r
3076 void rtw_ap_restore_network(_adapter *padapter)
\r
3078 struct mlme_priv *mlmepriv = &padapter->mlmepriv;
\r
3079 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
3080 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
3081 struct sta_priv * pstapriv = &padapter->stapriv;
\r
3082 struct sta_info *psta;
\r
3083 struct security_priv* psecuritypriv=&(padapter->securitypriv);
\r
3085 _list *phead, *plist;
\r
3086 u8 chk_alive_num = 0;
\r
3087 char chk_alive_list[NUM_STA];
\r
3090 rtw_setopmode_cmd(padapter, Ndis802_11APMode,_FALSE);
\r
3092 set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
\r
3094 start_bss_network(padapter, (u8*)&mlmepriv->cur_network.network);
\r
3096 if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
\r
3097 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
\r
3099 /* restore group key, WEP keys is restored in ips_leave() */
\r
3100 rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0,_FALSE);
\r
3103 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
3105 phead = &pstapriv->asoc_list;
\r
3106 plist = get_next(phead);
\r
3108 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
\r
3109 int stainfo_offset;
\r
3111 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
\r
3112 plist = get_next(plist);
\r
3114 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
\r
3115 if (stainfo_offset_valid(stainfo_offset)) {
\r
3116 chk_alive_list[chk_alive_num++] = stainfo_offset;
\r
3120 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
\r
3122 for (i = 0; i < chk_alive_num; i++) {
\r
3123 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
\r
3125 if (psta == NULL) {
\r
3126 DBG_871X(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));
\r
3127 } else if (psta->state &_FW_LINKED) {
\r
3128 rtw_sta_media_status_rpt(padapter, psta, 1);
\r
3129 Update_RA_Entry(padapter, psta);
\r
3131 /* per sta pairwise key and settings */
\r
3132 if( (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
\r
3133 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
\r
3135 rtw_setstakey_cmd(padapter, psta, _TRUE,_FALSE);
\r
3142 void start_ap_mode(_adapter *padapter)
\r
3145 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
3146 struct sta_priv *pstapriv = &padapter->stapriv;
\r
3147 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
3148 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
\r
3150 pmlmepriv->update_bcn = _FALSE;
\r
3152 //init_mlme_ap_info(padapter);
\r
3153 pmlmeext->bstart_bss = _FALSE;
\r
3155 pmlmepriv->num_sta_non_erp = 0;
\r
3157 pmlmepriv->num_sta_no_short_slot_time = 0;
\r
3159 pmlmepriv->num_sta_no_short_preamble = 0;
\r
3161 pmlmepriv->num_sta_ht_no_gf = 0;
\r
3162 #ifdef CONFIG_80211N_HT
\r
3163 pmlmepriv->num_sta_no_ht = 0;
\r
3164 #endif //CONFIG_80211N_HT
\r
3165 pmlmepriv->num_sta_ht_20mhz = 0;
\r
3167 pmlmepriv->olbc = _FALSE;
\r
3169 pmlmepriv->olbc_ht = _FALSE;
\r
3171 #ifdef CONFIG_80211N_HT
\r
3172 pmlmepriv->ht_op_mode = 0;
\r
3175 for(i=0; i<NUM_STA; i++)
\r
3176 pstapriv->sta_aid[i] = NULL;
\r
3178 pmlmepriv->wps_beacon_ie = NULL;
\r
3179 pmlmepriv->wps_probe_resp_ie = NULL;
\r
3180 pmlmepriv->wps_assoc_resp_ie = NULL;
\r
3182 pmlmepriv->p2p_beacon_ie = NULL;
\r
3183 pmlmepriv->p2p_probe_resp_ie = NULL;
\r
3187 _rtw_init_listhead(&(pacl_list->acl_node_q.queue));
\r
3188 pacl_list->num = 0;
\r
3189 pacl_list->mode = 0;
\r
3190 for(i = 0; i < NUM_ACL; i++)
\r
3192 _rtw_init_listhead(&pacl_list->aclnode[i].list);
\r
3193 pacl_list->aclnode[i].valid = _FALSE;
\r
3198 void stop_ap_mode(_adapter *padapter)
\r
3201 _list *phead, *plist;
\r
3202 struct rtw_wlan_acl_node *paclnode;
\r
3203 struct sta_info *psta=NULL;
\r
3204 struct sta_priv *pstapriv = &padapter->stapriv;
\r
3205 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
3206 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
3207 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
\r
3208 _queue *pacl_node_q =&pacl_list->acl_node_q;
\r
3210 pmlmepriv->update_bcn = _FALSE;
\r
3211 pmlmeext->bstart_bss = _FALSE;
\r
3212 //_rtw_spinlock_free(&pmlmepriv->bcn_update_lock);
\r
3214 //reset and init security priv , this can refine with rtw_reset_securitypriv
\r
3215 _rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv));
\r
3216 padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
\r
3217 padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
\r
3220 _enter_critical_bh(&(pacl_node_q->lock), &irqL);
\r
3221 phead = get_list_head(pacl_node_q);
\r
3222 plist = get_next(phead);
\r
3223 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
\r
3225 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
\r
3226 plist = get_next(plist);
\r
3228 if(paclnode->valid == _TRUE)
\r
3230 paclnode->valid = _FALSE;
\r
3232 rtw_list_delete(&paclnode->list);
\r
3234 pacl_list->num--;
\r
3237 _exit_critical_bh(&(pacl_node_q->lock), &irqL);
\r
3239 DBG_871X("%s, free acl_node_queue, num=%d\n", __func__, pacl_list->num);
\r
3241 rtw_sta_flush(padapter);
\r
3243 //free_assoc_sta_resources
\r
3244 rtw_free_all_stainfo(padapter);
\r
3246 psta = rtw_get_bcmc_stainfo(padapter);
\r
3247 _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
3248 rtw_free_stainfo(padapter, psta);
\r
3249 _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
3251 rtw_init_bcmc_stainfo(padapter);
\r
3253 rtw_free_mlme_priv_ie_data(pmlmepriv);
\r
3255 #ifdef CONFIG_BT_COEXIST
\r
3256 rtw_btcoex_MediaStatusNotify(padapter, 0); //disconnect
\r
3261 #endif //CONFIG_NATIVEAP_MLME
\r
3263 #ifdef CONFIG_CONCURRENT_MODE
\r
3264 void concurrent_set_ap_chbw(_adapter *padapter, u8 channel, u8 channel_offset, u8 bwmode)
\r
3268 u8 cur_channel, cur_bwmode, cur_ch_offset, change_band;
\r
3269 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
3270 WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
\r
3271 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
3272 struct HT_info_element *pht_info=NULL;
\r
3274 cur_channel = channel;
\r
3275 cur_bwmode = bwmode;
\r
3276 cur_ch_offset = channel_offset;
\r
3277 change_band = _FALSE;
\r
3279 p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
\r
3282 pht_info = (struct HT_info_element *)(p+2);
\r
3286 if(!check_buddy_fwstate(padapter, _FW_LINKED|_FW_UNDER_LINKING|_FW_UNDER_SURVEY))
\r
3288 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
\r
3290 else if(check_buddy_fwstate(padapter, _FW_LINKED)==_TRUE)
\r
3292 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;
\r
3293 struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
\r
3295 //To sync cur_channel/cur_bwmode/cur_ch_offset with buddy adapter
\r
3296 DBG_871X(ADPT_FMT" is at linked state\n", ADPT_ARG(pbuddy_adapter));
\r
3297 DBG_871X(ADPT_FMT": CH=%d, BW=%d, offset=%d\n", ADPT_ARG(pbuddy_adapter), pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);
\r
3298 DBG_871X(ADPT_FMT": CH=%d, BW=%d, offset=%d\n", ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
\r
3300 if((cur_channel <= 14 && pbuddy_mlmeext->cur_channel >= 36) ||
\r
3301 (cur_channel >= 36 && pbuddy_mlmeext->cur_channel <= 14))
\r
3302 change_band = _TRUE;
\r
3304 cur_channel = pbuddy_mlmeext->cur_channel;
\r
3306 #ifdef CONFIG_80211AC_VHT
\r
3307 if(cur_bwmode == CHANNEL_WIDTH_80)
\r
3309 u8 *pvht_cap_ie, *pvht_op_ie;
\r
3310 int vht_cap_ielen, vht_op_ielen;
\r
3312 pvht_cap_ie = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTCapability, &vht_cap_ielen, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
\r
3313 pvht_op_ie = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTOperation, &vht_op_ielen, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
\r
3315 if(pbuddy_mlmeext->cur_channel <= 14) // downgrade to 20/40Mhz
\r
3317 //modify vht cap ie
\r
3318 if( pvht_cap_ie && vht_cap_ielen)
\r
3320 SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvht_cap_ie+2, 0);
\r
3323 //modify vht op ie
\r
3324 if( pvht_op_ie && vht_op_ielen)
\r
3326 SET_VHT_OPERATION_ELE_CHL_WIDTH(pvht_op_ie+2, 0); //change to 20/40Mhz
\r
3327 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pvht_op_ie+2, 0);
\r
3328 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(pvht_op_ie+2, 0);
\r
3329 //SET_VHT_OPERATION_ELE_BASIC_MCS_SET(p+2, 0xFFFF);
\r
3330 cur_bwmode = CHANNEL_WIDTH_40;
\r
3337 cur_bwmode = CHANNEL_WIDTH_80;
\r
3339 if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||
\r
3340 pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80)
\r
3342 cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
\r
3344 else if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_20)
\r
3346 cur_ch_offset = rtw_get_offset_by_ch(cur_channel);
\r
3349 //modify ht info ie
\r
3351 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
\r
3353 switch(cur_ch_offset)
\r
3355 case HAL_PRIME_CHNL_OFFSET_LOWER:
\r
3357 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
\r
3358 //cur_bwmode = CHANNEL_WIDTH_40;
\r
3360 case HAL_PRIME_CHNL_OFFSET_UPPER:
\r
3362 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
\r
3363 //cur_bwmode = CHANNEL_WIDTH_40;
\r
3365 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
\r
3368 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
\r
3369 cur_bwmode = CHANNEL_WIDTH_20;
\r
3370 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
\r
3374 //modify vht op ie
\r
3375 center_freq = rtw_get_center_ch(cur_channel, cur_bwmode, HAL_PRIME_CHNL_OFFSET_LOWER);
\r
3376 if( pvht_op_ie && vht_op_ielen)
\r
3377 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pvht_op_ie+2, center_freq);
\r
3379 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
\r
3384 #endif //CONFIG_80211AC_VHT
\r
3386 if(cur_bwmode == CHANNEL_WIDTH_40)
\r
3389 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
\r
3391 if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||
\r
3392 pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80)
\r
3394 cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;
\r
3396 //to update cur_ch_offset value in beacon
\r
3399 switch(cur_ch_offset)
\r
3401 case HAL_PRIME_CHNL_OFFSET_LOWER:
\r
3402 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
\r
3404 case HAL_PRIME_CHNL_OFFSET_UPPER:
\r
3405 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
\r
3407 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
\r
3414 else if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_20)
\r
3416 cur_ch_offset = rtw_get_offset_by_ch(cur_channel);
\r
3418 switch(cur_ch_offset)
\r
3420 case HAL_PRIME_CHNL_OFFSET_LOWER:
\r
3422 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
\r
3423 cur_bwmode = CHANNEL_WIDTH_40;
\r
3425 case HAL_PRIME_CHNL_OFFSET_UPPER:
\r
3427 pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
\r
3428 cur_bwmode = CHANNEL_WIDTH_40;
\r
3430 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
\r
3433 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
\r
3434 cur_bwmode = CHANNEL_WIDTH_20;
\r
3435 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
\r
3441 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
\r
3446 set_channel_bwmode(padapter, cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
\r
3449 // to update channel value in beacon
\r
3450 pnetwork->Configuration.DSConfig = cur_channel;
\r
3451 p = rtw_get_ie((pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
\r
3453 *(p + 2) = cur_channel;
\r
3456 pht_info->primary_channel = cur_channel;
\r
3459 DBG_871X(FUNC_ADPT_FMT" CH=%d, BW=%d, offset=%d\n", FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
\r
3461 pmlmeext->cur_channel = cur_channel;
\r
3462 pmlmeext->cur_bwmode = cur_bwmode;
\r
3463 pmlmeext->cur_ch_offset = cur_ch_offset;
\r
3465 //buddy interface band is different from current interface, update ERP, support rate, ext support rate IE
\r
3466 if(change_band == _TRUE)
\r
3467 change_band_update_ie(padapter, pnetwork);
\r
3470 #endif //CONFIG_CONCURRENT_MODE
\r
3472 #endif //CONFIG_AP_MODE
\r