wifi: renew patch drivers/net/wireless
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rtl8723bs / core / rtw_ap.c
1 /******************************************************************************\r
2  *\r
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.\r
4  *                                        \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
8  *\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
12  * more details.\r
13  *\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
17  *\r
18  *\r
19  ******************************************************************************/\r
20 #define _RTW_AP_C_\r
21 \r
22 #include <drv_types.h>\r
23 \r
24 \r
25 #ifdef CONFIG_AP_MODE\r
26 \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
32 \r
33 void init_mlme_ap_info(_adapter *padapter)\r
34 {\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
39         \r
40 \r
41         _rtw_spinlock_init(&pmlmepriv->bcn_update_lock);        \r
42 \r
43         //for ACL \r
44         _rtw_init_queue(&pacl_list->acl_node_q);\r
45 \r
46         //pmlmeext->bstart_bss = _FALSE;\r
47 \r
48         start_ap_mode(padapter);\r
49 }\r
50 \r
51 void free_mlme_ap_info(_adapter *padapter)\r
52 {\r
53         _irqL irqL;\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
59 \r
60         //stop_ap_mode(padapter);\r
61 \r
62         pmlmepriv->update_bcn = _FALSE;\r
63         pmlmeext->bstart_bss = _FALSE;  \r
64         \r
65         rtw_sta_flush(padapter);\r
66 \r
67         pmlmeinfo->state = _HW_STATE_NOLINK_;\r
68 \r
69         //free_assoc_sta_resources\r
70         rtw_free_all_stainfo(padapter);\r
71 \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
77         \r
78 \r
79         _rtw_spinlock_free(&pmlmepriv->bcn_update_lock);\r
80         \r
81 }\r
82 \r
83 static void update_BCNTIM(_adapter *padapter)\r
84 {\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
90 \r
91         //DBG_871X("%s\n", __FUNCTION__);\r
92         \r
93         //update TIM IE\r
94         //if(pstapriv->tim_bitmap)\r
95         if(_TRUE)\r
96         {\r
97                 u8 *p, *dst_ie, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;\r
98                 u16 tim_bitmap_le;\r
99                 uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;        \r
100         \r
101                 tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);\r
102 \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
105                 {\r
106                         tim_ielen += 2;\r
107                         \r
108                         premainder_ie = p+tim_ielen;\r
109 \r
110                         tim_ie_offset = (sint)(p -pie);\r
111                         \r
112                         remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;\r
113 \r
114                         //append TIM IE from dst_ie offset\r
115                         dst_ie = p;\r
116                 }\r
117                 else\r
118                 {\r
119                         tim_ielen = 0;\r
120 \r
121                         //calucate head_len             \r
122                         offset = _FIXED_IE_LENGTH_;\r
123 \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
126                         if (p != NULL)\r
127                                 offset += tmp_len+2;\r
128 \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
131                         if (p !=  NULL) \r
132                         {                       \r
133                                 offset += tmp_len+2;\r
134                         }\r
135 \r
136                         //DS Parameter Set IE, len=3    \r
137                         offset += 3;\r
138 \r
139                         premainder_ie = pie + offset;\r
140 \r
141                         remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;      \r
142 \r
143                         //append TIM IE from offset\r
144                         dst_ie = pie + offset;\r
145                         \r
146                 }\r
147 \r
148                 \r
149                 if(remainder_ielen>0)\r
150                 {\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
154                 }               \r
155                 \r
156                 *dst_ie++=_TIM_IE_;\r
157 \r
158                 if((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fe))                      \r
159                         tim_ielen = 5;\r
160                 else\r
161                         tim_ielen = 4;\r
162 \r
163                 *dst_ie++= tim_ielen;\r
164                 \r
165                 *dst_ie++=0;//DTIM count\r
166                 *dst_ie++=1;//DTIM peroid\r
167                 \r
168                 if(pstapriv->tim_bitmap&BIT(0))//for bc/mc frames\r
169                         *dst_ie++ = BIT(0);//bitmap ctrl \r
170                 else\r
171                         *dst_ie++ = 0;\r
172 \r
173                 if(tim_ielen==4)\r
174                 {\r
175                         u8 pvb=0;\r
176                         \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
181                         else\r
182                                 pvb = (u8)tim_bitmap_le;\r
183 \r
184                         *dst_ie++ = pvb;\r
185                         \r
186                 }       \r
187                 else if(tim_ielen==5)\r
188                 {\r
189                         _rtw_memcpy(dst_ie, &tim_bitmap_le, 2);\r
190                         dst_ie+=2;                              \r
191                 }       \r
192                 \r
193                 //copy remainder IE\r
194                 if(pbackup_remainder_ie)\r
195                 {\r
196                         _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);\r
197 \r
198                         rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
199                 }       \r
200 \r
201                 offset =  (uint)(dst_ie - pie);\r
202                 pnetwork_mlmeext->IELength = offset + remainder_ielen;\r
203         \r
204         }\r
205 }\r
206 \r
207 void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)\r
208 {\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
214 \r
215         for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;)\r
216         {\r
217                 pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);\r
218 \r
219                 if (pIE->ElementID > index)\r
220                 {\r
221                         break;\r
222                 }\r
223                 else if(pIE->ElementID == index) // already exist the same IE\r
224                 {\r
225                         p = (u8 *)pIE;\r
226                         ielen = pIE->Length;\r
227                         bmatch = _TRUE;\r
228                         break;\r
229                 }\r
230 \r
231                 p = (u8 *)pIE;\r
232                 ielen = pIE->Length;\r
233                 i += (pIE->Length + 2);\r
234         }\r
235 \r
236         if (p != NULL && ielen>0)\r
237         {\r
238                 ielen += 2;\r
239                 \r
240                 premainder_ie = p+ielen;\r
241 \r
242                 ie_offset = (sint)(p -pie);\r
243                 \r
244                 remainder_ielen = pnetwork->IELength - ie_offset - ielen;\r
245 \r
246                 if(bmatch)\r
247                         dst_ie = p;\r
248                 else\r
249                         dst_ie = (p+ielen);\r
250         }\r
251 \r
252         if(remainder_ielen>0)\r
253         {\r
254                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
255                 if(pbackup_remainder_ie && premainder_ie)\r
256                         _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
257         }\r
258 \r
259         *dst_ie++=index;\r
260         *dst_ie++=len;\r
261 \r
262         _rtw_memcpy(dst_ie, data, len);\r
263         dst_ie+=len;\r
264 \r
265         //copy remainder IE\r
266         if(pbackup_remainder_ie)\r
267         {\r
268                 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);\r
269 \r
270                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
271         }\r
272 \r
273         offset =  (uint)(dst_ie - pie);\r
274         pnetwork->IELength = offset + remainder_ielen;\r
275 }\r
276 \r
277 void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)\r
278 {\r
279         u8 *p, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;\r
280         uint offset, ielen, ie_offset, remainder_ielen = 0;\r
281         u8      *pie = pnetwork->IEs;\r
282 \r
283         p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);\r
284         if (p != NULL && ielen>0)\r
285         {\r
286                 ielen += 2;\r
287                 \r
288                 premainder_ie = p+ielen;\r
289 \r
290                 ie_offset = (sint)(p -pie);\r
291                 \r
292                 remainder_ielen = pnetwork->IELength - ie_offset - ielen;\r
293 \r
294                 dst_ie = p;\r
295         }\r
296         else {\r
297                 return;\r
298         }\r
299 \r
300         if(remainder_ielen>0)\r
301         {\r
302                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
303                 if(pbackup_remainder_ie && premainder_ie)\r
304                         _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
305         }\r
306 \r
307         //copy remainder IE\r
308         if(pbackup_remainder_ie)\r
309         {\r
310                 _rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);\r
311 \r
312                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
313         }\r
314 \r
315         offset =  (uint)(dst_ie - pie);\r
316         pnetwork->IELength = offset + remainder_ielen;\r
317 }\r
318 \r
319 \r
320 u8 chk_sta_is_alive(struct sta_info *psta);\r
321 u8 chk_sta_is_alive(struct sta_info *psta)\r
322 {\r
323         u8 ret = _FALSE;\r
324         #ifdef DBG_EXPIRATION_CHK\r
325         DBG_871X("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"\r
326                 , MAC_ARG(psta->hwaddr)\r
327                 , psta->rssi_stat.UndecoratedSmoothedPWDB\r
328                 //, STA_RX_PKTS_ARG(psta)\r
329                 , STA_RX_PKTS_DIFF_ARG(psta)\r
330                 , psta->expire_to\r
331                 , psta->state&WIFI_SLEEP_STATE?"PS, ":""\r
332                 , psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":""\r
333                 , psta->sleepq_len\r
334         );\r
335         #endif\r
336 \r
337         //if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta))\r
338         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
339         {\r
340                 #if 0\r
341                 if(psta->state&WIFI_SLEEP_STATE)\r
342                         ret = _TRUE;\r
343                 #endif\r
344         }\r
345         else\r
346         {\r
347                 ret = _TRUE;\r
348         }\r
349 \r
350         sta_update_last_rx_pkts(psta);\r
351 \r
352         return ret;\r
353 }\r
354 \r
355 void    expire_timeout_chk(_adapter *padapter)\r
356 {\r
357         _irqL irqL;\r
358         _list   *phead, *plist;\r
359         u8 updated = _FALSE;\r
360         struct sta_info *psta=NULL;     \r
361         struct sta_priv *pstapriv = &padapter->stapriv;\r
362         u8 chk_alive_num = 0;\r
363         char chk_alive_list[NUM_STA];\r
364         int i;\r
365 \r
366 \r
367         _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
368         \r
369         phead = &pstapriv->auth_list;\r
370         plist = get_next(phead);\r
371         \r
372         //check auth_queue\r
373         #ifdef DBG_EXPIRATION_CHK\r
374         if (rtw_end_of_queue_search(phead, plist) == _FALSE) {\r
375                 DBG_871X(FUNC_NDEV_FMT" auth_list, cnt:%u\n"\r
376                         , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt);\r
377         }\r
378         #endif\r
379         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
380         {\r
381                 psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);\r
382 \r               plist = get_next(plist);\r
383 \r
384 \r
385 #ifdef CONFIG_ATMEL_RC_PATCH\r
386                 if (_TRUE == _rtw_memcmp((void *)(pstapriv->atmel_rc_pattern), (void *)(psta->hwaddr), ETH_ALEN))\r
387                         continue;\r
388                 if (psta->flag_atmel_rc)\r
389                         continue;\r
390 #endif\r
391                 if(psta->expire_to>0)\r
392                 {\r
393                         psta->expire_to--;\r
394                         if (psta->expire_to == 0)\r
395                         {\r
396                                 rtw_list_delete(&psta->auth_list);\r
397                                 pstapriv->auth_list_cnt--;\r
398                                 \r
399                                 DBG_871X("auth expire %02X%02X%02X%02X%02X%02X\n",\r
400                                         psta->hwaddr[0],psta->hwaddr[1],psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5]);\r
401                                 \r
402                                 _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
403                                 \r
404                                 _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);  \r
405                                 rtw_free_stainfo(padapter, psta);\r
406                                 _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);   \r
407                                 \r
408                                 _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
409                         }       \r
410                 }       \r
411                 \r
412         }\r
413 \r
414         _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);\r
415         psta = NULL;\r
416         \r
417 \r
418         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
419         \r
420         phead = &pstapriv->asoc_list;\r
421         plist = get_next(phead);\r
422 \r
423         //check asoc_queue\r
424         #ifdef DBG_EXPIRATION_CHK\r
425         if (rtw_end_of_queue_search(phead, plist) == _FALSE) {\r
426                 DBG_871X(FUNC_NDEV_FMT" asoc_list, cnt:%u\n"\r
427                         , FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->asoc_list_cnt);\r
428         }\r
429         #endif\r
430         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
431         {\r
432                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
433                 plist = get_next(plist);\r
434 #ifdef CONFIG_ATMEL_RC_PATCH\r
435                 DBG_871X("%s:%d  psta=%p, %02x,%02x||%02x,%02x  \n\n", __func__,  __LINE__,\r
436                         psta,pstapriv->atmel_rc_pattern[0], pstapriv->atmel_rc_pattern[5], psta->hwaddr[0], psta->hwaddr[5]);\r
437                 if (_TRUE == _rtw_memcmp((void *)pstapriv->atmel_rc_pattern, (void *)(psta->hwaddr), ETH_ALEN))\r
438                         continue;               \r
439                 if (psta->flag_atmel_rc)\r
440                         continue;\r
441                 DBG_871X("%s: debug line:%d \n", __func__, __LINE__);\r
442 #endif\r
443 #ifdef CONFIG_AUTO_AP_MODE\r
444                 if(psta->isrc)\r
445                         continue;\r
446 #endif\r
447                 if (chk_sta_is_alive(psta) || !psta->expire_to) {\r
448                         psta->expire_to = pstapriv->expire_to;\r
449                         psta->keep_alive_trycnt = 0;\r
450                         #ifdef CONFIG_TX_MCAST2UNI\r
451                         psta->under_exist_checking = 0;\r
452                         #endif  // CONFIG_TX_MCAST2UNI\r
453                 } else {\r
454                         psta->expire_to--;\r
455                 }\r
456 \r
457 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
458 #ifdef CONFIG_80211N_HT\r
459 #ifdef CONFIG_TX_MCAST2UNI\r
460                 if ( (psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking) ) {\r
461                         // check sta by delba(addba) for 11n STA \r
462                         // ToDo: use CCX report to check for all STAs\r
463                         //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
464                         \r
465                                 if ( psta->expire_to <= (pstapriv->expire_to - 50 ) ) {\r
466                                 DBG_871X("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);\r
467                                 psta->under_exist_checking = 0;\r
468                                 psta->expire_to = 0;\r
469                         } else if ( psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking==0)) {\r
470                                 DBG_871X("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);\r
471                                 psta->under_exist_checking = 1;\r
472                                 //tear down TX AMPDU\r
473                                 send_delba(padapter, 1, psta->hwaddr);// // originator\r
474                                 psta->htpriv.agg_enable_bitmap = 0x0;//reset\r
475                                 psta->htpriv.candidate_tid_bitmap = 0x0;//reset\r
476                         }\r
477                 }\r
478 #endif //CONFIG_TX_MCAST2UNI\r
479 #endif //CONFIG_80211N_HT\r
480 #endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
481 \r
482                 if (psta->expire_to <= 0)\r
483                 {\r
484                         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
485 \r
486                         if (padapter->registrypriv.wifi_spec == 1)\r
487                         {\r
488                                 psta->expire_to = pstapriv->expire_to;\r
489                                 continue;\r
490                         }\r
491 \r
492 #ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
493 #ifdef CONFIG_80211N_HT\r
494 \r
495 #define KEEP_ALIVE_TRYCNT (3)\r
496 \r
497                         if(psta->keep_alive_trycnt > 0 && psta->keep_alive_trycnt <= KEEP_ALIVE_TRYCNT)\r
498                         {                               \r
499                                 if(psta->state & WIFI_STA_ALIVE_CHK_STATE)\r
500                                         psta->state ^= WIFI_STA_ALIVE_CHK_STATE;\r
501                                 else\r
502                                         psta->keep_alive_trycnt = 0;\r
503                                 \r
504                         }\r
505                         else if((psta->keep_alive_trycnt > KEEP_ALIVE_TRYCNT) && !(psta->state & WIFI_STA_ALIVE_CHK_STATE))\r
506                         {\r
507                                 psta->keep_alive_trycnt = 0;\r
508                         }                       \r
509                         if((psta->htpriv.ht_option==_TRUE) && (psta->htpriv.ampdu_enable==_TRUE)) \r
510                         {\r
511                                 uint priority = 1; //test using BK\r
512                                 u8 issued=0;                            \r
513                 \r
514                                 //issued = (psta->htpriv.agg_enable_bitmap>>priority)&0x1;\r
515                                 issued |= (psta->htpriv.candidate_tid_bitmap>>priority)&0x1;\r
516 \r
517                                 if(0==issued)\r
518                                 {\r
519                                         if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE))\r
520                                         {\r
521                                                 psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);\r
522 \r
523                                                 if (psta->state & WIFI_SLEEP_STATE) \r
524                                                         psta->expire_to = 2; // 2x2=4 sec\r
525                                                 else\r
526                                                         psta->expire_to = 1; // 2 sec\r
527                                         \r
528                                                 psta->state |= WIFI_STA_ALIVE_CHK_STATE;\r
529                                         \r
530                                                 //add_ba_hdl(padapter, (u8*)paddbareq_parm);\r
531 \r
532                                                 DBG_871X("issue addba_req to check if sta alive, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);\r
533                                                 \r
534                                                 issue_action_BA(padapter, psta->hwaddr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)priority);              \r
535                 \r
536                                                 _set_timer(&psta->addba_retry_timer, ADDBA_TO);\r
537                                                 \r
538                                                 psta->keep_alive_trycnt++;                                              \r
539 \r
540                                                 continue;\r
541                                         }                       \r
542                                 }                                       \r
543                         }\r
544                         if(psta->keep_alive_trycnt > 0 && psta->state & WIFI_STA_ALIVE_CHK_STATE)\r
545                         {\r
546                                 psta->keep_alive_trycnt = 0;\r
547                                 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;\r
548                                 DBG_871X("change to another methods to check alive if staion is at ps mode\n");\r
549                         }       \r
550                         \r
551 #endif //CONFIG_80211N_HT\r
552 #endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK \r
553                         if (psta->state & WIFI_SLEEP_STATE) {\r
554                                 if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {\r
555                                         //to check if alive by another methods if staion is at ps mode.                                 \r
556                                         psta->expire_to = pstapriv->expire_to;\r
557                                         psta->state |= WIFI_STA_ALIVE_CHK_STATE;\r
558 \r
559                                         //DBG_871X("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->hwaddr));\r
560 \r
561                                         //to update bcn with tim_bitmap for this station\r
562                                         pstapriv->tim_bitmap |= BIT(psta->aid);\r
563                                         update_beacon(padapter, _TIM_IE_, NULL, _TRUE);\r
564 \r
565                                         if(!pmlmeext->active_keep_alive_check)\r
566                                                 continue;\r
567                                 }\r
568                         }\r
569                         #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
570                         if (pmlmeext->active_keep_alive_check) {\r
571                                 int stainfo_offset;\r
572 \r
573                                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);\r
574                                 if (stainfo_offset_valid(stainfo_offset)) {\r
575                                         chk_alive_list[chk_alive_num++] = stainfo_offset;\r
576                                 }\r
577 \r
578                                 continue;\r
579                         }\r
580                         #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */\r
581                         rtw_list_delete(&psta->asoc_list);\r
582                         pstapriv->asoc_list_cnt--;\r
583                         DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);\r
584                         updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING);\r
585                 }       \r
586                 else\r
587                 {\r
588                         /* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */\r
589                         if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)\r
590                                 && padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)\r
591                         ){\r
592                                 DBG_871X("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__\r
593                                         , MAC_ARG(psta->hwaddr)\r
594                                         , psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt);\r
595                                 wakeup_sta_to_xmit(padapter, psta);\r
596                         }\r
597                 }\r
598         }\r
599 \r
600         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
601 \r
602 #ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK\r
603 if (chk_alive_num) {\r
604 \r
605         u8 backup_oper_channel=0;\r
606         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
607         /* switch to correct channel of current network  before issue keep-alive frames */\r
608         if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {\r
609                 backup_oper_channel = rtw_get_oper_ch(padapter);\r
610                 SelectChannel(padapter, pmlmeext->cur_channel);\r
611         }\r
612 \r
613         /* issue null data to check sta alive*/\r
614         for (i = 0; i < chk_alive_num; i++) {\r
615                 int ret = _FAIL;\r
616 \r
617                 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);\r
618 #ifdef CONFIG_ATMEL_RC_PATCH\r
619                 if (_TRUE == _rtw_memcmp(  pstapriv->atmel_rc_pattern, psta->hwaddr, ETH_ALEN))\r
620                         continue;\r
621                 if (psta->flag_atmel_rc)\r
622                         continue;\r
623 #endif\r
624                 if(!(psta->state &_FW_LINKED))\r
625                         continue;               \r
626         \r
627                 if (psta->state & WIFI_SLEEP_STATE)\r
628                         ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);\r
629                 else\r
630                         ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);\r
631 \r
632                 psta->keep_alive_trycnt++;\r
633                 if (ret == _SUCCESS)\r
634                 {\r
635                         DBG_871X("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr));\r
636                         psta->expire_to = pstapriv->expire_to;\r
637                         psta->keep_alive_trycnt = 0;\r
638                         continue;\r
639                 }\r
640                 else if (psta->keep_alive_trycnt <= 3)\r
641                 {\r
642                         DBG_871X("ack check for asoc expire, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);\r
643                         psta->expire_to = 1;\r
644                         continue;\r
645                 }\r
646 \r
647                 psta->keep_alive_trycnt = 0;\r
648                 DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);\r
649                 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
650                 if (rtw_is_list_empty(&psta->asoc_list)==_FALSE) {\r
651                         rtw_list_delete(&psta->asoc_list);\r
652                         pstapriv->asoc_list_cnt--;\r
653                         updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING);\r
654                 }\r
655                 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
656 \r
657         }\r
658 \r
659         if (backup_oper_channel>0) /* back to the original operation channel */\r
660                 SelectChannel(padapter, backup_oper_channel);\r
661 }\r
662 #endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */\r
663 \r
664         associated_clients_update(padapter, updated);\r
665 }\r
666 \r
667 void add_RATid(_adapter *padapter, struct sta_info *psta, u8 rssi_level)\r
668 {       \r
669         int i;\r
670         u8 rf_type;\r
671         unsigned char sta_band = 0, shortGIrate = _FALSE;\r
672         unsigned int tx_ra_bitmap=0;\r
673         struct ht_priv  *psta_ht = NULL;\r
674         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
675         WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;\r
676 \r
677 #ifdef CONFIG_80211N_HT\r
678         if(psta)\r
679                 psta_ht = &psta->htpriv;\r
680         else\r
681                 return;\r
682 #endif //CONFIG_80211N_HT\r
683 \r
684         if(!(psta->state & _FW_LINKED))\r
685                 return;\r
686 \r
687 #if 0//gtest\r
688         if(get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)\r
689         {\r
690                 //is this a 2r STA?\r
691                 if((pstat->tx_ra_bitmap & 0x0ff00000) != 0 && !(priv->pshare->has_2r_sta & BIT(pstat->aid)))\r
692                 {\r
693                         priv->pshare->has_2r_sta |= BIT(pstat->aid);\r
694                         if(rtw_read16(padapter, 0x102501f6) != 0xffff)\r
695                         {\r
696                                 rtw_write16(padapter, 0x102501f6, 0xffff);\r
697                                 reset_1r_sta_RA(priv, 0xffff);\r
698                                 Switch_1SS_Antenna(priv, 3);\r
699                         }\r
700                 }\r
701                 else// bg or 1R STA? \r
702                 { \r
703                         if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && priv->pshare->has_2r_sta == 0)\r
704                         {\r
705                                 if(rtw_read16(padapter, 0x102501f6) != 0x7777)\r
706                                 { // MCS7 SGI\r
707                                         rtw_write16(padapter, 0x102501f6,0x7777);\r
708                                         reset_1r_sta_RA(priv, 0x7777);\r
709                                         Switch_1SS_Antenna(priv, 2);\r
710                                 }\r
711                         }\r
712                 }\r
713                 \r
714         }\r
715 \r
716         if ((pstat->rssi_level < 1) || (pstat->rssi_level > 3)) \r
717         {\r
718                 if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper)\r
719                         pstat->rssi_level = 1;\r
720                 else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) ||\r
721                         ((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) &&\r
722                         (pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) &&\r
723                         (pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))))\r
724                         pstat->rssi_level = 2;\r
725                 else\r
726                         pstat->rssi_level = 3;\r
727         }\r
728 \r
729         // rate adaptive by rssi\r
730         if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len)\r
731         {\r
732                 if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R))\r
733                 {\r
734                         switch (pstat->rssi_level) {\r
735                                 case 1:\r
736                                         pstat->tx_ra_bitmap &= 0x100f0000;\r
737                                         break;\r
738                                 case 2:\r
739                                         pstat->tx_ra_bitmap &= 0x100ff000;\r
740                                         break;\r
741                                 case 3:\r
742                                         if (priv->pshare->is_40m_bw)\r
743                                                 pstat->tx_ra_bitmap &= 0x100ff005;\r
744                                         else\r
745                                                 pstat->tx_ra_bitmap &= 0x100ff001;\r
746 \r
747                                         break;\r
748                         }\r
749                 }\r
750                 else \r
751                 {\r
752                         switch (pstat->rssi_level) {\r
753                                 case 1:\r
754                                         pstat->tx_ra_bitmap &= 0x1f0f0000;\r
755                                         break;\r
756                                 case 2:\r
757                                         pstat->tx_ra_bitmap &= 0x1f0ff000;\r
758                                         break;\r
759                                 case 3:\r
760                                         if (priv->pshare->is_40m_bw)\r
761                                                 pstat->tx_ra_bitmap &= 0x000ff005;\r
762                                         else\r
763                                                 pstat->tx_ra_bitmap &= 0x000ff001;\r
764 \r
765                                         break;\r
766                         }\r
767 \r
768                         // Don't need to mask high rates due to new rate adaptive parameters\r
769                         //if (pstat->is_broadcom_sta)           // use MCS12 as the highest rate vs. Broadcom sta\r
770                         //      pstat->tx_ra_bitmap &= 0x81ffffff;\r
771 \r
772                         // NIC driver will report not supporting MCS15 and MCS14 in asoc req\r
773                         //if (pstat->is_rtl8190_sta && !pstat->is_2t_mimo_sta)\r
774                         //      pstat->tx_ra_bitmap &= 0x83ffffff;              // if Realtek 1x2 sta, don't use MCS15 and MCS14\r
775                 }\r
776         }\r
777         else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat))\r
778         {\r
779                 switch (pstat->rssi_level) {\r
780                         case 1:\r
781                                 pstat->tx_ra_bitmap &= 0x00000f00;\r
782                                 break;\r
783                         case 2:\r
784                                 pstat->tx_ra_bitmap &= 0x00000ff0;\r
785                                 break;\r
786                         case 3:\r
787                                 pstat->tx_ra_bitmap &= 0x00000ff5;\r
788                                 break;\r
789                 }\r
790         }\r
791         else \r
792         {\r
793                 pstat->tx_ra_bitmap &= 0x0000000d;\r
794         }\r
795 \r
796         // disable tx short GI when station cannot rx MCS15(AP is 2T2R)\r
797         // disable tx short GI when station cannot rx MCS7 (AP is 1T2R or 1T1R)\r
798         // if there is only 1r STA and we are 2T2R, DO NOT mask SGI rate\r
799         if ((!(pstat->tx_ra_bitmap & 0x8000000) && (priv->pshare->has_2r_sta > 0) && (get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)) ||\r
800                  (!(pstat->tx_ra_bitmap & 0x80000) && (get_rf_mimo_mode(padapter) != RTL8712_RF_2T2R)))\r
801         {\r
802                 pstat->tx_ra_bitmap &= ~BIT(28);        \r
803         }\r
804 #endif\r
805 \r
806         rtw_hal_update_sta_rate_mask(padapter, psta);\r
807         tx_ra_bitmap = psta->ra_mask;\r
808 \r
809         shortGIrate = query_ra_short_GI(psta);\r
810 \r
811         if ( pcur_network->Configuration.DSConfig > 14 ) {\r
812                 \r
813                 if (tx_ra_bitmap & 0xffff000)\r
814                         sta_band |= WIRELESS_11_5N ;\r
815 \r
816                 if (tx_ra_bitmap & 0xff0)\r
817                         sta_band |= WIRELESS_11A;\r
818 \r
819                 // 5G band\r
820                 #ifdef CONFIG_80211AC_VHT\r
821                 if (psta->vhtpriv.vht_option)  {\r
822                         sta_band = WIRELESS_11_5AC;\r
823                 }               \r
824                 #endif\r
825                 \r
826         } else {\r
827                 if (tx_ra_bitmap & 0xffff000)\r
828                         sta_band |= WIRELESS_11_24N;\r
829 \r
830                 if (tx_ra_bitmap & 0xff0)\r
831                         sta_band |= WIRELESS_11G;\r
832 \r
833                 if (tx_ra_bitmap & 0x0f)\r
834                         sta_band |= WIRELESS_11B;\r
835         }\r
836 \r
837         psta->wireless_mode = sta_band;\r
838         psta->raid = rtw_hal_networktype_to_raid(padapter, psta);\r
839         \r
840         if (psta->aid < NUM_STA) \r
841         {\r
842                 u8      arg[4] = {0};\r
843 \r
844                 arg[0] = psta->mac_id;\r
845                 arg[1] = psta->raid;\r
846                 arg[2] = shortGIrate;\r
847                 arg[3] = psta->init_rate;\r
848 \r
849                 DBG_871X("%s=> mac_id:%d , raid:%d , shortGIrate=%d, bitmap=0x%x\n", \r
850                         __FUNCTION__ , psta->mac_id, psta->raid ,shortGIrate, tx_ra_bitmap);\r
851 \r
852                 rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);\r
853         }\r
854         else \r
855         {\r
856                 DBG_871X("station aid %d exceed the max number\n", psta->aid);\r
857         }\r
858 \r
859 }\r
860 \r
861 void update_bmc_sta(_adapter *padapter)\r
862 {\r
863         _irqL   irqL;\r
864         unsigned char   network_type;\r
865         int supportRateNum = 0;\r
866         unsigned int tx_ra_bitmap=0;\r
867         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
868         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
869         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);  \r
870         WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; \r
871         struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);\r
872 \r
873         if(psta)\r
874         {\r
875                 psta->aid = 0;//default set to 0\r
876                 //psta->mac_id = psta->aid+4;   \r
877                 psta->mac_id = psta->aid + 1;//mac_id=1 for bc/mc stainfo\r
878 \r
879                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;\r
880 \r
881                 psta->qos_option = 0;\r
882 #ifdef CONFIG_80211N_HT \r
883                 psta->htpriv.ht_option = _FALSE;\r
884 #endif //CONFIG_80211N_HT\r
885 \r
886                 psta->ieee8021x_blocked = 0;\r
887 \r
888                 _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));\r
889 \r
890                 //psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this.\r
891 \r
892                 //prepare for add_RATid         \r
893                 supportRateNum = rtw_get_rateset_len((u8*)&pcur_network->SupportedRates);\r
894                 network_type = rtw_check_network_type((u8*)&pcur_network->SupportedRates, supportRateNum, pcur_network->Configuration.DSConfig);\r
895                 if (IsSupportedTxCCK(network_type)) {\r
896                         network_type = WIRELESS_11B;\r
897                 }\r
898                 else if (network_type == WIRELESS_INVALID) { // error handling\r
899                         if ( pcur_network->Configuration.DSConfig > 14 )\r
900                                 network_type = WIRELESS_11A;\r
901                         else\r
902                                 network_type = WIRELESS_11B;\r
903                 }\r
904                 update_sta_basic_rate(psta, network_type);\r
905                 psta->wireless_mode = network_type;\r
906 \r
907                 rtw_hal_update_sta_rate_mask(padapter, psta);\r
908                 tx_ra_bitmap = psta->ra_mask;\r
909 \r
910                 psta->raid = rtw_hal_networktype_to_raid(padapter,psta);\r
911 \r
912                 //ap mode\r
913                 rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);\r
914 \r
915                 //if(pHalData->fw_ractrl == _TRUE)\r
916                 {\r
917                         u8      arg[4] = {0};\r
918 \r
919                         arg[0] = psta->mac_id;\r
920                         arg[1] = psta->raid;\r
921                         arg[2] = 0;\r
922                         arg[3] = psta->init_rate;\r
923 \r
924                         DBG_871X("%s=> mac_id:%d , raid:%d , bitmap=0x%x\n", \r
925                                 __FUNCTION__ , psta->mac_id, psta->raid , tx_ra_bitmap);\r
926 \r
927                         rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);\r
928                 }\r
929 \r
930                 rtw_sta_media_status_rpt(padapter, psta, 1);\r
931 \r
932                 _enter_critical_bh(&psta->lock, &irqL);\r
933                 psta->state = _FW_LINKED;\r
934                 _exit_critical_bh(&psta->lock, &irqL);\r
935 \r
936         }\r
937         else\r
938         {\r
939                 DBG_871X("add_RATid_bmc_sta error!\n");\r
940         }\r
941                 \r
942 }\r
943 \r
944 //notes:\r
945 //AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode \r
946 //MAC_ID = AID+1 for sta in ap/adhoc mode \r
947 //MAC_ID = 1 for bc/mc for sta/ap/adhoc\r
948 //MAC_ID = 0 for bssid for sta/ap/adhoc\r
949 //CAM_ID = //0~3 for default key, cmd_id=macid + 3, macid=aid+1;\r
950 \r
951 void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta)\r
952 {       \r
953         _irqL   irqL;\r
954         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
955         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
956         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
957 #ifdef CONFIG_80211N_HT\r
958         struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;\r
959         struct ht_priv  *phtpriv_sta = &psta->htpriv;\r
960 #endif //CONFIG_80211N_HT\r
961         //set intf_tag to if1\r
962         //psta->intf_tag = 0;\r
963 \r
964         DBG_871X("%s\n",__FUNCTION__);\r
965 \r
966         //psta->mac_id = psta->aid+4;\r
967         //psta->mac_id = psta->aid+1;//alloc macid when call rtw_alloc_stainfo(),\r
968                                                        //release macid when call rtw_free_stainfo()\r
969 \r
970         //ap mode\r
971         rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,psta,_TRUE);\r
972         \r
973         if(psecuritypriv->dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)\r
974                 psta->ieee8021x_blocked = _TRUE;\r
975         else\r
976                 psta->ieee8021x_blocked = _FALSE;\r
977         \r
978 \r
979         //update sta's cap\r
980         \r
981         //ERP\r
982         VCS_update(padapter, psta);\r
983 #ifdef CONFIG_80211N_HT \r
984         //HT related cap\r
985         if(phtpriv_sta->ht_option)\r
986         {\r
987                 //check if sta supports rx ampdu\r
988                 phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;\r
989 \r
990                 //check if sta support s Short GI 20M\r
991                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))\r
992                 {\r
993                         phtpriv_sta->sgi_20m = _TRUE;\r
994                 }\r
995                 //check if sta support s Short GI 40M\r
996                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))\r
997                 {\r
998                         phtpriv_sta->sgi_40m = _TRUE;\r
999                 }\r
1000 \r
1001                 // bwmode\r
1002                 if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))\r
1003                 {\r
1004                         phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;\r
1005                         psta->bw_mode = CHANNEL_WIDTH_40;\r
1006                 }\r
1007                 else\r
1008                 {\r
1009                         psta->bw_mode = CHANNEL_WIDTH_20;\r
1010                 }\r
1011 \r
1012                 psta->qos_option = _TRUE;\r
1013         }\r
1014         else\r
1015         {\r
1016                 phtpriv_sta->ampdu_enable = _FALSE;\r
1017                 \r
1018                 phtpriv_sta->sgi_20m = _FALSE;\r
1019                 phtpriv_sta->sgi_40m = _FALSE;\r
1020                 psta->bw_mode = CHANNEL_WIDTH_20;\r
1021                 phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
1022         }\r
1023 \r
1024         //Rx AMPDU\r
1025         send_delba(padapter, 0, psta->hwaddr);// recipient\r
1026         \r
1027         //TX AMPDU\r
1028         send_delba(padapter, 1, psta->hwaddr);// // originator\r
1029         phtpriv_sta->agg_enable_bitmap = 0x0;//reset\r
1030         phtpriv_sta->candidate_tid_bitmap = 0x0;//reset\r
1031 #endif //CONFIG_80211N_HT\r
1032 \r
1033 #ifdef CONFIG_80211AC_VHT\r
1034         update_sta_vht_info_apmode(padapter, psta);\r
1035 #endif\r
1036 \r
1037         //todo: init other variables\r
1038         \r
1039         _rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));\r
1040 \r
1041 \r
1042         //add ratid\r
1043         //add_RATid(padapter, psta);//move to ap_sta_info_defer_update()\r
1044 \r
1045 \r
1046         _enter_critical_bh(&psta->lock, &irqL);\r
1047         psta->state |= _FW_LINKED;\r
1048         _exit_critical_bh(&psta->lock, &irqL);\r
1049         \r
1050 \r
1051 }\r
1052 \r
1053 static void update_hw_ht_param(_adapter *padapter)\r
1054 {\r
1055         unsigned char           max_AMPDU_len;\r
1056         unsigned char           min_MPDU_spacing;\r
1057         struct registry_priv     *pregpriv = &padapter->registrypriv;\r
1058         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;\r
1059         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1060         \r
1061         DBG_871X("%s\n", __FUNCTION__);\r
1062         \r
1063 \r
1064         //handle A-MPDU parameter field\r
1065         /*      \r
1066                 AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k\r
1067                 AMPDU_para [4:2]:Min MPDU Start Spacing \r
1068         */\r
1069         max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;  \r
1070         \r
1071         min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;        \r
1072 \r
1073         rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));\r
1074 \r
1075         rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));\r
1076 \r
1077         //\r
1078         // Config SM Power Save setting\r
1079         //\r
1080         pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;\r
1081         if(pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)\r
1082         {\r
1083                 /*u8 i;\r
1084                 //update the MCS rates\r
1085                 for (i = 0; i < 16; i++)\r
1086                 {\r
1087                         pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];\r
1088                 }*/\r
1089                 DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n",__FUNCTION__);\r
1090         }\r
1091 \r
1092         //\r
1093         // Config current HT Protection mode.\r
1094         //\r
1095         //pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;\r
1096 \r
1097 }\r
1098 \r
1099 void start_bss_network(_adapter *padapter, u8 *pbuf)\r
1100 {\r
1101         u8 *p;\r
1102         u8 val8, cur_channel, cur_bwmode, cur_ch_offset;\r
1103         u16 bcn_interval;\r
1104         u32     acparm; \r
1105         int     ie_len; \r
1106         struct registry_priv     *pregpriv = &padapter->registrypriv;\r
1107         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
1108         struct security_priv* psecuritypriv=&(padapter->securitypriv);  \r
1109         WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;\r
1110         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
1111         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1112         WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);\r
1113         struct HT_info_element *pht_info=NULL;\r
1114 #ifdef CONFIG_P2P\r
1115         struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);\r
1116 #endif //CONFIG_P2P\r
1117         u8      cbw40_enable=0;\r
1118         u8      change_band = _FALSE;\r
1119         \r
1120         //DBG_871X("%s\n", __FUNCTION__);\r
1121 \r
1122         bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;       \r
1123         cur_channel = pnetwork->Configuration.DSConfig;\r
1124         cur_bwmode = CHANNEL_WIDTH_20;\r
1125         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
1126         \r
1127 \r
1128         //check if there is wps ie, \r
1129         //if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd,\r
1130         //and at first time the security ie ( RSN/WPA IE) will not include in beacon.\r
1131         if(NULL == rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))\r
1132         {\r
1133                 pmlmeext->bstart_bss = _TRUE;\r
1134         }\r
1135 \r
1136         //todo: update wmm, ht cap\r
1137         //pmlmeinfo->WMM_enable;\r
1138         //pmlmeinfo->HT_enable;\r
1139         if(pmlmepriv->qospriv.qos_option)\r
1140                 pmlmeinfo->WMM_enable = _TRUE;\r
1141 #ifdef CONFIG_80211N_HT\r
1142         if(pmlmepriv->htpriv.ht_option)\r
1143         {\r
1144                 pmlmeinfo->WMM_enable = _TRUE;\r
1145                 pmlmeinfo->HT_enable = _TRUE;\r
1146                 //pmlmeinfo->HT_info_enable = _TRUE;\r
1147                 //pmlmeinfo->HT_caps_enable = _TRUE;\r
1148 \r
1149                 update_hw_ht_param(padapter);\r
1150         }\r
1151 #endif //#CONFIG_80211N_HT\r
1152 \r
1153 #ifdef CONFIG_80211AC_VHT\r
1154         if(pmlmepriv->vhtpriv.vht_option) {\r
1155                 pmlmeinfo->VHT_enable = _TRUE;\r
1156                 update_hw_vht_param(padapter);\r
1157         }\r
1158 #endif //CONFIG_80211AC_VHT\r
1159 \r
1160         if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at  first time\r
1161         {\r
1162                 //WEP Key will be set before this function, do not clear CAM.\r
1163                 if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))\r
1164                         flush_all_cam_entry(padapter);  //clear CAM\r
1165         }       \r
1166 \r
1167         //set MSR to AP_Mode            \r
1168         Set_MSR(padapter, _HW_STATE_AP_);       \r
1169                 \r
1170         //Set BSSID REG\r
1171         rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);\r
1172 \r
1173         //Set EDCA param reg\r
1174 #ifdef CONFIG_CONCURRENT_MODE\r
1175         acparm = 0x005ea42b;\r
1176 #else\r
1177         acparm = 0x002F3217; // VO\r
1178 #endif\r
1179         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));\r
1180         acparm = 0x005E4317; // VI\r
1181         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));\r
1182         //acparm = 0x00105320; // BE\r
1183         acparm = 0x005ea42b;\r
1184         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));\r
1185         acparm = 0x0000A444; // BK\r
1186         rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));\r
1187 \r
1188         //Set Security\r
1189         val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;\r
1190         rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));\r
1191 \r
1192         //Beacon Control related register\r
1193         rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));\r
1194 \r
1195         rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);\r
1196 \r
1197         if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at  first time\r
1198         {\r
1199                 //u32 initialgain;\r
1200 \r
1201                 //initialgain = 0x1e;\r
1202 \r
1203 \r
1204                 //disable dynamic functions, such as high power, DIG\r
1205                 //Save_DM_Func_Flag(padapter);\r
1206                 //Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, _FALSE);\r
1207                 \r
1208                 //turn on all dynamic functions \r
1209                 Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);\r
1210 \r
1211                 //rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));\r
1212         \r
1213         }\r
1214 #ifdef CONFIG_80211N_HT\r
1215         //set channel, bwmode   \r
1216         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
1217         if( p && ie_len)\r
1218         {\r
1219                 pht_info = (struct HT_info_element *)(p+2);\r
1220 \r
1221                 if (cur_channel > 14) {\r
1222                         if ((pregpriv->bw_mode & 0xf0) > 0)\r
1223                                 cbw40_enable = 1;\r
1224                 } else {\r
1225                         if ((pregpriv->bw_mode & 0x0f) > 0)\r
1226                                 cbw40_enable = 1;\r
1227                 }\r
1228 \r
1229                 if ((cbw40_enable) &&    (pht_info->infos[0] & BIT(2)))\r
1230                 {\r
1231                         //switch to the 40M Hz mode\r
1232                         //pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;\r
1233                         cur_bwmode = CHANNEL_WIDTH_40;\r
1234                         switch (pht_info->infos[0] & 0x3)\r
1235                         {\r
1236                                 case 1:\r
1237                                         //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;\r
1238                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;\r
1239                                         break;\r
1240                         \r
1241                                 case 3:\r
1242                                         //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;\r
1243                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;                                    \r
1244                                         break;\r
1245                                 \r
1246                                 default:\r
1247                                         //pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
1248                                         cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
1249                                         break;\r
1250                         }               \r
1251                                                 \r
1252                 }\r
1253                                         \r
1254         }\r
1255 #endif //CONFIG_80211N_HT\r
1256 \r
1257 #ifdef CONFIG_80211AC_VHT\r
1258         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
1259         if( p && ie_len)\r
1260         {\r
1261                 if(GET_VHT_OPERATION_ELE_CHL_WIDTH(p+2) >= 1) {\r
1262                         cur_bwmode = CHANNEL_WIDTH_80;\r
1263                 }\r
1264         }\r
1265 #endif\r
1266 \r
1267 #ifdef CONFIG_DUALMAC_CONCURRENT\r
1268         dc_set_ap_channel_bandwidth(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
1269 #else //!CONFIG_DUALMAC_CONCURRENT      \r
1270 #ifdef CONFIG_CONCURRENT_MODE\r
1271         //TODO: need to judge the phy parameters on concurrent mode for single phy\r
1272         concurrent_set_ap_chbw(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
1273 #else //!CONFIG_CONCURRENT_MODE\r
1274         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
1275         DBG_871X("CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);\r
1276         pmlmeext->cur_channel = cur_channel;    \r
1277         pmlmeext->cur_bwmode = cur_bwmode;\r
1278         pmlmeext->cur_ch_offset = cur_ch_offset;\r
1279 #endif //!CONFIG_CONCURRENT_MODE\r
1280 #endif //!CONFIG_DUALMAC_CONCURRENT\r
1281 \r
1282         pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type;\r
1283 \r
1284         //let pnetwork_mlmeext == pnetwork_mlme.\r
1285         _rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);\r
1286 \r
1287         //update cur_wireless_mode\r
1288         update_wireless_mode(padapter);\r
1289 \r
1290         //update RRSR after set channel and bandwidth\r
1291         UpdateBrateTbl(padapter, pnetwork->SupportedRates);\r
1292         rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);\r
1293 \r
1294         //udpate capability after cur_wireless_mode updated\r
1295         update_capinfo(padapter, rtw_get_capability((WLAN_BSSID_EX *)pnetwork));\r
1296 \r
1297 \r
1298 #ifdef CONFIG_P2P\r
1299         _rtw_memcpy(pwdinfo->p2p_group_ssid, pnetwork->Ssid.Ssid, pnetwork->Ssid.SsidLength);   \r
1300         pwdinfo->p2p_group_ssid_len = pnetwork->Ssid.SsidLength;\r
1301 #endif //CONFIG_P2P\r
1302 \r
1303         if(_TRUE == pmlmeext->bstart_bss)\r
1304         {\r
1305                 update_beacon(padapter, _TIM_IE_, NULL, _TRUE);\r
1306 \r
1307 #ifndef CONFIG_INTERRUPT_BASED_TXBCN //other case will  tx beacon when bcn interrupt coming in.\r
1308 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)\r
1309                 //issue beacon frame\r
1310                 if(send_beacon(padapter)==_FAIL)\r
1311                 {\r
1312                         DBG_871X("issue_beacon, fail!\n");\r
1313                 }\r
1314 #endif \r
1315 #endif //!CONFIG_INTERRUPT_BASED_TXBCN\r
1316                 \r
1317         }\r
1318 \r
1319 \r
1320         //update bc/mc sta_info\r
1321         update_bmc_sta(padapter);\r
1322         \r
1323         //pmlmeext->bstart_bss = _TRUE;\r
1324         \r
1325 }\r
1326 \r
1327 int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf,  int len)\r
1328 {\r
1329         int ret=_SUCCESS;\r
1330         u8 *p;\r
1331         u8 *pHT_caps_ie=NULL;\r
1332         u8 *pHT_info_ie=NULL;\r
1333         struct sta_info *psta = NULL;\r
1334         u16 cap, ht_cap=_FALSE;\r
1335         uint ie_len = 0;\r
1336         int group_cipher, pairwise_cipher;      \r
1337         u8      channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];\r
1338         int supportRateNum = 0;\r
1339         u8 OUI1[] = {0x00, 0x50, 0xf2,0x01};\r
1340         u8 wps_oui[4]={0x0,0x50,0xf2,0x04};\r
1341         u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};        \r
1342         struct registry_priv *pregistrypriv = &padapter->registrypriv;  \r
1343         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
1344         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
1345         WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; \r
1346         struct sta_priv *pstapriv = &padapter->stapriv;\r
1347         u8 *ie = pbss_network->IEs;\r
1348         u8 vht_cap=_FALSE;\r
1349 \r
1350         /* SSID */\r
1351         /* Supported rates */\r
1352         /* DS Params */\r
1353         /* WLAN_EID_COUNTRY */\r
1354         /* ERP Information element */\r
1355         /* Extended supported rates */\r
1356         /* WPA/WPA2 */\r
1357         /* Wi-Fi Wireless Multimedia Extensions */\r
1358         /* ht_capab, ht_oper */\r
1359         /* WPS IE */\r
1360 \r
1361         DBG_871X("%s, len=%d\n", __FUNCTION__, len);\r
1362 \r
1363         if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)\r
1364                 return _FAIL;\r
1365 \r
1366 \r
1367         if(len>MAX_IE_SZ)\r
1368                 return _FAIL;\r
1369         \r
1370         pbss_network->IELength = len;\r
1371 \r
1372         _rtw_memset(ie, 0, MAX_IE_SZ);\r
1373         \r
1374         _rtw_memcpy(ie, pbuf, pbss_network->IELength);\r
1375 \r
1376 \r
1377         if(pbss_network->InfrastructureMode!=Ndis802_11APMode)\r
1378                 return _FAIL;\r
1379 \r
1380         pbss_network->Rssi = 0;\r
1381 \r
1382         _rtw_memcpy(pbss_network->MacAddress, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
1383         \r
1384         //beacon interval\r
1385         p = rtw_get_beacon_interval_from_ie(ie);//ie + 8;       // 8: TimeStamp, 2: Beacon Interval 2:Capability\r
1386         //pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p);\r
1387         pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);\r
1388         \r
1389         //capability\r
1390         //cap = *(unsigned short *)rtw_get_capability_from_ie(ie);\r
1391         //cap = le16_to_cpu(cap);\r
1392         cap = RTW_GET_LE16(ie);\r
1393 \r
1394         //SSID\r
1395         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength -_BEACON_IE_OFFSET_));\r
1396         if(p && ie_len>0)\r
1397         {\r
1398                 _rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID));\r
1399                 _rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);\r
1400                 pbss_network->Ssid.SsidLength = ie_len;\r
1401         }       \r
1402 \r
1403         //chnnel\r
1404         channel = 0;\r
1405         pbss_network->Configuration.Length = 0;\r
1406         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1407         if(p && ie_len>0)\r
1408                 channel = *(p + 2);\r
1409 \r
1410         pbss_network->Configuration.DSConfig = channel;\r
1411 \r
1412         \r
1413         _rtw_memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);\r
1414         // get supported rates\r
1415         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));   \r
1416         if (p !=  NULL) \r
1417         {\r
1418                 _rtw_memcpy(supportRate, p+2, ie_len);  \r
1419                 supportRateNum = ie_len;\r
1420         }\r
1421         \r
1422         //get ext_supported rates\r
1423         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_); \r
1424         if (p !=  NULL)\r
1425         {\r
1426                 _rtw_memcpy(supportRate+supportRateNum, p+2, ie_len);\r
1427                 supportRateNum += ie_len;\r
1428         \r
1429         }\r
1430 \r
1431         network_type = rtw_check_network_type(supportRate, supportRateNum, channel);\r
1432 \r
1433         rtw_set_supported_rate(pbss_network->SupportedRates, network_type);\r
1434 \r
1435 \r
1436         //parsing ERP_IE\r
1437         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1438         if(p && ie_len>0)\r
1439         {\r
1440                 ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);\r
1441         }\r
1442 \r
1443         //update privacy/security\r
1444         if (cap & BIT(4))\r
1445                 pbss_network->Privacy = 1;\r
1446         else\r
1447                 pbss_network->Privacy = 0;\r
1448 \r
1449         psecuritypriv->wpa_psk = 0;\r
1450 \r
1451         //wpa2\r
1452         group_cipher = 0; pairwise_cipher = 0;\r
1453         psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;\r
1454         psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;     \r
1455         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));            \r
1456         if(p && ie_len>0)\r
1457         {\r
1458                 if(rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)\r
1459                 {\r
1460                         psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;\r
1461                         \r
1462                         psecuritypriv->dot8021xalg = 1;//psk,  todo:802.1x\r
1463                         psecuritypriv->wpa_psk |= BIT(1);\r
1464 \r
1465                         psecuritypriv->wpa2_group_cipher = group_cipher;\r
1466                         psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;\r
1467 #if 0\r
1468                         switch(group_cipher)\r
1469                         {\r
1470                                 case WPA_CIPHER_NONE:                           \r
1471                                 psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;\r
1472                                 break;\r
1473                                 case WPA_CIPHER_WEP40:                          \r
1474                                 psecuritypriv->wpa2_group_cipher = _WEP40_;\r
1475                                 break;\r
1476                                 case WPA_CIPHER_TKIP:                           \r
1477                                 psecuritypriv->wpa2_group_cipher = _TKIP_;\r
1478                                 break;\r
1479                                 case WPA_CIPHER_CCMP:                           \r
1480                                 psecuritypriv->wpa2_group_cipher = _AES_;                               \r
1481                                 break;\r
1482                                 case WPA_CIPHER_WEP104:                                 \r
1483                                 psecuritypriv->wpa2_group_cipher = _WEP104_;\r
1484                                 break;\r
1485                         }\r
1486 \r
1487                         switch(pairwise_cipher)\r
1488                         {\r
1489                                 case WPA_CIPHER_NONE:                   \r
1490                                 psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;\r
1491                                 break;\r
1492                                 case WPA_CIPHER_WEP40:                  \r
1493                                 psecuritypriv->wpa2_pairwise_cipher = _WEP40_;\r
1494                                 break;\r
1495                                 case WPA_CIPHER_TKIP:                           \r
1496                                 psecuritypriv->wpa2_pairwise_cipher = _TKIP_;\r
1497                                 break;\r
1498                                 case WPA_CIPHER_CCMP:                   \r
1499                                 psecuritypriv->wpa2_pairwise_cipher = _AES_;\r
1500                                 break;\r
1501                                 case WPA_CIPHER_WEP104:                                 \r
1502                                 psecuritypriv->wpa2_pairwise_cipher = _WEP104_;\r
1503                                 break;\r
1504                         }\r
1505 #endif                  \r
1506                 }\r
1507                 \r
1508         }\r
1509 \r
1510         //wpa\r
1511         ie_len = 0;\r
1512         group_cipher = 0; pairwise_cipher = 0;\r
1513         psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;\r
1514         psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;      \r
1515         for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))\r
1516         {\r
1517                 p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));           \r
1518                 if ((p) && (_rtw_memcmp(p+2, OUI1, 4)))\r
1519                 {\r
1520                         if(rtw_parse_wpa_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)\r
1521                         {\r
1522                                 psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;\r
1523                                 \r
1524                                 psecuritypriv->dot8021xalg = 1;//psk,  todo:802.1x\r
1525 \r
1526                                 psecuritypriv->wpa_psk |= BIT(0);\r
1527 \r
1528                                 psecuritypriv->wpa_group_cipher = group_cipher;\r
1529                                 psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;\r
1530 \r
1531 #if 0\r
1532                                 switch(group_cipher)\r
1533                                 {\r
1534                                         case WPA_CIPHER_NONE:                                   \r
1535                                         psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;\r
1536                                         break;\r
1537                                         case WPA_CIPHER_WEP40:                                  \r
1538                                         psecuritypriv->wpa_group_cipher = _WEP40_;\r
1539                                         break;\r
1540                                         case WPA_CIPHER_TKIP:                                   \r
1541                                         psecuritypriv->wpa_group_cipher = _TKIP_;\r
1542                                         break;\r
1543                                         case WPA_CIPHER_CCMP:                                   \r
1544                                         psecuritypriv->wpa_group_cipher = _AES_;                                \r
1545                                         break;\r
1546                                         case WPA_CIPHER_WEP104:                                 \r
1547                                         psecuritypriv->wpa_group_cipher = _WEP104_;\r
1548                                         break;\r
1549                                 }\r
1550 \r
1551                                 switch(pairwise_cipher)\r
1552                                 {\r
1553                                         case WPA_CIPHER_NONE:                                   \r
1554                                         psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;\r
1555                                         break;\r
1556                                         case WPA_CIPHER_WEP40:                                  \r
1557                                         psecuritypriv->wpa_pairwise_cipher = _WEP40_;\r
1558                                         break;\r
1559                                         case WPA_CIPHER_TKIP:                                   \r
1560                                         psecuritypriv->wpa_pairwise_cipher = _TKIP_;\r
1561                                         break;\r
1562                                         case WPA_CIPHER_CCMP:                                   \r
1563                                         psecuritypriv->wpa_pairwise_cipher = _AES_;\r
1564                                         break;\r
1565                                         case WPA_CIPHER_WEP104:                                 \r
1566                                         psecuritypriv->wpa_pairwise_cipher = _WEP104_;\r
1567                                         break;\r
1568                                 }\r
1569 #endif                          \r
1570                         }\r
1571 \r
1572                         break;\r
1573                         \r
1574                 }\r
1575                         \r
1576                 if ((p == NULL) || (ie_len == 0))\r
1577                 {\r
1578                                 break;\r
1579                 }\r
1580                 \r
1581         }\r
1582 \r
1583         //wmm\r
1584         ie_len = 0;\r
1585         pmlmepriv->qospriv.qos_option = 0;\r
1586         if(pregistrypriv->wmm_enable)\r
1587         {\r
1588                 for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))\r
1589                 {                       \r
1590                         p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); \r
1591                         if((p) && _rtw_memcmp(p+2, WMM_PARA_IE, 6)) \r
1592                         {\r
1593                                 pmlmepriv->qospriv.qos_option = 1;      \r
1594 \r
1595                                 *(p+8) |= BIT(7);//QoS Info, support U-APSD\r
1596                                 \r
1597                                 /* disable all ACM bits since the WMM admission control is not supported */\r
1598                                 *(p + 10) &= ~BIT(4); /* BE */\r
1599                                 *(p + 14) &= ~BIT(4); /* BK */\r
1600                                 *(p + 18) &= ~BIT(4); /* VI */\r
1601                                 *(p + 22) &= ~BIT(4); /* VO */\r
1602                                 \r
1603                                 break;                          \r
1604                         }\r
1605                         \r
1606                         if ((p == NULL) || (ie_len == 0))\r
1607                         {\r
1608                                 break;\r
1609                         }                       \r
1610                 }               \r
1611         }\r
1612 #ifdef CONFIG_80211N_HT\r
1613         //parsing HT_CAP_IE\r
1614         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1615         if(p && ie_len>0)\r
1616         {\r
1617                 u8 rf_type;\r
1618 \r
1619                 struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2);\r
1620 \r
1621                 pHT_caps_ie=p;\r
1622                 \r
1623                 \r
1624                 ht_cap = _TRUE;\r
1625                 network_type |= WIRELESS_11_24N;\r
1626 \r
1627         \r
1628                 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));\r
1629 \r
1630                 if((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||\r
1631                         (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))\r
1632                 {\r
1633                         pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));\r
1634                 }       \r
1635                 else\r
1636                 {\r
1637                         pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);    \r
1638                 }       \r
1639 \r
1640                 pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & 0x03); //set  Max Rx AMPDU size  to 64K\r
1641 \r
1642                 if(rf_type == RF_1T1R)\r
1643                 {                       \r
1644                         pht_cap->supp_mcs_set[0] = 0xff;\r
1645                         pht_cap->supp_mcs_set[1] = 0x0;                         \r
1646                 }\r
1647 \r
1648                 _rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);            \r
1649                 \r
1650         }\r
1651 \r
1652         //parsing HT_INFO_IE\r
1653         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1654         if(p && ie_len>0)\r
1655         {\r
1656                 pHT_info_ie=p;\r
1657         }\r
1658 #endif //CONFIG_80211N_HT\r
1659         switch(network_type)\r
1660         {\r
1661                 case WIRELESS_11B:\r
1662                         pbss_network->NetworkTypeInUse = Ndis802_11DS;\r
1663                         break;  \r
1664                 case WIRELESS_11G:\r
1665                 case WIRELESS_11BG:\r
1666              case WIRELESS_11G_24N:\r
1667                 case WIRELESS_11BG_24N:\r
1668                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;\r
1669                         break;\r
1670                 case WIRELESS_11A:\r
1671                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;\r
1672                         break;\r
1673                 default :\r
1674                         pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;\r
1675                         break;\r
1676         }\r
1677         \r
1678         pmlmepriv->cur_network.network_type = network_type;\r
1679 \r
1680 #ifdef CONFIG_80211N_HT\r
1681         pmlmepriv->htpriv.ht_option = _FALSE;\r
1682 \r
1683         if( (psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||\r
1684                       (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP))\r
1685         {       \r
1686                 //todo:\r
1687                 //ht_cap = _FALSE;\r
1688         }\r
1689                       \r
1690         //ht_cap        \r
1691         if(pregistrypriv->ht_enable && ht_cap==_TRUE)\r
1692         {               \r
1693                 pmlmepriv->htpriv.ht_option = _TRUE;\r
1694                 pmlmepriv->qospriv.qos_option = 1;\r
1695 \r
1696                 if(pregistrypriv->ampdu_enable==1)\r
1697                 {\r
1698                         pmlmepriv->htpriv.ampdu_enable = _TRUE;\r
1699                 }\r
1700 \r
1701                 HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie);\r
1702                 \r
1703                 HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie);\r
1704         }\r
1705 #endif\r
1706 \r
1707 #ifdef CONFIG_80211AC_VHT\r
1708 \r
1709         //Parsing VHT CAP IE\r
1710         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));\r
1711         if(p && ie_len>0)\r
1712         {       \r
1713                 vht_cap = _TRUE; \r
1714         }\r
1715         //Parsing VHT OPERATION IE\r
1716         \r
1717 \r
1718         pmlmepriv->vhtpriv.vht_option = _FALSE;\r
1719         // if channel in 5G band, then add vht ie .\r
1720         if ((pbss_network->Configuration.DSConfig > 14) && \r
1721                 (pmlmepriv->htpriv.ht_option == _TRUE) &&\r
1722                 (pregistrypriv->vht_enable)) \r
1723         {\r
1724                 if(vht_cap == _TRUE)\r
1725                 {\r
1726                         pmlmepriv->vhtpriv.vht_option = _TRUE;\r
1727                 }\r
1728                 else if(pregistrypriv->vht_enable == 2) // auto enabled\r
1729                 {\r
1730                         u8      cap_len, operation_len;\r
1731 \r
1732                         rtw_vht_use_default_setting(padapter);\r
1733 \r
1734                         // VHT Capabilities element\r
1735                         cap_len = rtw_build_vht_cap_ie(padapter, pbss_network->IEs + pbss_network->IELength);\r
1736                         pbss_network->IELength += cap_len;\r
1737 \r
1738                         // VHT Operation element\r
1739                         operation_len = rtw_build_vht_operation_ie(padapter, pbss_network->IEs + pbss_network->IELength, pbss_network->Configuration.DSConfig);\r
1740                         pbss_network->IELength += operation_len;\r
1741 \r
1742                         pmlmepriv->vhtpriv.vht_option = _TRUE;\r
1743                 }               \r
1744         }\r
1745 #endif //CONFIG_80211AC_VHT\r
1746 \r
1747         pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX  *)pbss_network);\r
1748 \r
1749         //issue beacon to start bss network\r
1750         //start_bss_network(padapter, (u8*)pbss_network);\r
1751         rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK);\r
1752                         \r
1753 \r
1754         //alloc sta_info for ap itself\r
1755         psta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);\r
1756         if(!psta)\r
1757         {\r
1758                 psta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);\r
1759                 if (psta == NULL) \r
1760                 { \r
1761                         return _FAIL;\r
1762                 }       \r
1763         }       \r
1764         psta->state |= WIFI_AP_STATE;           //Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724  \r
1765         rtw_indicate_connect( padapter);\r
1766 \r
1767         pmlmepriv->cur_network.join_res = _TRUE;//for check if already set beacon\r
1768                 \r
1769         //update bc/mc sta_info\r
1770         //update_bmc_sta(padapter);\r
1771 \r
1772         return ret;\r
1773 \r
1774 }\r
1775 \r
1776 void rtw_set_macaddr_acl(_adapter *padapter, int mode)\r
1777 {\r
1778         struct sta_priv *pstapriv = &padapter->stapriv;\r
1779         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
1780 \r
1781         DBG_871X("%s, mode=%d\n", __func__, mode);\r
1782 \r
1783         pacl_list->mode = mode;\r
1784 }\r
1785 \r
1786 int rtw_acl_add_sta(_adapter *padapter, u8 *addr)\r
1787 {\r
1788         _irqL irqL;\r
1789         _list   *plist, *phead;\r
1790         u8 added = _FALSE;\r
1791         int i, ret=0;\r
1792         struct rtw_wlan_acl_node *paclnode;\r
1793         struct sta_priv *pstapriv = &padapter->stapriv;\r
1794         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
1795         _queue  *pacl_node_q =&pacl_list->acl_node_q;   \r
1796 \r
1797         DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));      \r
1798 \r
1799         if((NUM_ACL-1) < pacl_list->num)\r
1800                 return (-1);    \r
1801 \r
1802 \r
1803         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
1804 \r
1805         phead = get_list_head(pacl_node_q);\r
1806         plist = get_next(phead);\r
1807                 \r
1808         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
1809         {\r
1810                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);\r
1811                 plist = get_next(plist);\r
1812 \r
1813                 if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN))\r
1814                 {\r
1815                         if(paclnode->valid == _TRUE)\r
1816                         {\r
1817                                 added = _TRUE;\r
1818                                 DBG_871X("%s, sta has been added\n", __func__);\r
1819                                 break;\r
1820                         }\r
1821                 }               \r
1822         }\r
1823         \r
1824         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
1825 \r
1826 \r
1827         if(added == _TRUE)\r
1828                 return ret;\r
1829         \r
1830 \r
1831         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
1832 \r
1833         for(i=0; i< NUM_ACL; i++)\r
1834         {\r
1835                 paclnode = &pacl_list->aclnode[i];\r
1836 \r
1837                 if(paclnode->valid == _FALSE)\r
1838                 {\r
1839                         _rtw_init_listhead(&paclnode->list);\r
1840         \r
1841                         _rtw_memcpy(paclnode->addr, addr, ETH_ALEN);\r
1842                 \r
1843                         paclnode->valid = _TRUE;\r
1844 \r
1845                         rtw_list_insert_tail(&paclnode->list, get_list_head(pacl_node_q));\r
1846         \r
1847                         pacl_list->num++;\r
1848 \r
1849                         break;\r
1850                 }\r
1851         }\r
1852 \r
1853         DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);\r
1854         \r
1855         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
1856 \r
1857         return ret;\r
1858 }\r
1859 \r
1860 int rtw_acl_remove_sta(_adapter *padapter, u8 *addr)\r
1861 {\r
1862         _irqL irqL;\r
1863         _list   *plist, *phead;\r
1864         int i, ret=0;\r
1865         struct rtw_wlan_acl_node *paclnode;\r
1866         struct sta_priv *pstapriv = &padapter->stapriv;\r
1867         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
1868         _queue  *pacl_node_q =&pacl_list->acl_node_q;\r
1869         u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };    //Baddr is used for clearing acl_list\r
1870 \r
1871         DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));      \r
1872 \r
1873         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
1874 \r
1875         phead = get_list_head(pacl_node_q);\r
1876         plist = get_next(phead);\r
1877                 \r
1878         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
1879         {\r
1880                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);\r
1881                 plist = get_next(plist);\r
1882 \r
1883                 if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN) || _rtw_memcmp(baddr, addr, ETH_ALEN))\r
1884                 {\r
1885                         if(paclnode->valid == _TRUE)\r
1886                         {\r
1887                                 paclnode->valid = _FALSE;\r
1888 \r
1889                                 rtw_list_delete(&paclnode->list);\r
1890                                 \r
1891                                 pacl_list->num--;\r
1892                         }\r
1893                 }               \r
1894         }\r
1895         \r
1896         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
1897 \r
1898         DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);\r
1899         \r
1900         return ret;\r
1901 \r
1902 }\r
1903 \r
1904 u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta)\r
1905 {\r
1906         struct cmd_obj*                 ph2c;\r
1907         struct set_stakey_parm  *psetstakey_para;\r
1908         struct cmd_priv                         *pcmdpriv=&padapter->cmdpriv;   \r
1909         u8      res=_SUCCESS;\r
1910 \r
1911         ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));\r
1912         if ( ph2c == NULL){\r
1913                 res= _FAIL;\r
1914                 goto exit;\r
1915         }\r
1916 \r
1917         psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm));\r
1918         if(psetstakey_para==NULL){\r
1919                 rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));\r
1920                 res=_FAIL;\r
1921                 goto exit;\r
1922         }\r
1923 \r
1924         init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);\r
1925 \r
1926 \r
1927         psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;\r
1928 \r
1929         _rtw_memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);     \r
1930         \r
1931         _rtw_memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);\r
1932 \r
1933         \r
1934         res = rtw_enqueue_cmd(pcmdpriv, ph2c);  \r
1935 \r
1936 exit:\r
1937 \r
1938         return res;\r
1939         \r
1940 }\r
1941 \r
1942 static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx)\r
1943 {\r
1944         u8 keylen;\r
1945         struct cmd_obj* pcmd;\r
1946         struct setkey_parm *psetkeyparm;\r
1947         struct cmd_priv *pcmdpriv=&(padapter->cmdpriv); \r
1948         int res=_SUCCESS;\r
1949 \r
1950         //DBG_871X("%s\n", __FUNCTION__);\r
1951         \r
1952         pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));\r
1953         if(pcmd==NULL){\r
1954                 res= _FAIL;\r
1955                 goto exit;\r
1956         }\r
1957         psetkeyparm=(struct setkey_parm*)rtw_zmalloc(sizeof(struct setkey_parm));\r
1958         if(psetkeyparm==NULL){\r
1959                 rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));\r
1960                 res= _FAIL;\r
1961                 goto exit;\r
1962         }\r
1963 \r
1964         _rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));\r
1965                 \r
1966         psetkeyparm->keyid=(u8)keyid;\r
1967         if (is_wep_enc(alg))\r
1968                 padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);\r
1969 \r
1970         psetkeyparm->algorithm = alg;\r
1971 \r
1972         psetkeyparm->set_tx = set_tx;\r
1973 \r
1974         switch(alg)\r
1975         {\r
1976                 case _WEP40_:                                   \r
1977                         keylen = 5;\r
1978                         break;\r
1979                 case _WEP104_:\r
1980                         keylen = 13;                    \r
1981                         break;\r
1982                 case _TKIP_:\r
1983                 case _TKIP_WTMIC_:              \r
1984                 case _AES_:\r
1985                         keylen = 16;            \r
1986                 default:\r
1987                         keylen = 16;            \r
1988         }\r
1989 \r
1990         _rtw_memcpy(&(psetkeyparm->key[0]), key, keylen);\r
1991         \r
1992         pcmd->cmdcode = _SetKey_CMD_;\r
1993         pcmd->parmbuf = (u8 *)psetkeyparm;   \r
1994         pcmd->cmdsz =  (sizeof(struct setkey_parm));  \r
1995         pcmd->rsp = NULL;\r
1996         pcmd->rspsz = 0;\r
1997 \r
1998 \r
1999         _rtw_init_listhead(&pcmd->list);\r
2000 \r
2001         res = rtw_enqueue_cmd(pcmdpriv, pcmd);\r
2002 \r
2003 exit:\r
2004 \r
2005         return res;\r
2006 }\r
2007 \r
2008 int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid)\r
2009 {\r
2010         DBG_871X("%s\n", __FUNCTION__);\r
2011 \r
2012         return rtw_ap_set_key(padapter, key, alg, keyid, 1);\r
2013 }\r
2014 \r
2015 int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx)\r
2016 {\r
2017         u8 alg;\r
2018 \r
2019         switch(keylen)\r
2020         {\r
2021                 case 5:\r
2022                         alg =_WEP40_;                   \r
2023                         break;\r
2024                 case 13:\r
2025                         alg =_WEP104_;                  \r
2026                         break;\r
2027                 default:\r
2028                         alg =_NO_PRIVACY_;                      \r
2029         }\r
2030 \r
2031         DBG_871X("%s\n", __FUNCTION__);\r
2032 \r
2033         return rtw_ap_set_key(padapter, key, alg, keyid, set_tx);\r
2034 }\r
2035 \r
2036 #ifdef CONFIG_NATIVEAP_MLME\r
2037 \r
2038 static void update_bcn_fixed_ie(_adapter *padapter)\r
2039 {\r
2040         DBG_871X("%s\n", __FUNCTION__);\r
2041 \r
2042 }\r
2043 \r
2044 static void update_bcn_erpinfo_ie(_adapter *padapter)\r
2045 {\r
2046         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2047         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2048         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2049         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);\r
2050         unsigned char *p, *ie = pnetwork->IEs;\r
2051         u32 len = 0;\r
2052 \r
2053         DBG_871X("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable);\r
2054 \r
2055         if(!pmlmeinfo->ERP_enable)\r
2056                 return;\r
2057 \r
2058         //parsing ERP_IE\r
2059         p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));\r
2060         if(p && len>0)\r
2061         {\r
2062                 PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p;\r
2063 \r
2064                 if (pmlmepriv->num_sta_non_erp == 1)\r
2065                         pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION;\r
2066                 else\r
2067                         pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION);\r
2068 \r
2069                 if(pmlmepriv->num_sta_no_short_preamble > 0)\r
2070                         pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;\r
2071                 else\r
2072                         pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);\r
2073         \r
2074                 ERP_IE_handler(padapter, pIE);\r
2075         }\r
2076         \r
2077 }\r
2078 \r
2079 static void update_bcn_htcap_ie(_adapter *padapter)\r
2080 {\r
2081         DBG_871X("%s\n", __FUNCTION__);\r
2082 \r
2083 }\r
2084 \r
2085 static void update_bcn_htinfo_ie(_adapter *padapter)\r
2086 {       \r
2087         DBG_871X("%s\n", __FUNCTION__);\r
2088 \r
2089 }\r
2090 \r
2091 static void update_bcn_rsn_ie(_adapter *padapter)\r
2092 {\r
2093         DBG_871X("%s\n", __FUNCTION__);\r
2094 \r
2095 }\r
2096 \r
2097 static void update_bcn_wpa_ie(_adapter *padapter)\r
2098 {\r
2099         DBG_871X("%s\n", __FUNCTION__);\r
2100 \r
2101 }\r
2102 \r
2103 static void update_bcn_wmm_ie(_adapter *padapter)\r
2104 {\r
2105         DBG_871X("%s\n", __FUNCTION__);\r
2106         \r
2107 }\r
2108 \r
2109 static void update_bcn_wps_ie(_adapter *padapter)\r
2110 {\r
2111         u8 *pwps_ie=NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie=NULL;\r
2112         uint wps_ielen=0, wps_offset, remainder_ielen;\r
2113         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2114         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2115         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2116         WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);\r
2117         unsigned char *ie = pnetwork->IEs;\r
2118         u32 ielen = pnetwork->IELength;\r
2119 \r
2120 \r
2121         DBG_871X("%s\n", __FUNCTION__);\r
2122 \r
2123         pwps_ie = rtw_get_wps_ie(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);\r
2124         \r
2125         if(pwps_ie==NULL || wps_ielen==0)\r
2126                 return;\r
2127 \r
2128         pwps_ie_src = pmlmepriv->wps_beacon_ie;\r
2129         if(pwps_ie_src == NULL)\r
2130                 return;\r
2131 \r
2132         wps_offset = (uint)(pwps_ie-ie);\r
2133 \r
2134         premainder_ie = pwps_ie + wps_ielen;\r
2135 \r
2136         remainder_ielen = ielen - wps_offset - wps_ielen;\r
2137 \r
2138         if(remainder_ielen>0)\r
2139         {\r
2140                 pbackup_remainder_ie = rtw_malloc(remainder_ielen);\r
2141                 if(pbackup_remainder_ie)\r
2142                         _rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);\r
2143         }\r
2144 \r
2145         wps_ielen = (uint)pwps_ie_src[1];//to get ie data len\r
2146         if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)\r
2147         {\r
2148                 _rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);\r
2149                 pwps_ie += (wps_ielen+2);\r
2150 \r
2151                 if(pbackup_remainder_ie)\r
2152                         _rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);\r
2153 \r
2154                 //update IELength\r
2155                 pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;\r
2156         }\r
2157 \r
2158         if(pbackup_remainder_ie)\r
2159                 rtw_mfree(pbackup_remainder_ie, remainder_ielen);\r
2160 \r
2161 }\r
2162 \r
2163 static void update_bcn_p2p_ie(_adapter *padapter)\r
2164 {\r
2165 \r
2166 }\r
2167 \r
2168 static void update_bcn_vendor_spec_ie(_adapter *padapter, u8*oui)\r
2169 {\r
2170         DBG_871X("%s\n", __FUNCTION__);\r
2171 \r
2172         if(_rtw_memcmp(RTW_WPA_OUI, oui, 4))\r
2173         {\r
2174                 update_bcn_wpa_ie(padapter);\r
2175         }\r
2176         else if(_rtw_memcmp(WMM_OUI, oui, 4))\r
2177         {\r
2178                 update_bcn_wmm_ie(padapter);\r
2179         }\r
2180         else if(_rtw_memcmp(WPS_OUI, oui, 4))\r
2181         {\r
2182                 update_bcn_wps_ie(padapter);\r
2183         }\r
2184         else if(_rtw_memcmp(P2P_OUI, oui, 4))\r
2185         {\r
2186                 update_bcn_p2p_ie(padapter);\r
2187         }\r
2188         else\r
2189         {\r
2190                 DBG_871X("unknown OUI type!\n");\r
2191         }\r
2192         \r
2193         \r
2194 }\r
2195 \r
2196 void update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx)\r
2197 {\r
2198         _irqL irqL;\r
2199         struct mlme_priv *pmlmepriv;\r
2200         struct mlme_ext_priv    *pmlmeext;\r
2201         //struct mlme_ext_info  *pmlmeinfo;\r
2202         \r
2203         //DBG_871X("%s\n", __FUNCTION__);\r
2204 \r
2205         if(!padapter)\r
2206                 return;\r
2207 \r
2208         pmlmepriv = &(padapter->mlmepriv);\r
2209         pmlmeext = &(padapter->mlmeextpriv);\r
2210         //pmlmeinfo = &(pmlmeext->mlmext_info);\r
2211 \r
2212         if(_FALSE == pmlmeext->bstart_bss)\r
2213                 return;\r
2214 \r
2215         _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);\r
2216 \r
2217         switch(ie_id)\r
2218         {\r
2219                 case 0xFF:\r
2220 \r
2221                         update_bcn_fixed_ie(padapter);//8: TimeStamp, 2: Beacon Interval 2:Capability\r
2222                         \r
2223                         break;\r
2224         \r
2225                 case _TIM_IE_:\r
2226                         \r
2227                         update_BCNTIM(padapter);\r
2228                         \r
2229                         break;\r
2230 \r
2231                 case _ERPINFO_IE_:\r
2232 \r
2233                         update_bcn_erpinfo_ie(padapter);\r
2234 \r
2235                         break;\r
2236 \r
2237                 case _HT_CAPABILITY_IE_:\r
2238 \r
2239                         update_bcn_htcap_ie(padapter);\r
2240                         \r
2241                         break;\r
2242 \r
2243                 case _RSN_IE_2_:\r
2244 \r
2245                         update_bcn_rsn_ie(padapter);\r
2246 \r
2247                         break;\r
2248                         \r
2249                 case _HT_ADD_INFO_IE_:\r
2250 \r
2251                         update_bcn_htinfo_ie(padapter);\r
2252                         \r
2253                         break;\r
2254         \r
2255                 case _VENDOR_SPECIFIC_IE_:\r
2256 \r
2257                         update_bcn_vendor_spec_ie(padapter, oui);\r
2258                         \r
2259                         break;\r
2260                         \r
2261                 default:\r
2262                         break;\r
2263         }\r
2264 \r
2265         pmlmepriv->update_bcn = _TRUE;\r
2266         \r
2267         _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);          \r
2268         \r
2269 #ifndef CONFIG_INTERRUPT_BASED_TXBCN \r
2270 #if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)\r
2271         if(tx)\r
2272         {\r
2273                 //send_beacon(padapter);//send_beacon must execute on TSR level\r
2274                 set_tx_beacon_cmd(padapter);\r
2275         }\r
2276 #else\r
2277         {       \r
2278                 //PCI will issue beacon when BCN interrupt occurs.              \r
2279         }\r
2280 #endif\r
2281 #endif //!CONFIG_INTERRUPT_BASED_TXBCN\r
2282         \r
2283 }\r
2284 \r
2285 #ifdef CONFIG_80211N_HT\r
2286 \r
2287 /*\r
2288 op_mode\r
2289 Set to 0 (HT pure) under the followign conditions\r
2290         - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or\r
2291         - all STAs in the BSS are 20 MHz HT in 20 MHz BSS\r
2292 Set to 1 (HT non-member protection) if there may be non-HT STAs\r
2293         in both the primary and the secondary channel\r
2294 Set to 2 if only HT STAs are associated in BSS,\r
2295         however and at least one 20 MHz HT STA is associated\r
2296 Set to 3 (HT mixed mode) when one or more non-HT STAs are associated\r
2297         (currently non-GF HT station is considered as non-HT STA also)\r
2298 */\r
2299 static int rtw_ht_operation_update(_adapter *padapter)\r
2300 {\r
2301         u16 cur_op_mode, new_op_mode;\r
2302         int op_mode_changes = 0;\r
2303         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2304         struct ht_priv  *phtpriv_ap = &pmlmepriv->htpriv;\r
2305 \r
2306         if(pmlmepriv->htpriv.ht_option == _TRUE) \r
2307                 return 0;\r
2308         \r
2309         //if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)\r
2310         //      return 0;\r
2311 \r
2312         DBG_871X("%s current operation mode=0x%X\n",\r
2313                    __FUNCTION__, pmlmepriv->ht_op_mode);\r
2314 \r
2315         if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)\r
2316             && pmlmepriv->num_sta_ht_no_gf) {\r
2317                 pmlmepriv->ht_op_mode |=\r
2318                         HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;\r
2319                 op_mode_changes++;\r
2320         } else if ((pmlmepriv->ht_op_mode &\r
2321                     HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&\r
2322                    pmlmepriv->num_sta_ht_no_gf == 0) {\r
2323                 pmlmepriv->ht_op_mode &=\r
2324                         ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;\r
2325                 op_mode_changes++;\r
2326         }\r
2327 \r
2328         if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&\r
2329             (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {\r
2330                 pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;\r
2331                 op_mode_changes++;\r
2332         } else if ((pmlmepriv->ht_op_mode &\r
2333                     HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&\r
2334                    (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {\r
2335                 pmlmepriv->ht_op_mode &=\r
2336                         ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;\r
2337                 op_mode_changes++;\r
2338         }\r
2339 \r
2340         /* Note: currently we switch to the MIXED op mode if HT non-greenfield\r
2341          * station is associated. Probably it's a theoretical case, since\r
2342          * it looks like all known HT STAs support greenfield.\r
2343          */\r
2344         new_op_mode = 0;\r
2345         if (pmlmepriv->num_sta_no_ht ||\r
2346             (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT))\r
2347                 new_op_mode = OP_MODE_MIXED;\r
2348         else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH)\r
2349                  && pmlmepriv->num_sta_ht_20mhz)\r
2350                 new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;\r
2351         else if (pmlmepriv->olbc_ht)\r
2352                 new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;\r
2353         else\r
2354                 new_op_mode = OP_MODE_PURE;\r
2355 \r
2356         cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;\r
2357         if (cur_op_mode != new_op_mode) {\r
2358                 pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;\r
2359                 pmlmepriv->ht_op_mode |= new_op_mode;\r
2360                 op_mode_changes++;\r
2361         }\r
2362 \r
2363         DBG_871X("%s new operation mode=0x%X changes=%d\n",\r
2364                    __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes);\r
2365 \r
2366         return op_mode_changes;\r
2367         \r
2368 }\r
2369 \r
2370 #endif /* CONFIG_80211N_HT */\r
2371 \r
2372 void associated_clients_update(_adapter *padapter, u8 updated)\r
2373 {\r
2374         //update associcated stations cap.\r
2375         if(updated == _TRUE)\r
2376         {\r
2377                 _irqL irqL;\r
2378                 _list   *phead, *plist;\r
2379                 struct sta_info *psta=NULL;     \r
2380                 struct sta_priv *pstapriv = &padapter->stapriv;\r
2381                         \r
2382                 _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2383                 \r
2384                 phead = &pstapriv->asoc_list;\r
2385                 plist = get_next(phead);\r
2386                 \r
2387                 //check asoc_queue\r
2388                 while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
2389                 {\r
2390                         psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
2391                 \r
2392                         plist = get_next(plist);\r
2393 \r
2394                         VCS_update(padapter, psta);             \r
2395                 }\r
2396 \r
2397                 _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2398 \r
2399         }               \r
2400 \r
2401 }\r
2402 \r
2403 /* called > TSR LEVEL for USB or SDIO Interface*/\r
2404 void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta)\r
2405 {\r
2406         u8 beacon_updated = _FALSE;\r
2407         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2408         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);\r
2409 \r
2410         \r
2411 #if 0\r
2412         if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&\r
2413             !psta->no_short_preamble_set) {\r
2414                 psta->no_short_preamble_set = 1;\r
2415                 pmlmepriv->num_sta_no_short_preamble++;\r
2416                 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && \r
2417                      (pmlmepriv->num_sta_no_short_preamble == 1))\r
2418                         ieee802_11_set_beacons(hapd->iface);\r
2419         }\r
2420 #endif\r
2421 \r
2422 \r
2423         if(!(psta->flags & WLAN_STA_SHORT_PREAMBLE))    \r
2424         {\r
2425                 if(!psta->no_short_preamble_set)\r
2426                 {\r
2427                         psta->no_short_preamble_set = 1;\r
2428                         \r
2429                         pmlmepriv->num_sta_no_short_preamble++;\r
2430                         \r
2431                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && \r
2432                                 (pmlmepriv->num_sta_no_short_preamble == 1))\r
2433                         {\r
2434                                 beacon_updated = _TRUE;\r
2435                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2436                         }       \r
2437                         \r
2438                 }\r
2439         }\r
2440         else\r
2441         {\r
2442                 if(psta->no_short_preamble_set)\r
2443                 {\r
2444                         psta->no_short_preamble_set = 0;\r
2445                         \r
2446                         pmlmepriv->num_sta_no_short_preamble--;\r
2447                         \r
2448                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && \r
2449                                 (pmlmepriv->num_sta_no_short_preamble == 0))\r
2450                         {\r
2451                                 beacon_updated = _TRUE;\r
2452                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2453                         }       \r
2454                         \r
2455                 }\r
2456         }\r
2457 \r
2458 #if 0\r
2459         if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) {\r
2460                 psta->nonerp_set = 1;\r
2461                 pmlmepriv->num_sta_non_erp++;\r
2462                 if (pmlmepriv->num_sta_non_erp == 1)\r
2463                         ieee802_11_set_beacons(hapd->iface);\r
2464         }\r
2465 #endif\r
2466 \r
2467         if(psta->flags & WLAN_STA_NONERP)\r
2468         {\r
2469                 if(!psta->nonerp_set)\r
2470                 {\r
2471                         psta->nonerp_set = 1;\r
2472                         \r
2473                         pmlmepriv->num_sta_non_erp++;\r
2474                         \r
2475                         if (pmlmepriv->num_sta_non_erp == 1)\r
2476                         {\r
2477                                 beacon_updated = _TRUE;\r
2478                                 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);\r
2479                         }       \r
2480                 }\r
2481                 \r
2482         }\r
2483         else\r
2484         {\r
2485                 if(psta->nonerp_set)\r
2486                 {\r
2487                         psta->nonerp_set = 0;\r
2488                         \r
2489                         pmlmepriv->num_sta_non_erp--;\r
2490                         \r
2491                         if (pmlmepriv->num_sta_non_erp == 0)\r
2492                         {\r
2493                                 beacon_updated = _TRUE;\r
2494                                 update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);\r
2495                         }       \r
2496                 }\r
2497                 \r
2498         }\r
2499 \r
2500 \r
2501 #if 0\r
2502         if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) &&\r
2503             !psta->no_short_slot_time_set) {\r
2504                 psta->no_short_slot_time_set = 1;\r
2505                 pmlmepriv->num_sta_no_short_slot_time++;\r
2506                 if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&\r
2507                     (pmlmepriv->num_sta_no_short_slot_time == 1))\r
2508                         ieee802_11_set_beacons(hapd->iface);\r
2509         }\r
2510 #endif\r
2511 \r
2512         if(!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT))\r
2513         {\r
2514                 if(!psta->no_short_slot_time_set)\r
2515                 {\r
2516                         psta->no_short_slot_time_set = 1;\r
2517                         \r
2518                         pmlmepriv->num_sta_no_short_slot_time++;\r
2519                         \r
2520                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&\r
2521                                  (pmlmepriv->num_sta_no_short_slot_time == 1))\r
2522                         {\r
2523                                 beacon_updated = _TRUE;\r
2524                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2525                         }                       \r
2526                         \r
2527                 }\r
2528         }\r
2529         else\r
2530         {\r
2531                 if(psta->no_short_slot_time_set)\r
2532                 {\r
2533                         psta->no_short_slot_time_set = 0;\r
2534                         \r
2535                         pmlmepriv->num_sta_no_short_slot_time--;\r
2536                         \r
2537                         if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&\r
2538                                  (pmlmepriv->num_sta_no_short_slot_time == 0))\r
2539                         {\r
2540                                 beacon_updated = _TRUE;\r
2541                                 update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2542                         }                       \r
2543                 }\r
2544         }       \r
2545         \r
2546 #ifdef CONFIG_80211N_HT\r
2547 \r
2548         if (psta->flags & WLAN_STA_HT) \r
2549         {\r
2550                 u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);\r
2551                         \r
2552                 DBG_871X("HT: STA " MAC_FMT " HT Capabilities "\r
2553                            "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);\r
2554 \r
2555                 if (psta->no_ht_set) {\r
2556                         psta->no_ht_set = 0;\r
2557                         pmlmepriv->num_sta_no_ht--;\r
2558                 }\r
2559                 \r
2560                 if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {\r
2561                         if (!psta->no_ht_gf_set) {\r
2562                                 psta->no_ht_gf_set = 1;\r
2563                                 pmlmepriv->num_sta_ht_no_gf++;\r
2564                         }\r
2565                         DBG_871X("%s STA " MAC_FMT " - no "\r
2566                                    "greenfield, num of non-gf stations %d\n",\r
2567                                    __FUNCTION__, MAC_ARG(psta->hwaddr),\r
2568                                    pmlmepriv->num_sta_ht_no_gf);\r
2569                 }\r
2570                 \r
2571                 if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {\r
2572                         if (!psta->ht_20mhz_set) {\r
2573                                 psta->ht_20mhz_set = 1;\r
2574                                 pmlmepriv->num_sta_ht_20mhz++;\r
2575                         }\r
2576                         DBG_871X("%s STA " MAC_FMT " - 20 MHz HT, "\r
2577                                    "num of 20MHz HT STAs %d\n",\r
2578                                    __FUNCTION__, MAC_ARG(psta->hwaddr),\r
2579                                    pmlmepriv->num_sta_ht_20mhz);\r
2580                 }\r
2581                 \r
2582         } \r
2583         else \r
2584         {\r
2585                 if (!psta->no_ht_set) {\r
2586                         psta->no_ht_set = 1;\r
2587                         pmlmepriv->num_sta_no_ht++;\r
2588                 }\r
2589                 if(pmlmepriv->htpriv.ht_option == _TRUE) {              \r
2590                         DBG_871X("%s STA " MAC_FMT\r
2591                                    " - no HT, num of non-HT stations %d\n",\r
2592                                    __FUNCTION__, MAC_ARG(psta->hwaddr),\r
2593                                    pmlmepriv->num_sta_no_ht);\r
2594                 }\r
2595         }\r
2596 \r
2597         if (rtw_ht_operation_update(padapter) > 0)\r
2598         {\r
2599                 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);\r
2600                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);\r
2601         }       \r
2602         \r
2603 #endif /* CONFIG_80211N_HT */\r
2604 \r
2605         //update associcated stations cap.\r
2606         associated_clients_update(padapter,  beacon_updated);\r
2607 \r
2608         DBG_871X("%s, updated=%d\n", __func__, beacon_updated);\r
2609 \r
2610 }\r
2611 \r
2612 u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta)\r
2613 {\r
2614         u8 beacon_updated = _FALSE;\r
2615         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2616         struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);\r
2617 \r
2618         if(!psta)\r
2619                 return beacon_updated;\r
2620 \r
2621         if (psta->no_short_preamble_set) {\r
2622                 psta->no_short_preamble_set = 0;\r
2623                 pmlmepriv->num_sta_no_short_preamble--;\r
2624                 if (pmlmeext->cur_wireless_mode > WIRELESS_11B\r
2625                     && pmlmepriv->num_sta_no_short_preamble == 0)\r
2626                 {\r
2627                         beacon_updated = _TRUE;\r
2628                         update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2629                 }       \r
2630         }       \r
2631 \r
2632         if (psta->nonerp_set) {\r
2633                 psta->nonerp_set = 0;           \r
2634                 pmlmepriv->num_sta_non_erp--;\r
2635                 if (pmlmepriv->num_sta_non_erp == 0)\r
2636                 {\r
2637                         beacon_updated = _TRUE;\r
2638                         update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);\r
2639                 }       \r
2640         }\r
2641 \r
2642         if (psta->no_short_slot_time_set) {\r
2643                 psta->no_short_slot_time_set = 0;\r
2644                 pmlmepriv->num_sta_no_short_slot_time--;\r
2645                 if (pmlmeext->cur_wireless_mode > WIRELESS_11B\r
2646                     && pmlmepriv->num_sta_no_short_slot_time == 0)\r
2647                 {\r
2648                         beacon_updated = _TRUE;\r
2649                         update_beacon(padapter, 0xFF, NULL, _TRUE);\r
2650                 }       \r
2651         }\r
2652         \r
2653 #ifdef CONFIG_80211N_HT\r
2654 \r
2655         if (psta->no_ht_gf_set) {\r
2656                 psta->no_ht_gf_set = 0;\r
2657                 pmlmepriv->num_sta_ht_no_gf--;\r
2658         }\r
2659 \r
2660         if (psta->no_ht_set) {\r
2661                 psta->no_ht_set = 0;\r
2662                 pmlmepriv->num_sta_no_ht--;\r
2663         }\r
2664 \r
2665         if (psta->ht_20mhz_set) {\r
2666                 psta->ht_20mhz_set = 0;\r
2667                 pmlmepriv->num_sta_ht_20mhz--;\r
2668         }\r
2669 \r
2670         if (rtw_ht_operation_update(padapter) > 0)\r
2671         {\r
2672                 update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);\r
2673                 update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);\r
2674         }\r
2675         \r
2676 #endif /* CONFIG_80211N_HT */\r
2677 \r
2678         //update associcated stations cap.\r
2679         //associated_clients_update(padapter,  beacon_updated); //move it to avoid deadlock\r
2680 \r
2681         DBG_871X("%s, updated=%d\n", __func__, beacon_updated);\r
2682 \r
2683         return beacon_updated;\r
2684 \r
2685 }\r
2686 \r
2687 u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason)\r
2688 {\r
2689         _irqL irqL;\r
2690         u8 beacon_updated = _FALSE;\r
2691         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2692         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2693         struct sta_priv *pstapriv = &padapter->stapriv;\r
2694 \r
2695         if(!psta)\r
2696                 return beacon_updated;\r
2697 \r
2698         if (active == _TRUE)\r
2699         {\r
2700 #ifdef CONFIG_80211N_HT\r
2701                 //tear down Rx AMPDU\r
2702                 send_delba(padapter, 0, psta->hwaddr);// recipient\r
2703         \r
2704                 //tear down TX AMPDU\r
2705                 send_delba(padapter, 1, psta->hwaddr);// // originator\r
2706                 \r
2707 #endif //CONFIG_80211N_HT\r
2708 \r
2709                 issue_deauth(padapter, psta->hwaddr, reason);\r
2710         }\r
2711 \r
2712         psta->htpriv.agg_enable_bitmap = 0x0;//reset\r
2713         psta->htpriv.candidate_tid_bitmap = 0x0;//reset\r
2714 \r
2715 \r
2716         //report_del_sta_event(padapter, psta->hwaddr, reason);\r
2717 \r
2718         //clear cam entry / key\r
2719         //clear_cam_entry(padapter, (psta->mac_id + 3));\r
2720         rtw_clearstakey_cmd(padapter, (u8*)psta, (u8)rtw_get_camid(psta->mac_id), _TRUE);\r
2721 \r
2722 \r
2723         _enter_critical_bh(&psta->lock, &irqL);\r
2724         psta->state &= ~_FW_LINKED;\r
2725         _exit_critical_bh(&psta->lock, &irqL);\r
2726 \r
2727         #ifdef CONFIG_IOCTL_CFG80211\r
2728         if (1) {\r
2729                 #ifdef COMPAT_KERNEL_RELEASE\r
2730                 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);\r
2731                 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
2732                 rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);\r
2733                 #else //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
2734                 /* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */\r
2735                 #endif //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)\r
2736         } else\r
2737         #endif //CONFIG_IOCTL_CFG80211\r
2738         {\r
2739                 rtw_indicate_sta_disassoc_event(padapter, psta);\r
2740         }\r
2741 \r
2742         report_del_sta_event(padapter, psta->hwaddr, reason);\r
2743 \r
2744         beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);\r
2745 \r
2746         _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);                                  \r
2747         rtw_free_stainfo(padapter, psta);\r
2748         _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);\r
2749         \r
2750 \r
2751         return beacon_updated;\r
2752 \r
2753 }\r
2754 \r
2755 int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)\r
2756 {\r
2757         _irqL irqL;\r
2758         _list   *phead, *plist;\r
2759         int ret=0;      \r
2760         struct sta_info *psta = NULL;   \r
2761         struct sta_priv *pstapriv = &padapter->stapriv;\r
2762         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
2763         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2764         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};\r
2765 \r
2766         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)\r
2767                 return ret;\r
2768 \r
2769         DBG_871X(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",\r
2770                 FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);\r
2771 \r
2772         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2773         phead = &pstapriv->asoc_list;\r
2774         plist = get_next(phead);\r
2775         \r
2776         /* for each sta in asoc_queue */\r
2777         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)       \r
2778         {               \r
2779                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
2780                 plist = get_next(plist);\r
2781 \r
2782                 issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);\r
2783                 psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);\r
2784         }\r
2785         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2786 \r
2787         issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);\r
2788 \r
2789         return ret;\r
2790 }\r
2791 \r
2792 int rtw_sta_flush(_adapter *padapter)\r
2793 {\r
2794         _irqL irqL;\r
2795         _list   *phead, *plist;\r
2796         int ret=0;      \r
2797         struct sta_info *psta = NULL;   \r
2798         struct sta_priv *pstapriv = &padapter->stapriv;\r
2799         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
2800         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2801         u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};\r
2802 \r
2803         DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));\r
2804 \r
2805         if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)\r
2806                 return ret;\r
2807 \r
2808 \r
2809         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2810         phead = &pstapriv->asoc_list;\r
2811         plist = get_next(phead);\r
2812 \r
2813         //free sta asoc_queue\r
2814         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
2815         {\r
2816                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
2817                 \r
2818                 plist = get_next(plist);\r
2819 \r
2820                 rtw_list_delete(&psta->asoc_list);\r
2821                 pstapriv->asoc_list_cnt--;\r
2822 \r
2823                 //_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2824                 ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING);\r
2825                 //_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2826         }\r
2827         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2828 \r
2829 \r
2830         issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);\r
2831 \r
2832         associated_clients_update(padapter, _TRUE);\r
2833 \r
2834         return ret;\r
2835 \r
2836 }\r
2837 \r
2838 /* called > TSR LEVEL for USB or SDIO Interface*/\r
2839 void sta_info_update(_adapter *padapter, struct sta_info *psta)\r
2840 {       \r
2841         int flags = psta->flags;\r
2842         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2843         \r
2844                                 \r
2845         //update wmm cap.\r
2846         if(WLAN_STA_WME&flags)\r
2847                 psta->qos_option = 1;\r
2848         else\r
2849                 psta->qos_option = 0;\r
2850 \r
2851         if(pmlmepriv->qospriv.qos_option == 0)  \r
2852                 psta->qos_option = 0;\r
2853 \r
2854                 \r
2855 #ifdef CONFIG_80211N_HT         \r
2856         //update 802.11n ht cap.\r
2857         if(WLAN_STA_HT&flags)\r
2858         {\r
2859                 psta->htpriv.ht_option = _TRUE;\r
2860                 psta->qos_option = 1;   \r
2861         }\r
2862         else            \r
2863         {\r
2864                 psta->htpriv.ht_option = _FALSE;\r
2865         }\r
2866                 \r
2867         if(pmlmepriv->htpriv.ht_option == _FALSE)       \r
2868                 psta->htpriv.ht_option = _FALSE;\r
2869 #endif\r
2870 \r
2871 #ifdef CONFIG_80211AC_VHT\r
2872         //update 802.11AC vht cap.\r
2873         if(WLAN_STA_VHT&flags)\r
2874         {\r
2875                 psta->vhtpriv.vht_option = _TRUE;\r
2876         }\r
2877         else            \r
2878         {\r
2879                 psta->vhtpriv.vht_option = _FALSE;\r
2880         }\r
2881 \r
2882         if(pmlmepriv->vhtpriv.vht_option == _FALSE)\r
2883                 psta->vhtpriv.vht_option = _FALSE;\r
2884 #endif  \r
2885 \r
2886 \r
2887         update_sta_info_apmode(padapter, psta);\r
2888                 \r
2889 \r
2890 }\r
2891 \r
2892 /* called >= TSR LEVEL for USB or SDIO Interface*/\r
2893 void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta)\r
2894 {\r
2895         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
2896         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2897 \r
2898         if(psta->state & _FW_LINKED)\r
2899         {\r
2900                 pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;\r
2901         \r
2902                 //add ratid\r
2903                 add_RATid(padapter, psta, 0);//DM_RATR_STA_INIT\r
2904         }       \r
2905 }\r
2906 /* restore hw setting from sw data structures */\r
2907 void rtw_ap_restore_network(_adapter *padapter)\r
2908 {\r
2909         struct mlme_priv *mlmepriv = &padapter->mlmepriv;\r
2910         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;\r
2911         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2912         struct sta_priv * pstapriv = &padapter->stapriv;\r
2913         struct sta_info *psta;\r
2914         struct security_priv* psecuritypriv=&(padapter->securitypriv);\r
2915         _irqL irqL;\r
2916         _list   *phead, *plist;\r
2917         u8 chk_alive_num = 0;\r
2918         char chk_alive_list[NUM_STA];\r
2919         int i;\r
2920 \r
2921         rtw_setopmode_cmd(padapter, Ndis802_11APMode,_FALSE);\r
2922 \r
2923         set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);\r
2924 \r
2925         start_bss_network(padapter, (u8*)&mlmepriv->cur_network.network);\r
2926 \r
2927         if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||\r
2928                 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))\r
2929         {\r
2930                 /* restore group key, WEP keys is restored in ips_leave() */\r
2931                 rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0,_FALSE);\r
2932         }\r
2933 \r
2934         _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2935         \r
2936         phead = &pstapriv->asoc_list;\r
2937         plist = get_next(phead);\r
2938 \r
2939         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {\r
2940                 int stainfo_offset;\r
2941 \r
2942                 psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);\r
2943                 plist = get_next(plist);\r
2944 \r
2945                 stainfo_offset = rtw_stainfo_offset(pstapriv, psta);\r
2946                 if (stainfo_offset_valid(stainfo_offset)) {\r
2947                         chk_alive_list[chk_alive_num++] = stainfo_offset;\r
2948                 }\r
2949         }\r
2950 \r
2951         _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);\r
2952 \r
2953         for (i = 0; i < chk_alive_num; i++) {\r
2954                 psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);\r
2955 \r
2956                 if (psta == NULL) {\r
2957                         DBG_871X(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));\r
2958                 } else if (psta->state &_FW_LINKED) {\r
2959                         Update_RA_Entry(padapter, psta);\r
2960                         //pairwise key\r
2961                         /* per sta pairwise key and settings */\r
2962                         if(     (padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||\r
2963                                 (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))\r
2964                         {\r
2965                                 rtw_setstakey_cmd(padapter, (unsigned char *)psta, _TRUE,_FALSE);\r
2966                         }                       \r
2967                 }\r
2968         }\r
2969 \r
2970 }\r
2971 \r
2972 void start_ap_mode(_adapter *padapter)\r
2973 {\r
2974         int i;\r
2975         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2976         struct sta_priv *pstapriv = &padapter->stapriv;\r
2977         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
2978         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
2979         \r
2980         pmlmepriv->update_bcn = _FALSE;\r
2981         \r
2982         //init_mlme_ap_info(padapter);\r
2983         pmlmeext->bstart_bss = _FALSE;\r
2984 \r
2985         pmlmepriv->num_sta_non_erp = 0;\r
2986 \r
2987         pmlmepriv->num_sta_no_short_slot_time = 0;\r
2988 \r
2989         pmlmepriv->num_sta_no_short_preamble = 0;\r
2990 \r
2991         pmlmepriv->num_sta_ht_no_gf = 0;\r
2992 #ifdef CONFIG_80211N_HT\r
2993         pmlmepriv->num_sta_no_ht = 0;\r
2994 #endif //CONFIG_80211N_HT\r
2995         pmlmepriv->num_sta_ht_20mhz = 0;\r
2996 \r
2997         pmlmepriv->olbc = _FALSE;\r
2998 \r
2999         pmlmepriv->olbc_ht = _FALSE;\r
3000         \r
3001 #ifdef CONFIG_80211N_HT\r
3002         pmlmepriv->ht_op_mode = 0;\r
3003 #endif\r
3004 \r
3005         for(i=0; i<NUM_STA; i++)\r
3006                 pstapriv->sta_aid[i] = NULL;\r
3007 \r
3008         pmlmepriv->wps_beacon_ie = NULL;        \r
3009         pmlmepriv->wps_probe_resp_ie = NULL;\r
3010         pmlmepriv->wps_assoc_resp_ie = NULL;\r
3011         \r
3012         pmlmepriv->p2p_beacon_ie = NULL;\r
3013         pmlmepriv->p2p_probe_resp_ie = NULL;\r
3014 \r
3015         \r
3016         //for ACL \r
3017         _rtw_init_listhead(&(pacl_list->acl_node_q.queue));\r
3018         pacl_list->num = 0;\r
3019         pacl_list->mode = 0;\r
3020         for(i = 0; i < NUM_ACL; i++)\r
3021         {               \r
3022                 _rtw_init_listhead(&pacl_list->aclnode[i].list);\r
3023                 pacl_list->aclnode[i].valid = _FALSE;\r
3024         }\r
3025 \r
3026 }\r
3027 \r
3028 void stop_ap_mode(_adapter *padapter)\r
3029 {\r
3030         _irqL irqL;\r
3031         _list   *phead, *plist;\r
3032         struct rtw_wlan_acl_node *paclnode;\r
3033         struct sta_info *psta=NULL;\r
3034         struct sta_priv *pstapriv = &padapter->stapriv;\r
3035         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3036         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;        \r
3037         struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;\r
3038         _queue  *pacl_node_q =&pacl_list->acl_node_q;   \r
3039 \r
3040         pmlmepriv->update_bcn = _FALSE;\r
3041         pmlmeext->bstart_bss = _FALSE;\r
3042         //_rtw_spinlock_free(&pmlmepriv->bcn_update_lock);\r
3043         \r
3044         //reset and init security priv , this can refine with rtw_reset_securitypriv\r
3045         _rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv));\r
3046         padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;\r
3047         padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;\r
3048 \r
3049         //for ACL\r
3050         _enter_critical_bh(&(pacl_node_q->lock), &irqL);\r
3051         phead = get_list_head(pacl_node_q);\r
3052         plist = get_next(phead);                \r
3053         while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)\r
3054         {\r
3055                 paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);\r
3056                 plist = get_next(plist);\r
3057 \r
3058                 if(paclnode->valid == _TRUE)\r
3059                 {\r
3060                         paclnode->valid = _FALSE;\r
3061 \r
3062                         rtw_list_delete(&paclnode->list);\r
3063                                 \r
3064                         pacl_list->num--;               \r
3065                 }               \r
3066         }       \r
3067         _exit_critical_bh(&(pacl_node_q->lock), &irqL);\r
3068         \r
3069         DBG_871X("%s, free acl_node_queue, num=%d\n", __func__, pacl_list->num);\r
3070         \r
3071         rtw_sta_flush(padapter);\r
3072 \r
3073         //free_assoc_sta_resources      \r
3074         rtw_free_all_stainfo(padapter);\r
3075         \r
3076         psta = rtw_get_bcmc_stainfo(padapter);\r
3077         _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);          \r
3078         rtw_free_stainfo(padapter, psta);\r
3079         _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);\r
3080         \r
3081         rtw_init_bcmc_stainfo(padapter);        \r
3082 \r
3083         rtw_free_mlme_priv_ie_data(pmlmepriv);\r
3084 \r
3085 #ifdef CONFIG_BT_COEXIST\r
3086         rtw_btcoex_MediaStatusNotify(padapter, 0); //disconnect \r
3087 #endif  \r
3088 \r
3089 }\r
3090 \r
3091 #endif //CONFIG_NATIVEAP_MLME\r
3092 \r
3093 #ifdef CONFIG_CONCURRENT_MODE\r
3094 void concurrent_set_ap_chbw(_adapter *padapter, u8 channel, u8 channel_offset, u8 bwmode)\r
3095 {\r
3096         u8 *p;\r
3097         int     ie_len=0;\r
3098         u8 cur_channel, cur_bwmode, cur_ch_offset, change_band;\r
3099         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
3100         WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;\r
3101         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
3102         struct HT_info_element *pht_info=NULL;\r
3103         \r
3104         cur_channel = channel;\r
3105         cur_bwmode = bwmode;\r
3106         cur_ch_offset = channel_offset;\r
3107         change_band = _FALSE;\r
3108         \r
3109         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
3110         if( p && ie_len)\r
3111         {\r
3112                 pht_info = (struct HT_info_element *)(p+2);\r
3113         }\r
3114 \r
3115         \r
3116         if(!check_buddy_fwstate(padapter, _FW_LINKED|_FW_UNDER_LINKING|_FW_UNDER_SURVEY))\r
3117         {\r
3118                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
3119         }\r
3120         else if(check_buddy_fwstate(padapter, _FW_LINKED)==_TRUE)//only second adapter can enter AP Mode\r
3121         {\r
3122                 _adapter *pbuddy_adapter = padapter->pbuddy_adapter;            \r
3123                 struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;\r
3124         \r
3125                 //To sync cur_channel/cur_bwmode/cur_ch_offset with primary adapter\r
3126                 DBG_871X("primary iface is at linked state, sync cur_channel/cur_bwmode/cur_ch_offset\n");\r
3127                 DBG_871X("primary adapter, CH=%d, BW=%d, offset=%d\n", pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_bwmode, pbuddy_mlmeext->cur_ch_offset);\r
3128                 DBG_871X("second adapter, CH=%d, BW=%d, offset=%d\n", cur_channel, cur_bwmode, cur_ch_offset);\r
3129 \r
3130                 if((cur_channel <= 14 && pbuddy_mlmeext->cur_channel >= 36) ||\r
3131                         (cur_channel >= 36 && pbuddy_mlmeext->cur_channel <= 14))\r
3132                         change_band = _TRUE;\r
3133 \r
3134                 cur_channel = pbuddy_mlmeext->cur_channel;\r
3135 \r
3136 #ifdef CONFIG_80211AC_VHT\r
3137                 if(cur_bwmode == CHANNEL_WIDTH_80)\r
3138                 {\r
3139                         u8 *pvht_cap_ie, *pvht_op_ie;\r
3140                         int vht_cap_ielen, vht_op_ielen;\r
3141                         \r
3142                         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
3143                         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
3144                                                 \r
3145                         if(pbuddy_mlmeext->cur_channel <= 14) // downgrade to 20/40Mhz\r
3146                         {\r
3147                                 //modify vht cap ie\r
3148                                 if( pvht_cap_ie && vht_cap_ielen)\r
3149                                 {\r
3150                                         SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvht_cap_ie+2, 0);\r
3151                                 }\r
3152                                 \r
3153                                 //modify vht op ie\r
3154                                 if( pvht_op_ie && vht_op_ielen)\r
3155                                 {\r
3156                                         SET_VHT_OPERATION_ELE_CHL_WIDTH(pvht_op_ie+2, 0); //change to 20/40Mhz\r
3157                                         SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pvht_op_ie+2, 0);\r
3158                                         SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(pvht_op_ie+2, 0);\r
3159                                         //SET_VHT_OPERATION_ELE_BASIC_MCS_SET(p+2, 0xFFFF);                                     \r
3160                                         cur_bwmode = CHANNEL_WIDTH_40;\r
3161                                 }               \r
3162                         }\r
3163                         else\r
3164                         {\r
3165                                 u8      center_freq;\r
3166                                 \r
3167                                 cur_bwmode = CHANNEL_WIDTH_80;\r
3168                                 \r
3169                                 if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||\r
3170                                         pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80)\r
3171                                 {\r
3172                                         cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;\r
3173                                 }\r
3174                                 else if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_20)\r
3175                                 {\r
3176                                         cur_ch_offset =  rtw_get_offset_by_ch(cur_channel);\r
3177                                 }       \r
3178 \r
3179                                 //modify ht info ie\r
3180                                 if(pht_info)\r
3181                                         pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;\r
3182                                 \r
3183                                 switch(cur_ch_offset)\r
3184                                 {\r
3185                                         case HAL_PRIME_CHNL_OFFSET_LOWER:\r
3186                                                 if(pht_info)\r
3187                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;            \r
3188                                                 //cur_bwmode = CHANNEL_WIDTH_40;\r
3189                                                 break;\r
3190                                         case HAL_PRIME_CHNL_OFFSET_UPPER:\r
3191                                                 if(pht_info)\r
3192                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;                                            \r
3193                                                 //cur_bwmode = CHANNEL_WIDTH_40;\r
3194                                                 break;\r
3195                                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   \r
3196                                         default:\r
3197                                                 if(pht_info)\r
3198                                                         pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;\r
3199                                                 cur_bwmode = CHANNEL_WIDTH_20;\r
3200                                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
3201                                                 break;                                  \r
3202                                 }\r
3203 \r
3204                                 //modify vht op ie\r
3205                                 center_freq = rtw_get_center_ch(cur_channel, cur_bwmode, HAL_PRIME_CHNL_OFFSET_LOWER);\r
3206                                 if( pvht_op_ie && vht_op_ielen)\r
3207                                         SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(pvht_op_ie+2, center_freq);\r
3208 \r
3209                                 set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
3210                                 \r
3211                         }\r
3212                         \r
3213                 }\r
3214 #endif //CONFIG_80211AC_VHT\r
3215 \r
3216                 if(cur_bwmode == CHANNEL_WIDTH_40)\r
3217                 {\r
3218                         if(pht_info)\r
3219                                 pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;\r
3220                         \r
3221                         if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_40 ||\r
3222                                 pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_80)\r
3223                         {\r
3224                                 cur_ch_offset = pbuddy_mlmeext->cur_ch_offset;\r
3225 \r
3226                                 //to update cur_ch_offset value in beacon\r
3227                                 if(pht_info)\r
3228                                 {                               \r
3229                                         switch(cur_ch_offset)\r
3230                                         {\r
3231                                                 case HAL_PRIME_CHNL_OFFSET_LOWER:\r
3232                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;\r
3233                                                         break;\r
3234                                                 case HAL_PRIME_CHNL_OFFSET_UPPER:\r
3235                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;\r
3236                                                         break;\r
3237                                                 case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   \r
3238                                                 default:                                                        \r
3239                                                         break;                                  \r
3240                                         }\r
3241                                 }               \r
3242                                 \r
3243                         }\r
3244                         else if(pbuddy_mlmeext->cur_bwmode == CHANNEL_WIDTH_20)\r
3245                         {\r
3246                                 cur_ch_offset =  rtw_get_offset_by_ch(cur_channel);\r
3247 \r
3248                                 switch(cur_ch_offset)\r
3249                                 {\r
3250                                         case HAL_PRIME_CHNL_OFFSET_LOWER:\r
3251                                                 if(pht_info)\r
3252                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;            \r
3253                                                 cur_bwmode = CHANNEL_WIDTH_40;\r
3254                                                 break;\r
3255                                         case HAL_PRIME_CHNL_OFFSET_UPPER:\r
3256                                                 if(pht_info)\r
3257                                                         pht_info->infos[0] |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;                                            \r
3258                                                 cur_bwmode = CHANNEL_WIDTH_40;\r
3259                                                 break;\r
3260                                         case HAL_PRIME_CHNL_OFFSET_DONT_CARE:                                                   \r
3261                                         default:\r
3262                                                 if(pht_info)\r
3263                                                         pht_info->infos[0] &= ~HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;\r
3264                                                 cur_bwmode = CHANNEL_WIDTH_20;\r
3265                                                 cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;\r
3266                                                 break;                                  \r
3267                                 }                                               \r
3268                                 \r
3269                         }\r
3270 \r
3271                         set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);\r
3272                         \r
3273                 }\r
3274                 else\r
3275                 {               \r
3276                         //follow buddy's ch/bw/ch_offset setting, needn't set ch_bw again.\r
3277                         //set_channel_bwmode(padapter, cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);\r
3278                 }               \r
3279 \r
3280                 // to update channel value in beacon\r
3281                 pnetwork->Configuration.DSConfig = cur_channel;         \r
3282                 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
3283                 if(p && ie_len>0)\r
3284                         *(p + 2) = cur_channel;\r
3285                 \r
3286                 if(pht_info)\r
3287                         pht_info->primary_channel = cur_channel;\r
3288         }\r
3289 \r
3290         DBG_871X("%s, CH=%d, BW=%d, offset=%d\n", __FUNCTION__, cur_channel, cur_bwmode, cur_ch_offset);\r
3291 \r
3292         pmlmeext->cur_channel = cur_channel;    \r
3293         pmlmeext->cur_bwmode = cur_bwmode;\r
3294         pmlmeext->cur_ch_offset = cur_ch_offset;\r
3295 \r
3296         //buddy interface band is different from current interface, update ERP, support rate, ext support rate IE\r
3297         if(change_band == _TRUE)\r
3298                 change_band_update_ie(padapter, pnetwork);\r
3299 \r
3300 }\r
3301 #endif //CONFIG_CONCURRENT_MODE\r
3302 \r
3303 #endif //CONFIG_AP_MODE\r
3304 \r