1 /******************************************************************************
\r
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
\r
5 * This program is free software; you can redistribute it and/or modify it
\r
6 * under the terms of version 2 of the GNU General Public License as
\r
7 * published by the Free Software Foundation.
\r
9 * This program is distributed in the hope that it will be useful, but WITHOUT
\r
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
14 * You should have received a copy of the GNU General Public License along with
\r
15 * this program; if not, write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
\r
19 ******************************************************************************/
\r
20 #define _RTW_TDLS_C_
\r
22 #include <drv_types.h>
\r
23 #include <ethernet.h>
\r
24 #include <rtw_tdls.h>
\r
28 extern unsigned char MCS_rate_2R[16];
\r
29 extern unsigned char MCS_rate_1R[16];
\r
30 extern void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame);
\r
31 extern s32 rtw_dump_xframe(_adapter *padapter, struct xmit_frame *pxmitframe);
\r
33 void rtw_reset_tdls_info(_adapter* padapter)
\r
35 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
37 ptdlsinfo->ap_prohibited = _FALSE;
\r
38 ptdlsinfo->setup_state = TDLS_STATE_NONE;
\r
39 ptdlsinfo->sta_cnt = 0;
\r
40 ptdlsinfo->sta_maximum = _FALSE;
\r
41 ptdlsinfo->macid_index= 6;
\r
42 ptdlsinfo->clear_cam= 0;
\r
43 ptdlsinfo->ch_sensing = 0;
\r
44 ptdlsinfo->cur_channel = 0;
\r
45 ptdlsinfo->candidate_ch = 1; //when inplement channel switching, default candidate channel is 1
\r
46 ptdlsinfo->watchdog_count = 0;
\r
47 ptdlsinfo->dev_discovered = 0;
\r
50 ptdlsinfo->wfd_info = &padapter->wfd_info;
\r
54 int rtw_init_tdls_info(_adapter* padapter)
\r
57 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
59 ptdlsinfo->enable = 1;
\r
60 rtw_reset_tdls_info(padapter);
\r
62 _rtw_spinlock_init(&ptdlsinfo->cmd_lock);
\r
63 _rtw_spinlock_init(&ptdlsinfo->hdl_lock);
\r
69 void rtw_free_tdls_info(struct tdls_info *ptdlsinfo)
\r
71 _rtw_spinlock_free(&ptdlsinfo->cmd_lock);
\r
72 _rtw_spinlock_free(&ptdlsinfo->hdl_lock);
\r
74 _rtw_memset(ptdlsinfo, 0, sizeof(struct tdls_info) );
\r
78 void issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, struct sta_info *ptdls_sta, unsigned int power_mode)
\r
80 struct xmit_frame *pmgntframe;
\r
81 struct pkt_attrib *pattrib;
\r
82 unsigned char *pframe;
\r
83 struct rtw_ieee80211_hdr *pwlanhdr;
\r
84 unsigned short *fctrl;
\r
85 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
86 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
87 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
89 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
95 pattrib = &pmgntframe->attrib;
\r
96 update_mgntframe_attrib(padapter, pattrib);
\r
98 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
\r
100 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
\r
101 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
\r
103 fctrl = &(pwlanhdr->frame_ctl);
\r
111 _rtw_memcpy(pwlanhdr->addr1, ptdls_sta->hwaddr, ETH_ALEN);
\r
112 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
113 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
\r
115 ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority]++;
\r
116 ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;
\r
117 pattrib->seqnum = ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority];
\r
118 SetSeqNum(pwlanhdr, pattrib->seqnum);
\r
120 SetFrameSubType(pframe, WIFI_DATA_NULL);
\r
122 pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
\r
123 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
\r
125 pattrib->last_txcmdsz = pattrib->pktlen;
\r
126 dump_mgntframe(padapter, pmgntframe);
\r
131 s32 update_tdls_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
\r
134 struct sta_info *psta = NULL;
\r
135 struct sta_priv *pstapriv = &padapter->stapriv;
\r
136 struct security_priv *psecuritypriv = &padapter->securitypriv;
\r
137 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
138 struct qos_priv *pqospriv= &pmlmepriv->qospriv;
\r
143 bmcast = IS_MCAST(pattrib->ra);
\r
145 psta = rtw_get_stainfo(pstapriv, pattrib->ra);
\r
146 if (psta == NULL) {
\r
151 pattrib->mac_id = psta->mac_id;
\r
153 pattrib->psta = psta;
\r
155 pattrib->ack_policy = 0;
\r
156 // get ether_hdr_len
\r
157 pattrib->pkt_hdrlen = ETH_HLEN;//(pattrib->ether_type == 0x8100) ? (14 + 4 ): 14; //vlan tag
\r
159 if (pqospriv->qos_option && psta->qos_option) {
\r
160 pattrib->priority = 1; //tdls management frame should be AC_BK
\r
161 pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
\r
162 pattrib->subtype = WIFI_QOS_DATA_TYPE;
\r
164 pattrib->hdrlen = WLAN_HDR_A3_LEN;
\r
165 pattrib->subtype = WIFI_DATA_TYPE;
\r
166 pattrib->priority = 0;
\r
169 if (psta->ieee8021x_blocked == _TRUE)
\r
171 pattrib->encrypt = 0;
\r
175 GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
\r
177 switch(psecuritypriv->dot11AuthAlgrthm)
\r
179 case dot11AuthAlgrthm_Open:
\r
180 case dot11AuthAlgrthm_Shared:
\r
181 case dot11AuthAlgrthm_Auto:
\r
182 pattrib->key_idx = (u8)psecuritypriv->dot11PrivacyKeyIndex;
\r
184 case dot11AuthAlgrthm_8021X:
\r
185 pattrib->key_idx = 0;
\r
188 pattrib->key_idx = 0;
\r
193 switch (pattrib->encrypt)
\r
197 pattrib->iv_len = 4;
\r
198 pattrib->icv_len = 4;
\r
201 pattrib->iv_len = 8;
\r
202 pattrib->icv_len = 4;
\r
203 if(padapter->securitypriv.busetkipkey==_FAIL)
\r
210 pattrib->iv_len = 8;
\r
211 pattrib->icv_len = 8;
\r
214 pattrib->iv_len = 0;
\r
215 pattrib->icv_len = 0;
\r
219 if (pattrib->encrypt &&
\r
220 ((padapter->securitypriv.sw_encrypt == _TRUE) || (psecuritypriv->hw_decrypted == _FALSE)))
\r
222 pattrib->bswenc = _TRUE;
\r
224 pattrib->bswenc = _FALSE;
\r
227 //qos_en, ht_en, init rate, ,bw, ch_offset, sgi
\r
228 pattrib->qos_en = psta->qos_option;
\r
229 pattrib->ht_en = psta->htpriv.ht_option;
\r
230 pattrib->raid = psta->raid;
\r
231 pattrib->bwmode = psta->htpriv.bwmode;
\r
232 pattrib->ch_offset = psta->htpriv.ch_offset;
\r
233 pattrib->sgi= psta->htpriv.sgi;
\r
234 pattrib->ampdu_en = _FALSE;
\r
236 //if(pattrib->ht_en && psta->htpriv.ampdu_enable)
\r
238 // if(psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority))
\r
239 // pattrib->ampdu_en = _TRUE;
\r
247 void free_tdls_sta(_adapter *padapter, struct sta_info *ptdls_sta)
\r
249 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
250 struct sta_priv *pstapriv = &padapter->stapriv;
\r
253 //free peer sta_info
\r
254 _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
255 if(ptdlsinfo->sta_cnt != 0)
\r
256 ptdlsinfo->sta_cnt--;
\r
257 _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
258 if( ptdlsinfo->sta_cnt < (NUM_STA - 2) ) // -2: AP + BC/MC sta
\r
260 ptdlsinfo->sta_maximum = _FALSE;
\r
261 _rtw_memset( &ptdlsinfo->ss_record, 0x00, sizeof(struct tdls_ss_record) );
\r
263 //ready to clear cam
\r
264 if(ptdls_sta->mac_id!=0){
\r
265 ptdlsinfo->clear_cam=ptdls_sta->mac_id;
\r
266 rtw_setstakey_cmd(padapter, (u8 *)ptdls_sta, _TRUE, _TRUE);
\r
269 if(ptdlsinfo->sta_cnt==0){
\r
270 rtw_tdls_cmd(padapter, myid(&(padapter->eeprompriv)), TDLS_RS_RCR);
\r
271 ptdlsinfo->setup_state=TDLS_STATE_NONE;
\r
274 DBG_871X("Remain tdls sta:%02x\n", ptdlsinfo->sta_cnt);
\r
276 rtw_free_stainfo(padapter, ptdls_sta);
\r
280 // cam entry will be the same as mac_id
\r
281 void rtw_tdls_set_mac_id(struct tdls_info *ptdlsinfo, struct sta_info *ptdls_sta)
\r
283 if(ptdls_sta->mac_id==0)
\r
285 ptdls_sta->mac_id = ptdlsinfo->macid_index;
\r
286 if( (++ptdlsinfo->macid_index) > (NUM_STA -2) )
\r
287 ptdlsinfo->macid_index= TDLS_INI_MACID_ENTRY;
\r
291 //TDLS encryption(if needed) will always be CCMP
\r
292 void rtw_tdls_set_key(_adapter *adapter, struct rx_pkt_attrib *prx_pkt_attrib, struct sta_info *ptdls_sta)
\r
294 if(prx_pkt_attrib->encrypt)
\r
296 ptdls_sta->dot118021XPrivacy=_AES_;
\r
297 rtw_setstakey_cmd(adapter, (u8*)ptdls_sta, _TRUE, _TRUE);
\r
301 void rtw_tdls_process_ht_cap(_adapter *adapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)
\r
303 /* save HT capabilities in the sta object */
\r
304 _rtw_memset(&ptdls_sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
\r
305 if (data && Length >= sizeof(struct rtw_ieee80211_ht_cap) )
\r
307 ptdls_sta->flags |= WLAN_STA_HT;
\r
309 ptdls_sta->flags |= WLAN_STA_WME;
\r
311 _rtw_memcpy(&ptdls_sta->htpriv.ht_cap, data, sizeof(struct rtw_ieee80211_ht_cap));
\r
314 ptdls_sta->flags &= ~WLAN_STA_HT;
\r
316 if(ptdls_sta->flags & WLAN_STA_HT)
\r
318 if(adapter->registrypriv.ht_enable == _TRUE)
\r
320 ptdls_sta->htpriv.ht_option = _TRUE;
\r
324 ptdls_sta->htpriv.ht_option = _FALSE;
\r
325 ptdls_sta->stat_code = _STATS_FAILURE_;
\r
330 if(ptdls_sta->htpriv.ht_option)
\r
332 //check if sta supports rx ampdu
\r
333 if(adapter->registrypriv.ampdu_enable==1)
\r
334 ptdls_sta->htpriv.ampdu_enable = _TRUE;
\r
336 //check if sta support s Short GI
\r
337 if(ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_20|IEEE80211_HT_CAP_SGI_40))
\r
339 ptdls_sta->htpriv.sgi = _TRUE;
\r
342 // bwmode would still followed AP's setting
\r
343 if(ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))
\r
345 ptdls_sta->htpriv.bwmode = adapter->mlmeextpriv.cur_bwmode;
\r
346 ptdls_sta->htpriv.ch_offset = adapter->mlmeextpriv.cur_ch_offset;
\r
351 u8 *rtw_tdls_set_ht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
353 struct rtw_ieee80211_ht_cap ht_capie;
\r
357 _rtw_memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap));
\r
359 ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH |IEEE80211_HT_CAP_SGI_20 |IEEE80211_HT_CAP_SM_PS |
\r
360 IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_TX_STBC |IEEE80211_HT_CAP_DSSSCCK40;
\r
363 u32 rx_packet_offset, max_recvbuf_sz;
\r
364 padapter->HalFunc.GetHalDefVarHandler(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
\r
365 padapter->HalFunc.GetHalDefVarHandler(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
\r
366 if(max_recvbuf_sz-rx_packet_offset>(8191-256))
\r
367 ht_capie.cap_info = ht_capie.cap_info |IEEE80211_HT_CAP_MAX_AMSDU;
\r
370 ht_capie.ampdu_params_info = (IEEE80211_HT_CAP_AMPDU_FACTOR&0x03);
\r
372 padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
\r
376 ht_capie.cap_info |= 0x0100;//RX STBC One spatial stream
\r
377 _rtw_memcpy(ht_capie.supp_mcs_set, MCS_rate_1R, 16);
\r
383 ht_capie.cap_info|= 0x0200;//RX STBC two spatial stream
\r
384 _rtw_memcpy(ht_capie.supp_mcs_set, MCS_rate_2R, 16);
\r
388 return(rtw_set_ie(pframe, _HT_CAPABILITY_IE_,
\r
389 sizeof(struct rtw_ieee80211_ht_cap), (unsigned char*)&ht_capie, &(pattrib->pktlen)));
\r
392 u8 *rtw_tdls_set_sup_ch(struct mlme_ext_priv *pmlmeext, u8 *pframe, struct pkt_attrib *pattrib)
\r
394 u8 sup_ch[ 30 * 2 ] = { 0x00 }, sup_ch_idx = 0, idx_5g = 2; //For supported channel
\r
396 if( pmlmeext->channel_set[sup_ch_idx].ChannelNum <= 14 )
\r
398 sup_ch[0] = 1; //First channel number
\r
399 sup_ch[1] = pmlmeext->channel_set[sup_ch_idx].ChannelNum; //Number of channel
\r
403 sup_ch[idx_5g++] = pmlmeext->channel_set[sup_ch_idx].ChannelNum;
\r
404 sup_ch[idx_5g++] = 1;
\r
409 while( pmlmeext->channel_set[sup_ch_idx].ChannelNum != 0 );
\r
410 return(rtw_set_ie(pframe, _SUPPORTED_CH_IE_, idx_5g, sup_ch, &(pattrib->pktlen)));
\r
414 void rtw_tdls_process_wfd_ie(struct tdls_info *ptdlsinfo, u8 *ptr, u8 length)
\r
416 u8 wfd_ie[ 128 ] = { 0x00 };
\r
418 u32 wfd_offset = 0;
\r
419 // Try to get the TCP port information when receiving the negotiation response.
\r
423 wfd_offset = rtw_get_wfd_ie( ptr + wfd_offset, length - wfd_offset, wfd_ie, &wfd_ielen );
\r
424 while( wfd_offset )
\r
426 u8 attr_content[ 10 ] = { 0x00 };
\r
427 u32 attr_contentlen = 0;
\r
430 DBG_871X( "[%s] WFD IE Found!!\n", __FUNCTION__ );
\r
431 rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
\r
432 if ( attr_contentlen )
\r
434 ptdlsinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );
\r
435 DBG_871X( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, ptdlsinfo->wfd_info->peer_rtsp_ctrlport );
\r
438 _rtw_memset( attr_content, 0x00, 10);
\r
439 attr_contentlen = 0;
\r
440 rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_LOCAL_IP_ADDR, attr_content, &attr_contentlen);
\r
441 if ( attr_contentlen )
\r
443 _rtw_memcpy(ptdlsinfo->wfd_info->peer_ip_address, ( attr_content + 1 ), 4);
\r
444 DBG_871X( "[%s] Peer IP = %02u.%02u.%02u.%02u \n", __FUNCTION__,
\r
445 ptdlsinfo->wfd_info->peer_ip_address[0], ptdlsinfo->wfd_info->peer_ip_address[1],
\r
446 ptdlsinfo->wfd_info->peer_ip_address[2], ptdlsinfo->wfd_info->peer_ip_address[3]
\r
449 wfd_offset = rtw_get_wfd_ie( ptr + wfd_offset, length - wfd_offset, wfd_ie, &wfd_ielen );
\r
453 void issue_tunneled_probe_req(_adapter *padapter)
\r
455 struct xmit_frame *pmgntframe;
\r
456 struct pkt_attrib *pattrib;
\r
457 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
458 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
459 u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
\r
461 DBG_871X("[%s]\n", __FUNCTION__);
\r
463 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
469 pattrib = &pmgntframe->attrib;
\r
471 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
472 pattrib->ether_type = 0x890d;
\r
475 _rtw_memcpy(pattrib->dst, baddr, ETH_ALEN);
\r
477 _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
479 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
480 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
482 update_tdls_attrib(padapter, pattrib);
\r
483 pattrib->qsel=pattrib->priority;
\r
484 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TUNNELED_PROBE_REQ) != _SUCCESS) {
\r
485 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
486 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
489 rtw_dump_xframe(padapter, pmgntframe);
\r
496 void issue_tunneled_probe_rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
498 struct xmit_frame *pmgntframe;
\r
499 struct pkt_attrib *pattrib;
\r
500 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
501 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
502 struct rx_pkt_attrib *rx_pkt_pattrib = &precv_frame->u.hdr.attrib;
\r
504 DBG_871X("[%s]\n", __FUNCTION__);
\r
506 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
512 pattrib = &pmgntframe->attrib;
\r
514 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
515 pattrib->ether_type = 0x890d;
\r
518 _rtw_memcpy(pattrib->dst, rx_pkt_pattrib->src, ETH_ALEN);
\r
520 _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
522 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
523 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
525 update_tdls_attrib(padapter, pattrib);
\r
526 pattrib->qsel=pattrib->priority;
\r
527 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TUNNELED_PROBE_RSP) != _SUCCESS) {
\r
528 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
529 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
532 rtw_dump_xframe(padapter, pmgntframe);
\r
538 #endif //CONFIG_WFD
\r
540 void issue_tdls_setup_req(_adapter *padapter, u8 *mac_addr)
\r
542 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
543 struct xmit_frame *pmgntframe;
\r
544 struct pkt_attrib *pattrib;
\r
545 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
546 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
547 struct sta_priv *pstapriv = &padapter->stapriv;
\r
548 struct sta_info *ptdls_sta= NULL;
\r
550 static u8 dialogtoken = 0;
\r
551 u32 timeout_interval= TPK_RESEND_COUNT * 1000; //retry timer should set at least 301 sec, using TPK_count counting 301 times.
\r
553 if(ptdlsinfo->ap_prohibited == _TRUE)
\r
556 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
562 pattrib = &pmgntframe->attrib;
\r
564 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
565 pattrib->ether_type = 0x890d;
\r
566 pattrib->pctrl =0;
\r
568 _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);
\r
569 _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
571 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
572 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
574 update_tdls_attrib(padapter, pattrib);
\r
576 //init peer sta_info
\r
577 ptdls_sta = rtw_get_stainfo(pstapriv, mac_addr);
\r
578 if(ptdls_sta==NULL)
\r
580 ptdls_sta = rtw_alloc_stainfo(pstapriv, mac_addr);
\r
583 _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
584 if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
\r
585 ptdlsinfo->sta_cnt++;
\r
586 _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
587 if( ptdlsinfo->sta_cnt == (NUM_STA - 2) ) // -2: AP + BC/MC sta
\r
589 ptdlsinfo->sta_maximum = _TRUE;
\r
594 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
595 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
601 ptdls_sta->tdls_sta_state |= TDLS_RESPONDER_STATE;
\r
602 //for tdls; ptdls_sta->aid is used to fill dialogtoken
\r
603 ptdls_sta->dialog = dialogtoken;
\r
604 dialogtoken = (dialogtoken+1)%256;
\r
605 ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
\r
606 _set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME );
\r
609 pattrib->qsel=pattrib->priority;
\r
610 if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_SETUP_REQUEST) !=_SUCCESS ){
\r
611 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
612 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
615 rtw_dump_xframe(padapter, pmgntframe);
\r
622 void issue_tdls_teardown(_adapter *padapter, u8 *mac_addr)
\r
624 struct xmit_frame *pmgntframe;
\r
625 struct pkt_attrib *pattrib;
\r
626 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
627 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
628 struct sta_priv *pstapriv = &padapter->stapriv;
\r
629 struct sta_info *ptdls_sta=NULL;
\r
632 ptdls_sta = rtw_get_stainfo(pstapriv, mac_addr);
\r
633 if(ptdls_sta==NULL){
\r
634 DBG_871X("issue tdls teardown unsuccessful\n");
\r
637 ptdls_sta->tdls_sta_state=TDLS_STATE_NONE;
\r
640 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
646 pattrib = &pmgntframe->attrib;
\r
648 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
649 pattrib->ether_type = 0x890d;
\r
652 _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);
\r
653 _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
655 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
656 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
658 update_tdls_attrib(padapter, pattrib);
\r
659 pattrib->qsel=pattrib->priority;
\r
660 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_TEARDOWN) != _SUCCESS) {
\r
661 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
662 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
665 rtw_dump_xframe(padapter, pmgntframe);
\r
667 if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE){
\r
668 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CS_OFF);
\r
671 if( ptdls_sta->timer_flag == 1 )
\r
673 _enter_critical_bh(&(padapter->tdlsinfo.hdl_lock), &irqL);
\r
674 ptdls_sta->timer_flag = 2;
\r
675 _exit_critical_bh(&(padapter->tdlsinfo.hdl_lock), &irqL);
\r
678 rtw_tdls_cmd(padapter, mac_addr, TDLS_FREE_STA );
\r
686 void issue_tdls_dis_req(_adapter *padapter, u8 *mac_addr)
\r
688 struct xmit_frame *pmgntframe;
\r
689 struct pkt_attrib *pattrib;
\r
690 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
691 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
692 u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
\r
694 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
700 pattrib = &pmgntframe->attrib;
\r
702 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
703 pattrib->ether_type = 0x890d;
\r
706 if(mac_addr == NULL)
\r
707 _rtw_memcpy(pattrib->dst, baddr, ETH_ALEN);
\r
709 _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);
\r
711 _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
713 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
714 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
716 update_tdls_attrib(padapter, pattrib);
\r
717 pattrib->qsel=pattrib->priority;
\r
718 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_DISCOVERY_REQUEST) != _SUCCESS) {
\r
719 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
720 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
723 rtw_dump_xframe(padapter, pmgntframe);
\r
724 DBG_871X("issue tdls dis req\n");
\r
731 void issue_tdls_setup_rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
733 struct xmit_frame *pmgntframe;
\r
734 struct pkt_attrib *pattrib;
\r
735 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
736 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
737 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
738 struct rx_pkt_attrib *rx_pkt_pattrib = &precv_frame->u.hdr.attrib;
\r
741 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
747 pattrib = &pmgntframe->attrib;
\r
749 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
750 pattrib->ether_type = 0x890d;
\r
753 _rtw_memcpy(pattrib->dst, rx_pkt_pattrib->src, ETH_ALEN);
\r
754 _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
756 _rtw_memcpy(pattrib->ra, rx_pkt_pattrib->bssid, ETH_ALEN);
\r
757 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
759 update_tdls_attrib(padapter, pattrib);
\r
760 pattrib->qsel=pattrib->priority;
\r
761 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_SETUP_RESPONSE) != _SUCCESS) {
\r
762 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
763 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
766 rtw_dump_xframe(padapter, pmgntframe);
\r
774 void issue_tdls_setup_cfm(_adapter *padapter, union recv_frame *precv_frame)
\r
776 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
777 struct xmit_frame *pmgntframe;
\r
778 struct pkt_attrib *pattrib;
\r
779 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
780 struct sta_info *ptdls_sta=NULL;
\r
783 struct rx_pkt_attrib *rx_pkt_pattrib = & precv_frame->u.hdr.attrib;
\r
785 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
791 pattrib = &pmgntframe->attrib;
\r
793 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
794 pattrib->ether_type = 0x890d;
\r
797 _rtw_memcpy(pattrib->dst, rx_pkt_pattrib->src, ETH_ALEN);
\r
798 _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
800 _rtw_memcpy(pattrib->ra, rx_pkt_pattrib->bssid, ETH_ALEN);
\r
801 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
803 update_tdls_attrib(padapter, pattrib);
\r
804 pattrib->qsel=pattrib->priority;
\r
805 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_SETUP_CONFIRM) != _SUCCESS) {
\r
806 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
807 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
811 rtw_dump_xframe(padapter, pmgntframe);
\r
819 //TDLS Discovery Response frame is a management action frame
\r
820 void issue_tdls_dis_rsp(_adapter *padapter, union recv_frame *precv_frame, u8 dialog)
\r
822 struct xmit_frame *pmgntframe;
\r
823 struct pkt_attrib *pattrib;
\r
824 unsigned char *pframe;
\r
825 struct rtw_ieee80211_hdr *pwlanhdr;
\r
826 unsigned short *fctrl;
\r
827 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
828 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
830 struct rx_pkt_attrib *rx_pkt_pattrib = &precv_frame->u.hdr.attrib;
\r
832 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
838 pattrib = &pmgntframe->attrib;
\r
839 update_mgntframe_attrib(padapter, pattrib);
\r
841 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
\r
843 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
\r
844 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
\r
846 fctrl = &(pwlanhdr->frame_ctl);
\r
849 // unicast probe request frame
\r
850 _rtw_memcpy(pwlanhdr->addr1, rx_pkt_pattrib->src, ETH_ALEN);
\r
851 _rtw_memcpy(pattrib->dst, pwlanhdr->addr1, ETH_ALEN);
\r
853 _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
854 _rtw_memcpy(pattrib->src, pwlanhdr->addr2, ETH_ALEN);
\r
856 _rtw_memcpy(pwlanhdr->addr3, rx_pkt_pattrib->bssid, ETH_ALEN);
\r
857 _rtw_memcpy(pattrib->ra, pwlanhdr->addr3, ETH_ALEN);
\r
859 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
\r
860 pmlmeext->mgnt_seq++;
\r
861 SetFrameSubType(pframe, WIFI_ACTION);
\r
863 pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
\r
864 pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
\r
866 rtw_build_tdls_dis_rsp_ies(padapter, pmgntframe, pframe, dialog);
\r
868 pattrib->nr_frags = 1;
\r
869 pattrib->last_txcmdsz = pattrib->pktlen;
\r
871 dump_mgntframe(padapter, pmgntframe);
\r
876 void issue_tdls_peer_traffic_indication(_adapter *padapter, struct sta_info *ptdls_sta)
\r
878 struct xmit_frame *pmgntframe;
\r
879 struct pkt_attrib *pattrib;
\r
880 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
881 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
883 static u8 dialogtoken=0;
\r
885 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
891 pattrib = &pmgntframe->attrib;
\r
893 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
894 pattrib->ether_type = 0x890d;
\r
897 _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
\r
898 _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
900 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
901 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
903 //for tdls; pattrib->nr_frags is used to fill dialogtoken
\r
904 ptdls_sta->dialog = dialogtoken;
\r
905 dialogtoken = (dialogtoken+1)%256;
\r
906 //PTI frame's priority should be AC_VO
\r
907 pattrib->priority = 7;
\r
909 update_tdls_attrib(padapter, pattrib);
\r
910 pattrib->qsel=pattrib->priority;
\r
911 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_PEER_TRAFFIC_INDICATION) != _SUCCESS) {
\r
912 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
913 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
916 rtw_dump_xframe(padapter, pmgntframe);
\r
923 void issue_tdls_ch_switch_req(_adapter *padapter, u8 *mac_addr)
\r
925 struct xmit_frame *pmgntframe;
\r
926 struct pkt_attrib *pattrib;
\r
927 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
928 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
930 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
936 pattrib = &pmgntframe->attrib;
\r
938 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
939 pattrib->ether_type = 0x890d;
\r
940 pattrib->pctrl =0;
\r
942 _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);
\r
943 _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
945 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
946 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
948 update_tdls_attrib(padapter, pattrib);
\r
950 pattrib->qsel=pattrib->priority;
\r
951 if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_CHANNEL_SWITCH_REQUEST) !=_SUCCESS ){
\r
952 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
953 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
956 rtw_dump_xframe(padapter, pmgntframe);
\r
963 void issue_tdls_ch_switch_rsp(_adapter *padapter, u8 *mac_addr)
\r
965 struct xmit_frame *pmgntframe;
\r
966 struct pkt_attrib *pattrib;
\r
967 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
968 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
972 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
978 pattrib = &pmgntframe->attrib;
\r
980 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
981 pattrib->ether_type = 0x890d;
\r
982 pattrib->pctrl =0;
\r
984 _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);
\r
985 _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);
\r
987 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
988 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
990 update_tdls_attrib(padapter, pattrib);
\r
992 pattrib->qsel=pattrib->priority;
\r
994 _enter_critical_bh(&pxmitpriv->lock, &irqL);
\r
995 if(xmitframe_enqueue_for_tdls_sleeping_sta(padapter, pmgntframe)==_TRUE){
\r
996 _exit_critical_bh(&pxmitpriv->lock, &irqL);
\r
1000 if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, TDLS_CHANNEL_SWITCH_RESPONSE) !=_SUCCESS ){
\r
1001 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
1002 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1005 rtw_dump_xframe(padapter, pmgntframe);
\r
1012 sint On_TDLS_Dis_Rsp(_adapter *adapter, union recv_frame *precv_frame)
\r
1014 struct sta_info *ptdls_sta = NULL, *psta = rtw_get_stainfo(&(adapter->stapriv), get_bssid(&(adapter->mlmepriv)));
\r
1015 struct recv_priv *precvpriv = &(adapter->recvpriv);
\r
1016 u8 *ptr = precv_frame->u.hdr.rx_data, *psa;
\r
1017 struct rx_pkt_attrib *pattrib = &(precv_frame->u.hdr.attrib);
\r
1018 struct tdls_info *ptdlsinfo = &(adapter->tdlsinfo);
\r
1019 u8 empty_addr[ETH_ALEN] = { 0x00 };
\r
1020 int UndecoratedSmoothedPWDB;
\r
1023 //WFDTDLS: for sigma test, not to setup direct link automatically
\r
1024 ptdlsinfo->dev_discovered = 1;
\r
1026 #ifdef CONFIG_TDLS_AUTOSETUP
\r
1027 psa = get_sa(ptr);
\r
1028 ptdls_sta = rtw_get_stainfo(&(adapter->stapriv), psa);
\r
1030 if(ptdls_sta != NULL)
\r
1032 ptdls_sta->tdls_sta_state |= TDLS_ALIVE_STATE;
\r
1034 //Record the tdls sta with lowest signal strength
\r
1035 if( (ptdlsinfo->sta_maximum == _TRUE) && (ptdls_sta->alive_count >= 1) )
\r
1037 if( _rtw_memcmp(ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN) )
\r
1039 _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);
\r
1040 ptdlsinfo->ss_record.RxPWDBAll = pattrib->RxPWDBAll;
\r
1044 if( ptdlsinfo->ss_record.RxPWDBAll < pattrib->RxPWDBAll )
\r
1046 _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);
\r
1047 ptdlsinfo->ss_record.RxPWDBAll = pattrib->RxPWDBAll;
\r
1055 if( ptdlsinfo->sta_maximum == _TRUE)
\r
1057 if( _rtw_memcmp( ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN ) )
\r
1059 //All traffics are busy, do not set up another direct link.
\r
1064 if( pattrib->RxPWDBAll > ptdlsinfo->ss_record.RxPWDBAll )
\r
1066 issue_tdls_teardown(adapter, ptdlsinfo->ss_record.macaddr);
\r
1075 adapter->HalFunc.GetHalDefVarHandler(adapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
\r
1077 if( pattrib->RxPWDBAll + TDLS_SIGNAL_THRESH >= UndecoratedSmoothedPWDB);
\r
1079 DBG_871X("pattrib->RxPWDBAll=%d, pdmpriv->UndecoratedSmoothedPWDB=%d\n", pattrib->RxPWDBAll, UndecoratedSmoothedPWDB);
\r
1080 issue_tdls_setup_req(adapter, psa);
\r
1083 #endif //CONFIG_TDLS_AUTOSETUP
\r
1088 sint On_TDLS_Setup_Req(_adapter *adapter, union recv_frame *precv_frame)
\r
1090 struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
\r
1092 struct sta_info *ptdls_sta= NULL;
\r
1093 struct sta_priv *pstapriv = &adapter->stapriv;
\r
1094 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1095 struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
\r
1096 struct security_priv *psecuritypriv = &adapter->securitypriv;
\r
1098 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1099 u8 *prsnie, *ppairwise_cipher;
\r
1100 u8 i, k, pairwise_count;
\r
1101 u8 ccmp_have=0, rsnie_have=0;
\r
1104 u32 *timeout_interval;
\r
1105 sint parsing_length; //frame body length, without icv_len
\r
1106 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1108 unsigned char supportRate[16];
\r
1109 int supportRateNum = 0;
\r
1111 psa = get_sa(ptr);
\r
1112 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1114 pmyid=myid(&(adapter->eeprompriv));
\r
1115 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;
\r
1116 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1117 -prx_pkt_attrib->hdrlen
\r
1118 -prx_pkt_attrib->iv_len
\r
1119 -prx_pkt_attrib->icv_len
\r
1125 if(ptdlsinfo->ap_prohibited == _TRUE)
\r
1130 if(ptdls_sta==NULL){
\r
1131 ptdls_sta = rtw_alloc_stainfo(pstapriv, psa);
\r
1133 if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE){
\r
1134 //If the direct link is already set up
\r
1135 //Process as re-setup after tear down
\r
1136 DBG_871X("re-setup a direct link\n");
\r
1138 //already receiving TDLS setup request
\r
1139 else if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){
\r
1140 DBG_871X("receive duplicated TDLS setup request frame in handshaking\n");
\r
1143 //When receiving and sending setup_req to the same link at the same time, STA with higher MAC_addr would be initiator
\r
1144 //following is to check out MAC_addr
\r
1145 else if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){
\r
1146 DBG_871X("receive setup_req after sending setup_req\n");
\r
1147 for (i=0;i<6;i++){
\r
1148 if(*(pmyid+i)==*(psa+i)){
\r
1150 else if(*(pmyid+i)>*(psa+i)){
\r
1152 }else if(*(pmyid+i)<*(psa+i)){
\r
1153 ptdls_sta->tdls_sta_state=TDLS_INITIATOR_STATE;
\r
1162 ptdls_sta->dialog = *(ptr+2); //copy dialog token
\r
1163 ptdls_sta->stat_code = 0;
\r
1165 //parsing information element
\r
1166 for(j=FIXED_IE; j<parsing_length;){
\r
1168 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1170 switch (pIE->ElementID)
\r
1172 case _SUPPORTEDRATES_IE_:
\r
1173 _rtw_memcpy(supportRate, pIE->data, pIE->Length);
\r
1174 supportRateNum = pIE->Length;
\r
1176 case _COUNTRY_IE_:
\r
1178 case _EXT_SUPPORTEDRATES_IE_:
\r
1179 if(supportRateNum<=sizeof(supportRate))
\r
1181 _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);
\r
1182 supportRateNum += pIE->Length;
\r
1185 case _SUPPORTED_CH_IE_:
\r
1189 if(prx_pkt_attrib->encrypt){
\r
1191 //check whether initiator STA has CCMP pairwise_cipher.
\r
1192 ppairwise_cipher=prsnie+10;
\r
1193 _rtw_memcpy(&pairwise_count, (u16*)(ppairwise_cipher-2), 1);
\r
1194 for(k=0;k<pairwise_count;k++){
\r
1195 if(_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE)
\r
1199 //invalid contents of RSNIE
\r
1200 ptdls_sta->stat_code=72;
\r
1204 case _EXT_CAP_IE_:
\r
1206 case _VENDOR_SPECIFIC_IE_:
\r
1209 if(prx_pkt_attrib->encrypt)
\r
1210 _rtw_memcpy(SNonce, (ptr+j+52), 32);
\r
1212 case _TIMEOUT_ITVL_IE_:
\r
1213 if(prx_pkt_attrib->encrypt)
\r
1214 timeout_interval = (u32 *)(ptr+j+3);
\r
1216 case _RIC_Descriptor_IE_:
\r
1218 case _HT_CAPABILITY_IE_:
\r
1219 rtw_tdls_process_ht_cap(adapter, ptdls_sta, pIE->data, pIE->Length);
\r
1221 case EID_BSSCoexistence:
\r
1223 case _LINK_ID_IE_:
\r
1224 if(_rtw_memcmp(get_bssid(pmlmepriv), pIE->data, 6) == _FALSE)
\r
1226 //not in the same BSS
\r
1227 ptdls_sta->stat_code=7;
\r
1234 j += (pIE->Length + 2);
\r
1238 //update station supportRate
\r
1239 ptdls_sta->bssratelen = supportRateNum;
\r
1240 _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);
\r
1242 //check status code
\r
1243 //if responder STA has/hasn't security on AP, but request hasn't/has RSNIE, it should reject
\r
1244 if(ptdls_sta->stat_code == 0 )
\r
1246 if(rsnie_have && (prx_pkt_attrib->encrypt==0)){
\r
1247 //security disabled
\r
1248 ptdls_sta->stat_code = 5;
\r
1249 }else if(rsnie_have==0 && (prx_pkt_attrib->encrypt)){
\r
1250 //request haven't RSNIE
\r
1251 ptdls_sta->stat_code = 38;
\r
1255 //WFD test plan version 0.18.2 test item 5.1.5
\r
1256 //SoUT does not use TDLS if AP uses weak security
\r
1257 if ( adapter->wdinfo.wfd_tdls_enable )
\r
1259 if(rsnie_have && (prx_pkt_attrib->encrypt != _AES_))
\r
1261 ptdls_sta->stat_code = 5;
\r
1264 #endif //CONFIG_WFD
\r
1267 ptdls_sta->tdls_sta_state|= TDLS_INITIATOR_STATE;
\r
1268 if(prx_pkt_attrib->encrypt){
\r
1269 _rtw_memcpy(ptdls_sta->SNonce, SNonce, 32);
\r
1270 _rtw_memcpy(&(ptdls_sta->TDLS_PeerKey_Lifetime), timeout_interval, 4);
\r
1272 _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
1273 if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
\r
1274 ptdlsinfo->sta_cnt++;
\r
1275 _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
1276 if( ptdlsinfo->sta_cnt == (NUM_STA - 2) ) // -2: AP + BC/MC sta
\r
1278 ptdlsinfo->sta_maximum = _TRUE;
\r
1282 rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length - FIXED_IE);
\r
1283 #endif // CONFIG_WFD
\r
1291 issue_tdls_setup_rsp(adapter, precv_frame);
\r
1293 if(ptdls_sta->stat_code==0)
\r
1295 _set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);
\r
1297 else //status code!=0 ; setup unsuccess
\r
1299 free_tdls_sta(adapter, ptdls_sta);
\r
1307 sint On_TDLS_Setup_Rsp(_adapter *adapter, union recv_frame *precv_frame)
\r
1309 struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
\r
1310 struct sta_info *ptdls_sta= NULL;
\r
1311 struct sta_priv *pstapriv = &adapter->stapriv;
\r
1312 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1314 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1317 sint parsing_length; //frame body length, without icv_len
\r
1318 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1320 u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic, *ppairwise_cipher;
\r
1321 u16 pairwise_count, j, k;
\r
1323 unsigned char supportRate[16];
\r
1324 int supportRateNum = 0;
\r
1326 psa = get_sa(ptr);
\r
1327 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1329 if ( NULL == ptdls_sta )
\r
1334 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;
\r
1335 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1336 -prx_pkt_attrib->hdrlen
\r
1337 -prx_pkt_attrib->iv_len
\r
1338 -prx_pkt_attrib->icv_len
\r
1340 -TYPE_LENGTH_FIELD_SIZE
\r
1344 _rtw_memcpy(&stat_code, ptr+2, 2);
\r
1348 DBG_871X( "[%s] status_code = %d, free_tdls_sta\n", __FUNCTION__, stat_code );
\r
1349 free_tdls_sta(adapter, ptdls_sta);
\r
1355 //parsing information element
\r
1356 for(j=FIXED_IE; j<parsing_length;)
\r
1358 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1360 switch (pIE->ElementID)
\r
1362 case _SUPPORTEDRATES_IE_:
\r
1363 _rtw_memcpy(supportRate, pIE->data, pIE->Length);
\r
1364 supportRateNum = pIE->Length;
\r
1366 case _COUNTRY_IE_:
\r
1368 case _EXT_SUPPORTEDRATES_IE_:
\r
1369 if(supportRateNum<=sizeof(supportRate))
\r
1371 _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);
\r
1372 supportRateNum += pIE->Length;
\r
1375 case _SUPPORTED_CH_IE_:
\r
1379 //check whether responder STA has CCMP pairwise_cipher.
\r
1380 ppairwise_cipher=prsnie+10;
\r
1381 _rtw_memcpy(&pairwise_count, (u16*)(ppairwise_cipher-2), 2);
\r
1382 for(k=0;k<pairwise_count;k++){
\r
1383 if(_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE)
\r
1386 case _EXT_CAP_IE_:
\r
1388 case _VENDOR_SPECIFIC_IE_:
\r
1392 _rtw_memcpy(ptdls_sta->ANonce, (ptr+j+20), 32);
\r
1394 case _TIMEOUT_ITVL_IE_:
\r
1395 ptimeout_ie=(u8*)pIE;
\r
1397 case _RIC_Descriptor_IE_:
\r
1399 case _HT_CAPABILITY_IE_:
\r
1400 rtw_tdls_process_ht_cap(adapter, ptdls_sta, pIE->data, pIE->Length);
\r
1402 case EID_BSSCoexistence:
\r
1404 case _LINK_ID_IE_:
\r
1405 plinkid_ie=(u8*)pIE;
\r
1411 j += (pIE->Length + 2);
\r
1415 //update station supportRate
\r
1416 ptdls_sta->bssratelen = supportRateNum;
\r
1417 _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);
\r
1420 rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length - FIXED_IE);
\r
1421 #endif // CONFIG_WFD
\r
1423 if(stat_code != 0)
\r
1425 ptdls_sta->stat_code = stat_code;
\r
1429 if(prx_pkt_attrib->encrypt)
\r
1431 if(verify_ccmp==1)
\r
1433 wpa_tdls_generate_tpk(adapter, ptdls_sta);
\r
1434 ptdls_sta->stat_code=0;
\r
1435 if(tdls_verify_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie)==0) //0: Invalid, 1: valid
\r
1437 free_tdls_sta(adapter, ptdls_sta);
\r
1443 ptdls_sta->stat_code=72; //invalide contents of RSNIE
\r
1447 ptdls_sta->stat_code=0;
\r
1451 DBG_871X("issue_tdls_setup_cfm\n");
\r
1452 issue_tdls_setup_cfm(adapter, precv_frame);
\r
1454 if(ptdls_sta->stat_code==0)
\r
1456 ptdlsinfo->setup_state = TDLS_LINKED_STATE;
\r
1458 if( ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE )
\r
1460 ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;
\r
1461 _cancel_timer_ex( &ptdls_sta->handshake_timer);
\r
1462 #ifdef CONFIG_TDLS_AUTOCHECKALIVE
\r
1463 _set_timer( &ptdls_sta->alive_timer1, TDLS_ALIVE_TIMER_PH1);
\r
1464 #endif //CONFIG_TDLS_AUTOSETUP
\r
1467 rtw_tdls_set_mac_id(ptdlsinfo, ptdls_sta);
\r
1468 rtw_tdls_set_key(adapter, prx_pkt_attrib, ptdls_sta);
\r
1470 rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_WRCR);
\r
1473 else //status code!=0 ; setup unsuccessful
\r
1475 free_tdls_sta(adapter, ptdls_sta);
\r
1482 sint On_TDLS_Setup_Cfm(_adapter *adapter, union recv_frame *precv_frame)
\r
1484 struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
\r
1485 struct sta_info *ptdls_sta= NULL;
\r
1486 struct sta_priv *pstapriv = &adapter->stapriv;
\r
1487 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1489 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1492 sint parsing_length;
\r
1493 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1495 u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic, *ppairwise_cipher;
\r
1496 u16 j, pairwise_count;
\r
1498 psa = get_sa(ptr);
\r
1499 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1501 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;
\r
1502 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1503 -prx_pkt_attrib->hdrlen
\r
1504 -prx_pkt_attrib->iv_len
\r
1505 -prx_pkt_attrib->icv_len
\r
1510 _rtw_memcpy(&stat_code, ptr+2, 2);
\r
1513 DBG_871X( "[%s] stat_code = %d\n, free_tdls_sta", __FUNCTION__, stat_code );
\r
1514 free_tdls_sta(adapter, ptdls_sta);
\r
1518 if(prx_pkt_attrib->encrypt){
\r
1519 //parsing information element
\r
1520 for(j=FIXED_IE; j<parsing_length;){
\r
1522 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1524 switch (pIE->ElementID)
\r
1529 case _VENDOR_SPECIFIC_IE_:
\r
1534 case _TIMEOUT_ITVL_IE_:
\r
1535 ptimeout_ie=(u8*)pIE;
\r
1537 case _HT_EXTRA_INFO_IE_:
\r
1539 case _LINK_ID_IE_:
\r
1540 plinkid_ie=(u8*)pIE;
\r
1546 j += (pIE->Length + 2);
\r
1550 //verify mic in FTIE MIC field
\r
1551 if(tdls_verify_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie)==0){ //0: Invalid, 1: Valid
\r
1552 free_tdls_sta(adapter, ptdls_sta);
\r
1558 ptdlsinfo->setup_state = TDLS_LINKED_STATE;
\r
1559 if( ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE )
\r
1561 ptdls_sta->tdls_sta_state|=TDLS_LINKED_STATE;
\r
1562 _cancel_timer_ex( &ptdls_sta->handshake_timer);
\r
1563 #ifdef CONFIG_TDLS_AUTOCHECKALIVE
\r
1564 _set_timer( &ptdls_sta->alive_timer1, TDLS_ALIVE_TIMER_PH1);
\r
1565 #endif //CONFIG_TDLS_AUTOCHECKALIVE
\r
1568 rtw_tdls_set_mac_id(ptdlsinfo, ptdls_sta);
\r
1569 rtw_tdls_set_key(adapter, prx_pkt_attrib, ptdls_sta);
\r
1571 rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_WRCR);
\r
1577 sint On_TDLS_Dis_Req(_adapter *adapter, union recv_frame *precv_frame)
\r
1579 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1580 struct sta_priv *pstapriv = &adapter->stapriv;
\r
1581 struct sta_info *psta_ap;
\r
1582 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1583 sint parsing_length; //frame body length, without icv_len
\r
1584 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1585 u8 FIXED_IE = 3, *dst, *pdialog = NULL;
\r
1588 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE + 1;
\r
1591 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1592 -prx_pkt_attrib->hdrlen
\r
1593 -prx_pkt_attrib->iv_len
\r
1594 -prx_pkt_attrib->icv_len
\r
1596 -TYPE_LENGTH_FIELD_SIZE
\r
1600 //parsing information element
\r
1601 for(j=FIXED_IE; j<parsing_length;){
\r
1603 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1605 switch (pIE->ElementID)
\r
1607 case _LINK_ID_IE_:
\r
1608 psta_ap = rtw_get_stainfo(pstapriv, pIE->data);
\r
1609 if(psta_ap == NULL)
\r
1613 dst = pIE->data + 12;
\r
1614 if( (MacAddr_isBcst(dst) == _FALSE) && (_rtw_memcmp(myid(&(adapter->eeprompriv)), dst, 6) == _FALSE) )
\r
1623 j += (pIE->Length + 2);
\r
1627 //check frame contents
\r
1629 issue_tdls_dis_rsp(adapter, precv_frame, *(pdialog) );
\r
1637 sint On_TDLS_Teardown(_adapter *adapter, union recv_frame *precv_frame)
\r
1640 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1641 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1642 struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
\r
1643 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
1644 struct sta_priv *pstapriv = &adapter->stapriv;
\r
1645 struct sta_info *ptdls_sta= NULL;
\r
1648 psa = get_sa(ptr);
\r
1650 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1651 if(ptdls_sta!=NULL){
\r
1652 if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE){
\r
1653 rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_CS_OFF);
\r
1655 free_tdls_sta(adapter, ptdls_sta);
\r
1662 u8 TDLS_check_ch_state(uint state){
\r
1663 if( (state & TDLS_CH_SWITCH_ON_STATE) &&
\r
1664 (state & TDLS_AT_OFF_CH_STATE) &&
\r
1665 (state & TDLS_PEER_AT_OFF_STATE) ){
\r
1667 if(state & TDLS_PEER_SLEEP_STATE)
\r
1668 return 2; //U-APSD + ch. switch
\r
1670 return 1; //ch. switch
\r
1675 //we process buffered data for 1. U-APSD, 2. ch. switch, 3. U-APSD + ch. switch here
\r
1676 sint On_TDLS_Peer_Traffic_Rsp(_adapter *adapter, union recv_frame *precv_frame)
\r
1678 struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
\r
1679 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
\r
1680 struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib;
\r
1681 struct sta_priv *pstapriv = &adapter->stapriv;
\r
1682 //get peer sta infomation
\r
1683 struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->src);
\r
1684 u8 wmmps_ac=0, state=TDLS_check_ch_state(ptdls_sta->tdls_sta_state);
\r
1687 ptdls_sta->sta_stats.rx_data_pkts++;
\r
1689 //receive peer traffic response frame, sleeping STA wakes up
\r
1690 //ptdls_sta->tdls_sta_state &= ~(TDLS_PEER_SLEEP_STATE);
\r
1691 process_wmmps_data( adapter, precv_frame);
\r
1693 // if noticed peer STA wakes up by receiving peer traffic response
\r
1694 // and we want to do channel swtiching, then we will transmit channel switch request first
\r
1695 if(ptdls_sta->tdls_sta_state & TDLS_APSD_CHSW_STATE){
\r
1696 issue_tdls_ch_switch_req(adapter, pattrib->src);
\r
1697 ptdls_sta->tdls_sta_state &= ~(TDLS_APSD_CHSW_STATE);
\r
1701 //check 4-AC queue bit
\r
1702 if(ptdls_sta->uapsd_vo || ptdls_sta->uapsd_vi || ptdls_sta->uapsd_be || ptdls_sta->uapsd_bk)
\r
1705 //if it's a direct link and have buffered frame
\r
1706 if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE){
\r
1707 if(wmmps_ac && state)
\r
1710 _list *xmitframe_plist, *xmitframe_phead;
\r
1711 struct xmit_frame *pxmitframe=NULL;
\r
1713 _enter_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);
\r
1715 xmitframe_phead = get_list_head(&ptdls_sta->sleep_q);
\r
1716 xmitframe_plist = get_next(xmitframe_phead);
\r
1718 //transmit buffered frames
\r
1719 while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
\r
1721 pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
\r
1722 xmitframe_plist = get_next(xmitframe_plist);
\r
1723 rtw_list_delete(&pxmitframe->list);
\r
1725 ptdls_sta->sleepq_len--;
\r
1726 if(ptdls_sta->sleepq_len>0){
\r
1727 pxmitframe->attrib.mdata = 1;
\r
1728 pxmitframe->attrib.eosp = 0;
\r
1730 pxmitframe->attrib.mdata = 0;
\r
1731 pxmitframe->attrib.eosp = 1;
\r
1733 //pxmitframe->attrib.triggered = 1; //maybe doesn't need in TDLS
\r
1734 if(adapter->HalFunc.hal_xmit(adapter, pxmitframe) == _TRUE)
\r
1736 rtw_os_xmit_complete(adapter, pxmitframe);
\r
1741 if(ptdls_sta->sleepq_len==0)
\r
1743 DBG_871X("no buffered packets for tdls to xmit\n");
\r
1744 //on U-APSD + CH. switch state, when there is no buffered date to xmit,
\r
1745 // we should go back to base channel
\r
1747 rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_CS_OFF);
\r
1748 }else if(ptdls_sta->tdls_sta_state&TDLS_SW_OFF_STATE){
\r
1749 ptdls_sta->tdls_sta_state &= ~(TDLS_SW_OFF_STATE);
\r
1750 ptdlsinfo->candidate_ch= pmlmeext->cur_channel;
\r
1751 issue_tdls_ch_switch_req(adapter, pattrib->src);
\r
1752 DBG_871X("issue tdls ch switch req back to base channel\n");
\r
1758 DBG_871X("error!psta->sleepq_len=%d\n", ptdls_sta->sleepq_len);
\r
1759 ptdls_sta->sleepq_len=0;
\r
1762 _exit_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);
\r
1771 sint On_TDLS_Ch_Switch_Req(_adapter *adapter, union recv_frame *precv_frame)
\r
1773 struct sta_info *ptdls_sta= NULL;
\r
1774 struct sta_priv *pstapriv = &adapter->stapriv;
\r
1775 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1776 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1778 sint parsing_length;
\r
1779 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1782 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
\r
1784 psa = get_sa(ptr);
\r
1785 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1787 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;
\r
1788 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1789 -prx_pkt_attrib->hdrlen
\r
1790 -prx_pkt_attrib->iv_len
\r
1791 -prx_pkt_attrib->icv_len
\r
1797 ptdls_sta->off_ch = *(ptr+2);
\r
1799 //parsing information element
\r
1800 for(j=FIXED_IE; j<parsing_length;){
\r
1802 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1804 switch (pIE->ElementID)
\r
1806 case _COUNTRY_IE_:
\r
1808 case _CH_SWTICH_ANNOUNCE_:
\r
1810 case _LINK_ID_IE_:
\r
1812 case _CH_SWITCH_TIMING_:
\r
1813 _rtw_memcpy(&ptdls_sta->ch_switch_time, pIE->data, 2);
\r
1814 _rtw_memcpy(&ptdls_sta->ch_switch_timeout, pIE->data+2, 2);
\r
1819 j += (pIE->Length + 2);
\r
1823 //todo: check status
\r
1824 ptdls_sta->stat_code=0;
\r
1825 ptdls_sta->tdls_sta_state |= TDLS_CH_SWITCH_ON_STATE;
\r
1827 issue_nulldata(adapter, NULL, 1, 0, 0);
\r
1829 issue_tdls_ch_switch_rsp(adapter, psa);
\r
1831 DBG_871X("issue tdls channel switch response\n");
\r
1833 if((ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE) && ptdls_sta->off_ch==pmlmeext->cur_channel){
\r
1834 DBG_871X("back to base channel %x\n", pmlmeext->cur_channel);
\r
1835 ptdls_sta->option=7;
\r
1836 rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_BASE_CH);
\r
1838 ptdls_sta->option=6;
\r
1839 rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_OFF_CH);
\r
1844 sint On_TDLS_Ch_Switch_Rsp(_adapter *adapter, union recv_frame *precv_frame)
\r
1846 struct sta_info *ptdls_sta= NULL;
\r
1847 struct sta_priv *pstapriv = &adapter->stapriv;
\r
1848 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1849 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1851 sint parsing_length;
\r
1852 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1854 u16 stat_code, j, switch_time, switch_timeout;
\r
1855 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
\r
1857 psa = get_sa(ptr);
\r
1858 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1860 //if channel switch is running and receiving Unsolicited TDLS Channel Switch Response,
\r
1861 //it will go back to base channel and terminate this channel switch procedure
\r
1862 if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE ){
\r
1863 if(pmlmeext->cur_channel==ptdls_sta->off_ch){
\r
1864 DBG_871X("back to base channel %x\n", pmlmeext->cur_channel);
\r
1865 ptdls_sta->option=7;
\r
1866 rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_OFF_CH);
\r
1868 DBG_871X("receive unsolicited channel switch response \n");
\r
1869 rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_CS_OFF);
\r
1874 //avoiding duplicated or unconditional ch. switch. rsp
\r
1875 if((ptdls_sta->tdls_sta_state & TDLS_CH_SW_INITIATOR_STATE) != TDLS_CH_SW_INITIATOR_STATE)
\r
1878 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;
\r
1879 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1880 -prx_pkt_attrib->hdrlen
\r
1881 -prx_pkt_attrib->iv_len
\r
1882 -prx_pkt_attrib->icv_len
\r
1888 _rtw_memcpy(&stat_code, ptr+2, 2);
\r
1894 //parsing information element
\r
1895 for(j=FIXED_IE; j<parsing_length;){
\r
1897 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1899 switch (pIE->ElementID)
\r
1901 case _LINK_ID_IE_:
\r
1903 case _CH_SWITCH_TIMING_:
\r
1904 _rtw_memcpy(&switch_time, pIE->data, 2);
\r
1905 if(switch_time > ptdls_sta->ch_switch_time)
\r
1906 _rtw_memcpy(&ptdls_sta->ch_switch_time, &switch_time, 2);
\r
1908 _rtw_memcpy(&switch_timeout, pIE->data+2, 2);
\r
1909 if(switch_timeout > ptdls_sta->ch_switch_timeout)
\r
1910 _rtw_memcpy(&ptdls_sta->ch_switch_timeout, &switch_timeout, 2);
\r
1916 j += (pIE->Length + 2);
\r
1920 ptdls_sta->tdls_sta_state &= ~(TDLS_CH_SW_INITIATOR_STATE);
\r
1921 ptdls_sta->tdls_sta_state |=TDLS_CH_SWITCH_ON_STATE;
\r
1923 //goto set_channel_workitem_callback()
\r
1924 ptdls_sta->option=6;
\r
1925 rtw_tdls_cmd(adapter, ptdls_sta->hwaddr, TDLS_OFF_CH);
\r
1931 void wfd_ie_tdls(_adapter * padapter, u8 *pframe, u32 *pktlen )
\r
1933 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1934 struct wifi_display_info *pwfd_info = padapter->tdlsinfo.wfd_info;
\r
1935 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
\r
1940 wfdie[ wfdielen++ ] = 0x50;
\r
1941 wfdie[ wfdielen++ ] = 0x6F;
\r
1942 wfdie[ wfdielen++ ] = 0x9A;
\r
1943 wfdie[ wfdielen++ ] = 0x0A; // WFA WFD v1.0
\r
1945 // Commented by Albert 20110825
\r
1946 // According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
\r
1947 // 1. WFD Device Information
\r
1948 // 2. Associated BSSID ( Optional )
\r
1949 // 3. Local IP Adress ( Optional )
\r
1951 // WFD Device Information ATTR
\r
1953 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
\r
1956 // Note: In the WFD specification, the size of length field is 2.
\r
1957 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
\r
1961 // WFD device information
\r
1962 // available for WFD session + Preferred TDLS + WSD ( WFD Service Discovery )
\r
1963 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL
\r
1964 | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_WSD);
\r
1968 // Session Management Control Port
\r
1969 // Default TCP port for RTSP messages is 554
\r
1970 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
\r
1974 // WFD Device Maximum Throughput
\r
1975 // 300Mbps is the maximum throughput
\r
1976 RTW_PUT_BE16(wfdie + wfdielen, 300);
\r
1979 // Associated BSSID ATTR
\r
1981 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
\r
1984 // Note: In the WFD specification, the size of length field is 2.
\r
1985 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
\r
1989 // Associated BSSID
\r
1990 if ( check_fwstate( pmlmepriv, _FW_LINKED) == _TRUE )
\r
1992 _rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
\r
1996 _rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
\r
1999 // Local IP Address ATTR
\r
2000 wfdie[ wfdielen++ ] = WFD_ATTR_LOCAL_IP_ADDR;
\r
2003 // Note: In the WFD specification, the size of length field is 2.
\r
2004 RTW_PUT_BE16(wfdie + wfdielen, 0x0005);
\r
2008 // 0x01: Version1;IPv4
\r
2009 wfdie[ wfdielen++ ] = 0x01;
\r
2012 _rtw_memcpy( wfdie + wfdielen, pwfd_info->ip_address, 4 );
\r
2015 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, pktlen);
\r
2018 #endif //CONFIG_WFD
\r
2020 void rtw_build_tdls_setup_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2022 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2023 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
\r
2024 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2025 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
2026 struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);
\r
2028 u8 payload_type = 0x02;
\r
2029 u8 category = RTW_WLAN_CATEGORY_TDLS;
\r
2030 u8 action = TDLS_SETUP_REQUEST;
\r
2031 u8 bssrate[NDIS_802_11_LENGTH_RATES_EX]; //Use NDIS_802_11_LENGTH_RATES_EX in order to call func.rtw_set_supported_rate
\r
2032 int bssrate_len = 0, i = 0 ;
\r
2033 u8 more_supportedrates = 0;
\r
2034 unsigned int ie_len;
\r
2036 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
2037 u8 link_id_addr[18] = {0};
\r
2039 u8 sup_ch[ 30 * 2 ] = {0x00 }, sup_ch_idx = 0, idx_5g = 2; //For supported channel
\r
2040 u8 timeout_itvl[5]; //set timeout interval to maximum value
\r
2044 if(pattrib->encrypt){
\r
2046 time=rtw_get_current_time();
\r
2047 _rtw_memcpy(&ptdls_sta->SNonce[4*i], (u8 *)&time, 4);
\r
2052 pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
2053 //category, action, dialog token
\r
2054 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2055 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
\r
2056 pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));
\r
2059 _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
\r
2061 if(pattrib->encrypt)
\r
2062 *pframe =*pframe | BIT(4);
\r
2064 pattrib->pktlen += 2;
\r
2067 rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N);
\r
2068 bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN;
\r
2070 if (bssrate_len > 8)
\r
2072 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
\r
2073 more_supportedrates = 1;
\r
2077 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
\r
2080 //country(optional)
\r
2081 //extended supported rates
\r
2082 if(more_supportedrates==1){
\r
2083 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
\r
2086 //supported channels
\r
2087 pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);
\r
2090 pframe = rtw_set_ie( pframe, _SRC_IE_, 16, TDLS_SRC, &(pattrib->pktlen));
\r
2093 if(pattrib->encrypt)
\r
2094 pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen));
\r
2096 //extended capabilities
\r
2097 pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , 5, TDLS_EXT_CAPIE, &(pattrib->pktlen));
\r
2099 //QoS capability(WMM_IE)
\r
2100 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 7, TDLS_WMMIE, &(pattrib->pktlen));
\r
2103 if(pattrib->encrypt){
\r
2105 _rtw_memset(pframe, 0, 84); //All fields except SNonce shall be set to 0
\r
2106 _rtw_memset(pframe, _FTIE_, 1); //version
\r
2107 _rtw_memset((pframe+1), 82, 1); //length
\r
2108 _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32);
\r
2110 pattrib->pktlen += 84;
\r
2112 //Timeout interval
\r
2113 timeout_itvl[0]=0x02;
\r
2114 _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);
\r
2115 pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
\r
2118 //Sup_reg_classes(optional)
\r
2120 pframe = rtw_tdls_set_ht_cap(padapter, pframe, pattrib);
\r
2122 //20/40 BSS coexistence
\r
2123 if(pmlmepriv->num_FortyMHzIntolerant>0)
\r
2124 iedata |= BIT(2);//20 MHz BSS Width Request
\r
2125 pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
\r
2128 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
2129 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
\r
2130 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
\r
2131 pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
2134 wfd_ie_tdls( padapter, pframe, &(pattrib->pktlen) );
\r
2135 #endif //CONFIG_WFD
\r
2139 void rtw_build_tdls_setup_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2141 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2142 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
2143 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2144 struct sta_info *ptdls_sta;
\r
2145 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
2147 u8 payload_type = 0x02;
\r
2148 unsigned char category = RTW_WLAN_CATEGORY_TDLS;
\r
2149 unsigned char action = TDLS_SETUP_RESPONSE;
\r
2150 unsigned char bssrate[NDIS_802_11_LENGTH_RATES_EX];
\r
2151 int bssrate_len = 0;
\r
2152 u8 more_supportedrates = 0;
\r
2153 unsigned int ie_len;
\r
2155 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
2156 u8 link_id_addr[18] = {0};
\r
2158 u8 timeout_itvl[5]; //setup response timeout interval will copy from request
\r
2159 u8 ANonce[32]; //maybe it can put in ontdls_req
\r
2160 u8 k; //for random ANonce
\r
2161 u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic;
\r
2164 ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);
\r
2166 if(ptdls_sta == NULL )
\r
2168 DBG_871X("[%s] %d\n", __FUNCTION__, __LINE__);
\r
2172 if(pattrib->encrypt){
\r
2174 time=rtw_get_current_time();
\r
2175 _rtw_memcpy(&ptdls_sta->ANonce[4*k], (u8*)&time, 4);
\r
2180 pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
2181 //category, action, status code
\r
2182 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2183 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
\r
2184 pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));
\r
2186 if(ptdls_sta->stat_code!=0) //invalid setup request
\r
2188 DBG_871X("ptdls_sta->stat_code:%04x \n", ptdls_sta->stat_code);
\r
2193 pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));
\r
2196 _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
\r
2198 if(pattrib->encrypt )
\r
2199 *pframe =*pframe | BIT(4);
\r
2201 pattrib->pktlen += 2;
\r
2204 rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N);
\r
2205 bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN;
\r
2207 if (bssrate_len > 8)
\r
2209 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
\r
2210 more_supportedrates = 1;
\r
2214 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
\r
2217 //country(optional)
\r
2218 //extended supported rates
\r
2219 if(more_supportedrates==1){
\r
2220 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
\r
2223 //supported channels
\r
2224 pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);
\r
2227 pframe = rtw_set_ie(pframe, _SRC_IE_ , 16, TDLS_SRC, &(pattrib->pktlen));
\r
2230 if(pattrib->encrypt){
\r
2232 pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen));
\r
2235 //extended capabilities
\r
2236 pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , 5, TDLS_EXT_CAPIE, &(pattrib->pktlen));
\r
2238 //QoS capability(WMM_IE)
\r
2239 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 7, TDLS_WMMIE, &(pattrib->pktlen));
\r
2241 if(pattrib->encrypt){
\r
2242 wpa_tdls_generate_tpk(padapter, ptdls_sta);
\r
2246 pftie_mic = pframe+4;
\r
2247 _rtw_memset(pframe, 0, 84); //All fields except SNonce shall be set to 0
\r
2248 _rtw_memset(pframe, _FTIE_, 1); //version
\r
2249 _rtw_memset((pframe+1), 82, 1); //length
\r
2250 _rtw_memcpy((pframe+20), ptdls_sta->ANonce, 32);
\r
2251 _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32);
\r
2253 pattrib->pktlen += 84;
\r
2255 //Timeout interval
\r
2256 ptimeout_ie = pframe;
\r
2257 timeout_itvl[0]=0x02;
\r
2258 _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);
\r
2259 pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
\r
2262 //Sup_reg_classes(optional)
\r
2264 pframe = rtw_tdls_set_ht_cap(padapter, pframe, pattrib);
\r
2266 //20/40 BSS coexistence
\r
2267 if(pmlmepriv->num_FortyMHzIntolerant>0)
\r
2268 iedata |= BIT(2);//20 MHz BSS Width Request
\r
2269 pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
\r
2272 plinkid_ie = pframe;
\r
2273 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
2274 _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);
\r
2275 _rtw_memcpy((link_id_addr+12), pattrib->src, 6);
\r
2276 pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
2279 if(pattrib->encrypt)
\r
2280 wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);
\r
2283 wfd_ie_tdls( padapter, pframe, &(pattrib->pktlen) );
\r
2284 #endif //CONFIG_WFD
\r
2288 void rtw_build_tdls_setup_cfm_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2291 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2292 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
2293 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2294 struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);
\r
2296 u8 payload_type = 0x02;
\r
2297 unsigned char category = RTW_WLAN_CATEGORY_TDLS;
\r
2298 unsigned char action = TDLS_SETUP_CONFIRM;
\r
2299 u8 more_supportedrates = 0;
\r
2300 unsigned int ie_len;
\r
2302 u8 timeout_itvl[5]; //set timeout interval to maximum value
\r
2303 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
2304 u8 link_id_addr[18] = {0};
\r
2305 u8 *pftie, *ptimeout_ie, *plinkid_ie, *prsnie, *pftie_mic;
\r
2308 pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
2309 //category, action, status code, dialog token
\r
2310 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2311 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
\r
2312 pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));
\r
2313 pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));
\r
2315 if(ptdls_sta->stat_code!=0) //invalid setup request
\r
2319 if(pattrib->encrypt){
\r
2321 pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen));
\r
2324 //EDCA param set; WMM param ele.
\r
2325 if(pattrib->encrypt){
\r
2328 pftie_mic = pframe+4;
\r
2329 _rtw_memset(pframe, 0, 84); //All fields except SNonce shall be set to 0
\r
2330 _rtw_memset(pframe, _FTIE_, 1); //version
\r
2331 _rtw_memset((pframe+1), 82, 1); //length
\r
2332 _rtw_memcpy((pframe+20), ptdls_sta->ANonce, 32);
\r
2333 _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32);
\r
2335 pattrib->pktlen += 84;
\r
2337 //Timeout interval
\r
2338 ptimeout_ie = pframe;
\r
2339 timeout_itvl[0]=0x02;
\r
2340 _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);
\r
2341 ptdls_sta->TPK_count=0;
\r
2342 _set_timer(&ptdls_sta->TPK_timer, ptdls_sta->TDLS_PeerKey_Lifetime/TPK_RESEND_COUNT);
\r
2343 pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
\r
2346 //HT operation; todo
\r
2348 plinkid_ie = pframe;
\r
2349 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
2350 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
\r
2351 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
\r
2352 pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
2355 if(pattrib->encrypt)
\r
2356 wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);
\r
2360 void rtw_build_tdls_teardown_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2363 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2364 u8 payload_type = 0x02;
\r
2365 unsigned char category = RTW_WLAN_CATEGORY_TDLS;
\r
2366 unsigned char action = TDLS_TEARDOWN;
\r
2367 u8 link_id_addr[18] = {0};
\r
2369 struct sta_info *ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);
\r
2370 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2373 pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
2374 //category, action, reason code
\r
2375 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2376 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
\r
2377 pframe = rtw_set_fixed_ie(pframe, 1, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));
\r
2380 if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){
\r
2381 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
2382 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
\r
2383 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
\r
2384 }else if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){
\r
2385 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
2386 _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);
\r
2387 _rtw_memcpy((link_id_addr+12), pattrib->src, 6);
\r
2389 pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
2393 void rtw_build_tdls_dis_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2396 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2397 u8 payload_type = 0x02;
\r
2398 u8 category = RTW_WLAN_CATEGORY_TDLS;
\r
2399 u8 action = TDLS_DISCOVERY_REQUEST;
\r
2400 u8 link_id_addr[18] = {0};
\r
2401 static u8 dialogtoken=0;
\r
2404 pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
2405 //category, action, reason code
\r
2406 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2407 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
\r
2408 pframe = rtw_set_fixed_ie(pframe, 1, &(dialogtoken), &(pattrib->pktlen));
\r
2409 dialogtoken = (dialogtoken+1)%256;
\r
2412 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
2413 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
\r
2414 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
\r
2415 pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
2419 void rtw_build_tdls_dis_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, u8 dialog)
\r
2421 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2422 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
\r
2423 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2424 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
2426 u8 category = RTW_WLAN_CATEGORY_PUBLIC;
\r
2427 u8 action = TDLS_DISCOVERY_RESPONSE;
\r
2428 u8 bssrate[NDIS_802_11_LENGTH_RATES_EX];
\r
2429 int bssrate_len = 0;
\r
2430 u8 more_supportedrates = 0;
\r
2432 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
2433 u8 link_id_addr[18] = {0};
\r
2435 u8 timeout_itvl[5]; //set timeout interval to maximum value
\r
2436 u32 timeout_interval= TPK_RESEND_COUNT * 1000;
\r
2438 //category, action, dialog token
\r
2439 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2440 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
\r
2441 pframe = rtw_set_fixed_ie(pframe, 1, &(dialog), &(pattrib->pktlen));
\r
2444 _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
\r
2446 if(pattrib->encrypt)
\r
2447 *pframe =*pframe | BIT(4);
\r
2449 pattrib->pktlen += 2;
\r
2452 rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N);
\r
2453 bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN;
\r
2455 if (bssrate_len > 8)
\r
2457 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
\r
2458 more_supportedrates = 1;
\r
2462 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
\r
2465 //extended supported rates
\r
2466 if(more_supportedrates==1){
\r
2467 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
\r
2470 //supported channels
\r
2471 pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);
\r
2474 if(pattrib->encrypt)
\r
2475 pframe = rtw_set_ie(pframe, _RSN_IE_2_, 20, TDLS_RSNIE, &(pattrib->pktlen));
\r
2477 //extended capability
\r
2478 pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , 5, TDLS_EXT_CAPIE, &(pattrib->pktlen));
\r
2480 if(pattrib->encrypt){
\r
2482 _rtw_memset(pframe, 0, 84); //All fields shall be set to 0
\r
2483 _rtw_memset(pframe, _FTIE_, 1); //version
\r
2484 _rtw_memset((pframe+1), 82, 1); //length
\r
2486 pattrib->pktlen += 84;
\r
2488 //Timeout interval
\r
2489 timeout_itvl[0]=0x02;
\r
2490 _rtw_memcpy(timeout_itvl+1, &timeout_interval, 4);
\r
2491 pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
\r
2494 //Sup_reg_classes(optional)
\r
2496 pframe = rtw_tdls_set_ht_cap(padapter, pframe, pattrib);
\r
2498 //20/40 BSS coexistence
\r
2499 if(pmlmepriv->num_FortyMHzIntolerant>0)
\r
2500 iedata |= BIT(2);//20 MHz BSS Width Request
\r
2501 pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
\r
2504 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
2505 _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);
\r
2506 _rtw_memcpy((link_id_addr+12), pattrib->src, 6);
\r
2507 pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
2511 void rtw_build_tdls_peer_traffic_indication_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2514 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2515 u8 payload_type = 0x02;
\r
2516 unsigned char category = RTW_WLAN_CATEGORY_TDLS;
\r
2517 unsigned char action = TDLS_PEER_TRAFFIC_INDICATION;
\r
2519 u8 link_id_addr[18] = {0};
\r
2521 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2522 struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
\r
2525 pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
2526 //category, action, reason code
\r
2527 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2528 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
\r
2529 pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));
\r
2532 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
2533 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
\r
2534 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
\r
2535 pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
2538 //PU buffer status
\r
2539 if(ptdls_sta->uapsd_bk&BIT(1))
\r
2541 if(ptdls_sta->uapsd_be&BIT(1))
\r
2543 if(ptdls_sta->uapsd_vi&BIT(1))
\r
2545 if(ptdls_sta->uapsd_vo&BIT(1))
\r
2547 pframe = rtw_set_ie(pframe, _PTI_BUFFER_STATUS_, 1, &AC_queue, &(pattrib->pktlen));
\r
2551 void rtw_build_tdls_ch_switch_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2554 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2555 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
2556 u8 payload_type = 0x02;
\r
2557 unsigned char category = RTW_WLAN_CATEGORY_TDLS;
\r
2558 unsigned char action = TDLS_CHANNEL_SWITCH_REQUEST;
\r
2559 u8 link_id_addr[18] = {0};
\r
2560 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2561 struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
\r
2562 u8 ch_switch_timing[4] = {0};
\r
2563 u16 switch_time= CH_SWITCH_TIME, switch_timeout=CH_SWITCH_TIMEOUT;
\r
2566 pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
2567 //category, action, target_ch
\r
2568 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2569 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
\r
2570 pframe = rtw_set_fixed_ie(pframe, 1, &(ptdlsinfo->candidate_ch), &(pattrib->pktlen));
\r
2573 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
2574 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
\r
2575 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
\r
2576 pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
2578 //ch switch timing
\r
2579 _rtw_memcpy(ch_switch_timing, &switch_time, 2);
\r
2580 _rtw_memcpy(ch_switch_timing+2, &switch_timeout, 2);
\r
2581 pframe = rtw_set_ie(pframe, _CH_SWITCH_TIMING_, 4, ch_switch_timing, &(pattrib->pktlen));
\r
2583 //update ch switch attrib to sta_info
\r
2584 ptdls_sta->off_ch=ptdlsinfo->candidate_ch;
\r
2585 ptdls_sta->ch_switch_time=switch_time;
\r
2586 ptdls_sta->ch_switch_timeout=switch_timeout;
\r
2590 void rtw_build_tdls_ch_switch_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2593 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2594 u8 payload_type = 0x02;
\r
2595 unsigned char category = RTW_WLAN_CATEGORY_TDLS;
\r
2596 unsigned char action = TDLS_CHANNEL_SWITCH_RESPONSE;
\r
2597 u8 link_id_addr[18] = {0};
\r
2598 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2599 struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
\r
2600 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2601 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
\r
2602 u8 ch_switch_timing[4] = {0};
\r
2605 pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
2606 //category, action, status_code
\r
2607 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2608 pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
\r
2609 pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));
\r
2612 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
2613 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
\r
2614 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
\r
2615 pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
2617 //ch switch timing
\r
2618 _rtw_memcpy(ch_switch_timing, &ptdls_sta->ch_switch_time, 2);
\r
2619 _rtw_memcpy(ch_switch_timing+2, &ptdls_sta->ch_switch_timeout, 2);
\r
2620 pframe = rtw_set_ie(pframe, _CH_SWITCH_TIMING_, 4, ch_switch_timing, &(pattrib->pktlen));
\r
2625 void rtw_build_tunneled_probe_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2628 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2629 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
\r
2630 struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;
\r
2631 u8 payload_type = 0x02;
\r
2632 u8 category = RTW_WLAN_CATEGORY_P2P;
\r
2633 u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};
\r
2638 pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
2639 //category, OUI, frame_body_type
\r
2640 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2641 pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));
\r
2642 pframe = rtw_set_fixed_ie(pframe, 1, &(probe_req), &(pattrib->pktlen));
\r
2644 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
\r
2646 wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
\r
2647 pframe += wfdielen;
\r
2648 pattrib->pktlen += wfdielen;
\r
2650 else if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
\r
2652 wfdielen = build_probe_req_wfd_ie(pbuddy_wdinfo, pframe);
\r
2653 pframe += wfdielen;
\r
2654 pattrib->pktlen += wfdielen;
\r
2659 void rtw_build_tunneled_probe_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2662 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2663 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
\r
2664 struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;
\r
2665 u8 payload_type = 0x02;
\r
2666 u8 category = RTW_WLAN_CATEGORY_P2P;
\r
2667 u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};
\r
2672 pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
2673 //category, OUI, frame_body_type
\r
2674 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2675 pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));
\r
2676 pframe = rtw_set_fixed_ie(pframe, 1, &(probe_rsp), &(pattrib->pktlen));
\r
2678 if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
\r
2680 wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 1);
\r
2681 pframe += wfdielen;
\r
2682 pattrib->pktlen += wfdielen;
\r
2684 else if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
\r
2686 wfdielen = build_probe_resp_wfd_ie(pbuddy_wdinfo, pframe, 1);
\r
2687 pframe += wfdielen;
\r
2688 pattrib->pktlen += wfdielen;
\r
2692 #endif //CONFIG_WFD
\r
2694 void _TPK_timer_hdl(void *FunctionContext)
\r
2696 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2698 ptdls_sta->TPK_count++;
\r
2699 //TPK_timer set 1000 as default
\r
2700 //retry timer should set at least 301 sec.
\r
2701 if(ptdls_sta->TPK_count==TPK_RESEND_COUNT){
\r
2702 ptdls_sta->TPK_count=0;
\r
2703 issue_tdls_setup_req(ptdls_sta->padapter, ptdls_sta->hwaddr);
\r
2706 _set_timer(&ptdls_sta->TPK_timer, ptdls_sta->TDLS_PeerKey_Lifetime/TPK_RESEND_COUNT);
\r
2709 void init_TPK_timer(_adapter *padapter, struct sta_info *psta)
\r
2711 psta->padapter=padapter;
\r
2713 _init_timer(&psta->TPK_timer, padapter->pnetdev, _TPK_timer_hdl, psta);
\r
2716 // TDLS_DONE_CH_SEN: channel sensing and report candidate channel
\r
2717 // TDLS_OFF_CH: first time set channel to off channel
\r
2718 // TDLS_BASE_CH: when go back to the channel linked with AP, send null data to peer STA as an indication
\r
2719 void _ch_switch_timer_hdl(void *FunctionContext)
\r
2722 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2723 _adapter *padapter = ptdls_sta->padapter;
\r
2725 if( ptdls_sta->option == TDLS_DONE_CH_SEN ){
\r
2726 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_DONE_CH_SEN);
\r
2727 }else if( ptdls_sta->option == TDLS_OFF_CH ){
\r
2728 issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta, 0);
\r
2729 _set_timer(&ptdls_sta->base_ch_timer, 500);
\r
2730 }else if( ptdls_sta->option == TDLS_BASE_CH){
\r
2731 issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta, 0);
\r
2735 void init_ch_switch_timer(_adapter *padapter, struct sta_info *psta)
\r
2737 psta->padapter=padapter;
\r
2738 _init_timer(&psta->option_timer, padapter->pnetdev, _ch_switch_timer_hdl, psta);
\r
2741 void _base_ch_timer_hdl(void *FunctionContext)
\r
2743 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2744 rtw_tdls_cmd(ptdls_sta->padapter, ptdls_sta->hwaddr, TDLS_P_OFF_CH);
\r
2747 void init_base_ch_timer(_adapter *padapter, struct sta_info *psta)
\r
2749 psta->padapter=padapter;
\r
2750 _init_timer(&psta->base_ch_timer, padapter->pnetdev, _base_ch_timer_hdl, psta);
\r
2753 void _off_ch_timer_hdl(void *FunctionContext)
\r
2755 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2756 rtw_tdls_cmd(ptdls_sta->padapter, ptdls_sta->hwaddr, TDLS_P_BASE_CH );
\r
2759 void init_off_ch_timer(_adapter *padapter, struct sta_info *psta)
\r
2761 psta->padapter=padapter;
\r
2762 _init_timer(&psta->off_ch_timer, padapter->pnetdev, _off_ch_timer_hdl, psta);
\r
2765 void _tdls_handshake_timer_hdl(void *FunctionContext)
\r
2767 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2769 if(ptdls_sta != NULL)
\r
2771 if( !(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) )
\r
2773 DBG_871X("tdls handshake time out\n");
\r
2774 free_tdls_sta(ptdls_sta->padapter, ptdls_sta);
\r
2779 void init_handshake_timer(_adapter *padapter, struct sta_info *psta)
\r
2781 psta->padapter=padapter;
\r
2782 _init_timer(&psta->handshake_timer, padapter->pnetdev, _tdls_handshake_timer_hdl, psta);
\r
2785 //Check tdls peer sta alive.
\r
2786 void _tdls_alive_timer_phase1_hdl(void *FunctionContext)
\r
2789 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2790 _adapter *padapter = ptdls_sta->padapter;
\r
2791 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
2793 _enter_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
\r
2794 ptdls_sta->timer_flag = 1;
\r
2795 _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
\r
2797 ptdls_sta->tdls_sta_state &= (~TDLS_ALIVE_STATE);
\r
2799 DBG_871X("issue_tdls_dis_req to check alive\n");
\r
2800 issue_tdls_dis_req( padapter, ptdls_sta->hwaddr);
\r
2801 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CKALV_PH1);
\r
2802 sta_update_last_rx_pkts(ptdls_sta);
\r
2804 if ( ptdls_sta->timer_flag == 2 )
\r
2805 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_FREE_STA);
\r
2808 _enter_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
\r
2809 ptdls_sta->timer_flag = 0;
\r
2810 _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
\r
2815 void _tdls_alive_timer_phase2_hdl(void *FunctionContext)
\r
2818 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2819 _adapter *padapter = ptdls_sta->padapter;
\r
2820 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
2822 _enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL);
\r
2823 ptdls_sta->timer_flag = 1;
\r
2824 _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
\r
2826 if( (ptdls_sta->tdls_sta_state & TDLS_ALIVE_STATE) &&
\r
2827 (sta_last_rx_pkts(ptdls_sta) + 3 <= sta_rx_pkts(ptdls_sta)) )
\r
2829 DBG_871X("TDLS STA ALIVE, ptdls_sta->sta_stats.last_rx_pkts:%llu, ptdls_sta->sta_stats.rx_pkts:%llu\n",
\r
2830 sta_last_rx_pkts(ptdls_sta), sta_rx_pkts(ptdls_sta));
\r
2832 ptdls_sta->alive_count = 0;
\r
2833 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CKALV_PH2);
\r
2837 if( !(ptdls_sta->tdls_sta_state & TDLS_ALIVE_STATE) )
\r
2838 DBG_871X("TDLS STA TOO FAR\n");
\r
2839 if( !(sta_last_rx_pkts(ptdls_sta) + 3 <= sta_rx_pkts(ptdls_sta)))
\r
2840 DBG_871X("TDLS LINK WITH LOW TRAFFIC, ptdls_sta->sta_stats.last_rx_pkts:%llu, ptdls_sta->sta_stats.rx_pkts:%llu\n",
\r
2841 sta_last_rx_pkts(ptdls_sta), sta_rx_pkts(ptdls_sta));
\r
2843 ptdls_sta->alive_count++;
\r
2844 if( ptdls_sta->alive_count == TDLS_ALIVE_COUNT )
\r
2846 ptdls_sta->stat_code = _RSON_TDLS_TEAR_TOOFAR_;
\r
2847 issue_tdls_teardown(padapter, ptdls_sta->hwaddr);
\r
2851 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CKALV_PH2);
\r
2855 if ( ptdls_sta->timer_flag == 2 )
\r
2856 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_FREE_STA);
\r
2859 _enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL);
\r
2860 ptdls_sta->timer_flag = 0;
\r
2861 _exit_critical_bh(&ptdlsinfo->hdl_lock, &irqL);
\r
2866 void init_tdls_alive_timer(_adapter *padapter, struct sta_info *psta)
\r
2868 psta->padapter=padapter;
\r
2869 _init_timer(&psta->alive_timer1, padapter->pnetdev, _tdls_alive_timer_phase1_hdl, psta);
\r
2870 _init_timer(&psta->alive_timer2, padapter->pnetdev, _tdls_alive_timer_phase2_hdl, psta);
\r
2873 int update_sgi_tdls(_adapter *padapter, struct sta_info *psta)
\r
2875 struct ht_priv *psta_ht = NULL;
\r
2876 psta_ht = &psta->htpriv;
\r
2878 if(psta_ht->ht_option)
\r
2880 return psta_ht->sgi;
\r
2886 u32 update_mask_tdls(_adapter *padapter, struct sta_info *psta)
\r
2890 unsigned char sta_band = 0;
\r
2891 unsigned char limit;
\r
2892 unsigned int tx_ra_bitmap=0;
\r
2893 struct ht_priv *psta_ht = NULL;
\r
2894 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
2895 WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
\r
2897 psta_ht = &psta->htpriv;
\r
2898 //b/g mode ra_bitmap
\r
2899 for (i=0; i<sizeof(psta->bssrateset); i++)
\r
2901 if (psta->bssrateset[i])
\r
2902 tx_ra_bitmap |= rtw_get_bit_value_from_ieee_value(psta->bssrateset[i]&0x7f);
\r
2905 //n mode ra_bitmap
\r
2906 if(psta_ht->ht_option)
\r
2908 padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
\r
2909 if(rf_type == RF_2T2R)
\r
2914 for (i=0; i<limit; i++) {
\r
2915 if (psta_ht->ht_cap.supp_mcs_set[i/8] & BIT(i%8))
\r
2916 tx_ra_bitmap |= BIT(i+12);
\r
2920 if ( pcur_network->Configuration.DSConfig > 14 ) {
\r
2922 if (tx_ra_bitmap & 0xffff000)
\r
2923 sta_band |= WIRELESS_11_5N | WIRELESS_11A;
\r
2925 sta_band |= WIRELESS_11A;
\r
2927 if (tx_ra_bitmap & 0xffff000)
\r
2928 sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
\r
2929 else if (tx_ra_bitmap & 0xff0)
\r
2930 sta_band |= WIRELESS_11G |WIRELESS_11B;
\r
2932 sta_band |= WIRELESS_11B;
\r
2935 id = networktype_to_raid(sta_band);
\r
2936 tx_ra_bitmap |= ((id<<28)&0xf0000000);
\r
2937 return tx_ra_bitmap;
\r
2940 #endif //CONFIG_TDLS
\r