Merge tag 'lsk-v3.10-15.09-android'
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bu / core / rtw_tdls.c
1 /******************************************************************************\r
2  *\r
3  * Copyright(c) 2007 - 2011 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_TDLS_C_\r
21 \r
22 #include <drv_types.h>\r
23 \r
24 #ifdef CONFIG_TDLS\r
25 extern void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame);\r
26 \r
27 void rtw_reset_tdls_info(_adapter* padapter)\r
28 {\r
29         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;\r
30 \r
31         ptdlsinfo->ap_prohibited = _FALSE;\r
32         ptdlsinfo->link_established = _FALSE;\r
33         ptdlsinfo->sta_cnt = 0;\r
34         ptdlsinfo->sta_maximum = _FALSE;\r
35         ptdlsinfo->ch_sensing = 0;\r
36         ptdlsinfo->cur_channel = 0;\r
37         ptdlsinfo->candidate_ch = 1;    //when inplement channel switching, default candidate channel is 1\r
38         ptdlsinfo->watchdog_count = 0;\r
39         ptdlsinfo->dev_discovered = 0;\r
40 \r
41 #ifdef CONFIG_WFD\r
42         ptdlsinfo->wfd_info = &padapter->wfd_info;\r
43 #endif //CONFIG_WFD\r
44 }\r
45 \r
46 int rtw_init_tdls_info(_adapter* padapter)\r
47 {\r
48         int     res = _SUCCESS;\r
49         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;\r
50 \r
51         ptdlsinfo->tdls_enable = _TRUE;\r
52         rtw_reset_tdls_info(padapter);\r
53 \r
54         _rtw_spinlock_init(&ptdlsinfo->cmd_lock);\r
55         _rtw_spinlock_init(&ptdlsinfo->hdl_lock);\r
56 \r
57         return res;\r
58 \r
59 }\r
60 \r
61 void rtw_free_tdls_info(struct tdls_info *ptdlsinfo)\r
62 {\r
63         _rtw_spinlock_free(&ptdlsinfo->cmd_lock);\r
64         _rtw_spinlock_free(&ptdlsinfo->hdl_lock);\r
65 \r
66         _rtw_memset(ptdlsinfo, 0, sizeof(struct tdls_info) );\r
67 \r
68 }\r
69 \r
70 int _issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)\r
71 {\r
72         int ret = _FAIL;\r
73         struct xmit_frame                       *pmgntframe;\r
74         struct pkt_attrib                       *pattrib;\r
75         unsigned char                                   *pframe;\r
76         struct rtw_ieee80211_hdr        *pwlanhdr;\r
77         unsigned short                          *fctrl;\r
78         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);\r
79         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
80         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
81 \r
82         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
83         {\r
84                 goto exit;\r
85         }\r
86 \r
87         //update attribute\r
88         pattrib = &pmgntframe->attrib;\r
89         update_mgntframe_attrib(padapter, pattrib);\r
90         pattrib->retry_ctrl = _FALSE;\r
91 \r
92         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
93 \r
94         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
95         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
96 \r
97         fctrl = &(pwlanhdr->frame_ctl);\r
98         *(fctrl) = 0;\r
99 \r
100         //      SetToDs(fctrl);\r
101 \r
102         if (power_mode)\r
103         {\r
104                 SetPwrMgt(fctrl);\r
105         }\r
106 \r
107         _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);\r
108         _rtw_memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
109         _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);\r
110 \r
111         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);\r
112         pmlmeext->mgnt_seq++;\r
113         SetFrameSubType(pframe, WIFI_DATA_NULL);\r
114 \r
115         pframe += sizeof(struct rtw_ieee80211_hdr_3addr);\r
116         pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);\r
117 \r
118         pattrib->last_txcmdsz = pattrib->pktlen;\r
119 \r
120         if(wait_ack)\r
121         {\r
122                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);\r
123         }\r
124         else\r
125         {\r
126                 dump_mgntframe(padapter, pmgntframe);\r
127                 ret = _SUCCESS;\r
128         }\r
129 \r
130 exit:\r
131         return ret;\r
132 \r
133 }\r
134 \r
135 int issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)\r
136 {\r
137         int ret;\r
138         int i = 0;\r
139         u32 start = rtw_get_current_time();\r
140         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
141         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
142 \r
143         //[TDLS] UAPSD : merge this from issue_nulldata() and mark it first.\r
144         #if 0\r
145         psta = rtw_get_stainfo(&padapter->stapriv, da);\r
146         if (psta) {\r
147                 if (power_mode)\r
148                         rtw_hal_macid_sleep(padapter, psta->mac_id);\r
149                 else\r
150                         rtw_hal_macid_wakeup(padapter, psta->mac_id);\r
151         } else {\r
152                 DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",\r
153                         FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup");\r
154                 rtw_warn_on(1);\r
155         }\r
156         #endif\r
157 \r
158         do\r
159         {\r
160                 ret = _issue_nulldata_to_TDLS_peer_STA(padapter, da, power_mode, wait_ms>0 ? _TRUE : _FALSE);\r
161 \r
162                 i++;\r
163 \r
164                 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)\r
165                         break;\r
166 \r
167                 if(i < try_cnt && wait_ms > 0 && ret==_FAIL)\r
168                         rtw_msleep_os(wait_ms);\r
169 \r
170         }while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));\r
171 \r
172         if (ret != _FAIL) {\r
173                 ret = _SUCCESS;\r
174                 #ifndef DBG_XMIT_ACK\r
175                 goto exit;\r
176                 #endif\r
177         }\r
178 \r
179         if (try_cnt && wait_ms) {\r
180                 if (da)\r
181                         DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",\r
182                                 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),\r
183                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));\r
184                 else\r
185                         DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",\r
186                                 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),\r
187                                 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));\r
188         }\r
189 exit:\r
190         return ret;\r
191 }\r
192 \r
193 void free_tdls_sta(_adapter *padapter, struct sta_info *ptdls_sta)\r
194 {\r
195         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;\r
196         struct sta_priv *pstapriv = &padapter->stapriv;\r
197         _irqL irqL;\r
198         \r
199         //free peer sta_info\r
200         _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);\r
201         if(ptdlsinfo->sta_cnt != 0)\r
202                 ptdlsinfo->sta_cnt--;\r
203         _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);\r
204         if( ptdlsinfo->sta_cnt < (NUM_STA - 2 - 4) )    // -2: AP + BC/MC sta, -4: default key\r
205         {\r
206                 ptdlsinfo->sta_maximum = _FALSE;\r
207                 _rtw_memset( &ptdlsinfo->ss_record, 0x00, sizeof(struct tdls_ss_record) );\r
208         }\r
209 \r
210         //clear cam\r
211         rtw_clearstakey_cmd(padapter, ptdls_sta, _TRUE);\r
212 \r
213         if(ptdlsinfo->sta_cnt==0){\r
214                 rtw_tdls_cmd(padapter, myid(&(padapter->eeprompriv)), TDLS_RS_RCR);\r
215                 ptdlsinfo->link_established = _FALSE;\r
216         }\r
217         else\r
218                 DBG_871X("Remain tdls sta:%02x\n", ptdlsinfo->sta_cnt);\r
219 \r
220         rtw_free_stainfo(padapter,  ptdls_sta);\r
221         \r
222 }\r
223 \r
224 \r
225 //TDLS encryption(if needed) will always be CCMP\r
226 void rtw_tdls_set_key(_adapter *padapter, struct rx_pkt_attrib *prx_pkt_attrib, struct sta_info *ptdls_sta)\r
227 {\r
228         if(prx_pkt_attrib->encrypt)\r
229         {\r
230                 ptdls_sta->dot118021XPrivacy=_AES_;\r
231                 rtw_setstakey_cmd(padapter, ptdls_sta, _TRUE, _TRUE);\r
232         }\r
233 }\r
234 \r
235 void rtw_tdls_process_ht_cap(_adapter *padapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)\r
236 {\r
237         /* save HT capabilities in the sta object */\r
238         _rtw_memset(&ptdls_sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));\r
239         if (data && Length >= sizeof(struct rtw_ieee80211_ht_cap) )\r
240         {\r
241                 ptdls_sta->flags |= WLAN_STA_HT;\r
242                 \r
243                 ptdls_sta->flags |= WLAN_STA_WME;\r
244                 \r
245                 _rtw_memcpy(&ptdls_sta->htpriv.ht_cap, data, sizeof(struct rtw_ieee80211_ht_cap));                      \r
246                 \r
247         } else\r
248                 ptdls_sta->flags &= ~WLAN_STA_HT;\r
249 \r
250         if(ptdls_sta->flags & WLAN_STA_HT)\r
251         {\r
252                 if(padapter->registrypriv.ht_enable == _TRUE)\r
253                 {\r
254                         ptdls_sta->htpriv.ht_option = _TRUE;\r
255                 }\r
256                 else\r
257                 {\r
258                         ptdls_sta->htpriv.ht_option = _FALSE;\r
259                         ptdls_sta->stat_code = _STATS_FAILURE_;\r
260                 }\r
261         }\r
262 \r
263         //HT related cap\r
264         if(ptdls_sta->htpriv.ht_option)\r
265         {\r
266                 //check if sta supports rx ampdu\r
267                 if(padapter->registrypriv.ampdu_enable==1)\r
268                         ptdls_sta->htpriv.ampdu_enable = _TRUE;\r
269 \r
270                 //check if sta support s Short GI 20M\r
271                 if(ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))\r
272                 {\r
273                         ptdls_sta->htpriv.sgi_20m = _TRUE;\r
274                 }\r
275                 //check if sta support s Short GI 40M\r
276                 if(ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))\r
277                 {\r
278                         ptdls_sta->htpriv.sgi_40m = _TRUE;\r
279                 }\r
280 \r
281                 // bwmode would still followed AP's setting\r
282                 if(ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))\r
283                 {\r
284                         if (padapter->mlmeextpriv.cur_bwmode >= CHANNEL_WIDTH_40)\r
285                                 ptdls_sta->bw_mode = CHANNEL_WIDTH_40;\r
286                         ptdls_sta->htpriv.ch_offset = padapter->mlmeextpriv.cur_ch_offset;\r
287                 }\r
288         }\r
289 \r
290 }\r
291 \r
292 int rtw_tdls_set_ht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)\r
293 {\r
294         int tmplen;\r
295 \r
296         rtw_ht_use_default_setting(padapter);\r
297 \r
298         tmplen = pattrib->pktlen;\r
299         rtw_restructure_ht_ie(padapter, NULL, pframe, 0, &(pattrib->pktlen), padapter->mlmeextpriv.cur_channel);\r
300 \r
301         return (pattrib->pktlen - tmplen);\r
302 \r
303 }\r
304 \r
305 u8 *rtw_tdls_set_sup_ch(struct mlme_ext_priv *pmlmeext, u8 *pframe, struct pkt_attrib *pattrib)\r
306 {\r
307         u8 sup_ch[ 30 * 2 ] = { 0x00 }, ch_set_idx = 0; //For supported channel\r
308         u8 ch_24g = 0, b1 = 0, b4 = 0;\r
309         u8 bit_table = 0, sup_ch_idx = 0;\r
310 \r
311         do{\r
312                 if( pmlmeext->channel_set[ch_set_idx].ChannelNum >= 1 &&\r
313                         pmlmeext->channel_set[ch_set_idx].ChannelNum <= 14 )\r
314                 {\r
315                         ch_24g = 1;     // 2.4 G channels\r
316                 }\r
317                 else if( pmlmeext->channel_set[ch_set_idx].ChannelNum >= 36 && \r
318                         pmlmeext->channel_set[ch_set_idx].ChannelNum <= 48)\r
319                 {\r
320                         b1 = 1; // 5 G band1\r
321                 }\r
322                 else if( pmlmeext->channel_set[ch_set_idx].ChannelNum >= 149 && \r
323                         pmlmeext->channel_set[ch_set_idx].ChannelNum <= 165)\r
324                 {\r
325                         b4 = 1; // 5 G band4\r
326                 }\r
327                 else\r
328                 {\r
329                         ch_set_idx++;   // We don't claim that we support DFS channels.\r
330                         continue;\r
331                 }\r
332 \r
333                 sup_ch_idx = (ch_24g + b1 + b4 - 1) * 2;\r
334                 if( sup_ch_idx >= 0)\r
335                 {\r
336                         if(sup_ch[sup_ch_idx] == 0)\r
337                                 sup_ch[sup_ch_idx] = pmlmeext->channel_set[ch_set_idx].ChannelNum;\r
338                         sup_ch[sup_ch_idx+1]++; //Number of channel\r
339                 }\r
340 \r
341                 ch_set_idx++;\r
342         }\r
343         while( pmlmeext->channel_set[ch_set_idx].ChannelNum != 0 && ch_set_idx < MAX_CHANNEL_NUM );\r
344 \r
345         return(rtw_set_ie(pframe, _SUPPORTED_CH_IE_, sup_ch_idx+2, sup_ch, &(pattrib->pktlen)));\r
346 }\r
347 \r
348 #ifdef CONFIG_WFD\r
349 void rtw_tdls_process_wfd_ie(struct tdls_info *ptdlsinfo, u8 *ptr, u8 length)\r
350 {\r
351         u8      wfd_ie[ 128 ] = { 0x00 };\r
352         u32     wfd_ielen = 0;\r
353         u32     wfd_offset = 0;\r
354         //      Try to get the TCP port information when receiving the negotiation response.\r
355         //\r
356 \r
357         wfd_offset = 0;\r
358         wfd_offset = rtw_get_wfd_ie( ptr + wfd_offset, length - wfd_offset, wfd_ie, &wfd_ielen );\r
359         while( wfd_offset )\r
360         {\r
361                 u8      attr_content[ 10 ] = { 0x00 };\r
362                 u32     attr_contentlen = 0;\r
363                 int     i;\r
364 \r
365                 DBG_871X( "[%s] WFD IE Found!!\n", __FUNCTION__ );\r
366                 rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);\r
367                 if ( attr_contentlen )\r
368                 {\r
369                         ptdlsinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );\r
370                         DBG_871X( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, ptdlsinfo->wfd_info->peer_rtsp_ctrlport );\r
371                 }\r
372 \r
373                 _rtw_memset( attr_content, 0x00, 10);\r
374                 attr_contentlen = 0;\r
375                 rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_LOCAL_IP_ADDR, attr_content, &attr_contentlen);\r
376                 if ( attr_contentlen )\r
377                 {\r
378                         _rtw_memcpy(ptdlsinfo->wfd_info->peer_ip_address, ( attr_content + 1 ), 4);\r
379                         DBG_871X( "[%s] Peer IP = %02u.%02u.%02u.%02u \n", __FUNCTION__, \r
380                                 ptdlsinfo->wfd_info->peer_ip_address[0], ptdlsinfo->wfd_info->peer_ip_address[1],\r
381                                 ptdlsinfo->wfd_info->peer_ip_address[2], ptdlsinfo->wfd_info->peer_ip_address[3]\r
382                                 );\r
383                 }\r
384                 wfd_offset = rtw_get_wfd_ie( ptr + wfd_offset, length - wfd_offset, wfd_ie, &wfd_ielen );\r
385         }\r
386 }\r
387 \r
388 int issue_tunneled_probe_req(_adapter *padapter)\r
389 {\r
390         struct xmit_frame                       *pmgntframe;\r
391         struct pkt_attrib                       *pattrib;\r
392         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
393         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);\r
394         u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; \r
395         struct tdls_txmgmt txmgmt;\r
396         int ret = _FAIL;\r
397 \r
398         DBG_871X("[%s]\n", __FUNCTION__);\r
399 \r
400         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
401         txmgmt.action_code = TUNNELED_PROBE_REQ;\r
402 \r
403         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
404         {\r
405                 goto exit;\r
406         }\r
407         \r
408         //update attribute\r
409         pattrib = &pmgntframe->attrib;\r
410 \r
411         pmgntframe->frame_tag = DATA_FRAMETAG;\r
412         pattrib->ether_type = 0x890d;\r
413 \r
414         _rtw_memcpy(pattrib->dst, baddr, ETH_ALEN);\r
415         _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
416         _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);\r
417         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
418 \r
419         update_tdls_attrib(padapter, pattrib);\r
420         pattrib->qsel = pattrib->priority;\r
421         if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {\r
422                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);\r
423                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
424                 goto exit;\r
425         }\r
426         dump_mgntframe(padapter, pmgntframe);\r
427         ret = _SUCCESS;\r
428 exit:\r
429 \r
430         return ret;\r
431 }\r
432 \r
433 int issue_tunneled_probe_rsp(_adapter *padapter, union recv_frame *precv_frame)\r
434 {\r
435         struct xmit_frame                       *pmgntframe;\r
436         struct pkt_attrib                       *pattrib;\r
437         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
438         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);\r
439         struct tdls_txmgmt txmgmt;\r
440         int ret = _FAIL;\r
441 \r
442         DBG_871X("[%s]\n", __FUNCTION__);\r
443 \r
444         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
445         txmgmt.action_code = TUNNELED_PROBE_RSP;\r
446 \r
447         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
448         {\r
449                 goto exit;\r
450         }\r
451         \r
452         //update attribute\r
453         pattrib = &pmgntframe->attrib;\r
454 \r
455         pmgntframe->frame_tag = DATA_FRAMETAG;\r
456         pattrib->ether_type = 0x890d;\r
457 \r
458         _rtw_memcpy(pattrib->dst, precv_frame->u.hdr.attrib.src, ETH_ALEN);\r
459         _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
460         _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);\r
461         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
462 \r
463         update_tdls_attrib(padapter, pattrib);\r
464         pattrib->qsel = pattrib->priority;\r
465         if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {\r
466                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);\r
467                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
468                 goto exit;\r
469         }\r
470         dump_mgntframe(padapter, pmgntframe);\r
471         ret = _SUCCESS;\r
472 exit:\r
473 \r
474         return ret;\r
475 }\r
476 #endif //CONFIG_WFD\r
477 \r
478 int issue_tdls_setup_req(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, int wait_ack)\r
479 {\r
480         struct tdls_info        *ptdlsinfo = &padapter->tdlsinfo;\r
481         struct xmit_frame                       *pmgntframe;\r
482         struct pkt_attrib                       *pattrib;\r
483         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
484         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);\r
485         struct sta_priv *pstapriv = &padapter->stapriv;\r
486         struct sta_info *ptdls_sta= NULL;\r
487         _irqL irqL;\r
488         static u8 dialogtoken = 0;\r
489         int ret = _FAIL;\r
490         u32 timeout_interval= TPK_RESEND_COUNT * 1000;  //retry timer should set at least 301 sec, using TPK_count counting 301 times.\r
491 \r
492         ptxmgmt->action_code = TDLS_SETUP_REQUEST;\r
493         if(ptdlsinfo->ap_prohibited == _TRUE)\r
494                 goto exit;\r
495 \r
496         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
497         {\r
498                 goto exit;\r
499         }\r
500         \r
501         //update attribute\r
502         pattrib = &pmgntframe->attrib;\r
503         pmgntframe->frame_tag = DATA_FRAMETAG;\r
504         pattrib->ether_type = 0x890d;\r
505 \r
506         _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);\r
507         _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
508         _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);\r
509         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
510 \r
511         update_tdls_attrib(padapter, pattrib);\r
512 \r
513         //init peer sta_info\r
514         ptdls_sta = rtw_get_stainfo(pstapriv, ptxmgmt->peer);\r
515         if(ptdls_sta==NULL)\r
516         {\r
517                 ptdls_sta = rtw_alloc_stainfo(pstapriv, ptxmgmt->peer);\r
518                 if(ptdls_sta==NULL)\r
519                 {\r
520                         DBG_871X("[%s] rtw_alloc_stainfo fail\n", __FUNCTION__);        \r
521                         rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);\r
522                         rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
523                         goto exit;\r
524                 }\r
525         }\r
526         \r
527         if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))\r
528                 ptdlsinfo->sta_cnt++;\r
529         if( ptdlsinfo->sta_cnt == (NUM_STA - 2 - 4) )   // -2: AP + BC/MC sta, -4: default key\r
530         {\r
531                 ptdlsinfo->sta_maximum  = _TRUE;\r
532         }\r
533 \r
534         ptdls_sta->tdls_sta_state |= TDLS_RESPONDER_STATE;\r
535         //for tdls; ptdls_sta->aid is used to fill dialogtoken\r
536         ptdls_sta->dialog = dialogtoken;\r
537         dialogtoken = (dialogtoken+1)%256;\r
538         ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;\r
539         _set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME );\r
540 \r
541         pattrib->qsel = pattrib->priority;\r
542 \r
543         if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) !=_SUCCESS ){\r
544                 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);\r
545                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
546                 goto exit;\r
547         }\r
548 \r
549         if (wait_ack) {\r
550                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);\r
551         } else {\r
552                 dump_mgntframe(padapter, pmgntframe);\r
553                 ret = _SUCCESS;\r
554         }\r
555 \r
556         ret = _SUCCESS;\r
557 \r
558 exit:\r
559 \r
560         return ret;\r
561 }\r
562 \r
563 int issue_tdls_teardown(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 wait_ack)\r
564 {\r
565         struct xmit_frame                       *pmgntframe;\r
566         struct pkt_attrib                       *pattrib;\r
567         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
568         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);\r
569         struct sta_priv *pstapriv = &padapter->stapriv;\r
570         struct sta_info *ptdls_sta=NULL;\r
571         _irqL irqL;\r
572         int ret = _FAIL;\r
573 \r
574         ptxmgmt->action_code = TDLS_TEARDOWN;\r
575         ptdls_sta = rtw_get_stainfo(pstapriv, ptxmgmt->peer);\r
576         if(ptdls_sta==NULL){\r
577                 DBG_871X("Np tdls_sta for tearing down\n");\r
578                 goto exit;\r
579         }\r
580 \r
581         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
582         {\r
583                 goto exit;\r
584         }\r
585         \r
586         //update attribute\r
587         pattrib = &pmgntframe->attrib;\r
588 \r
589         pmgntframe->frame_tag = DATA_FRAMETAG;\r
590         pattrib->ether_type = 0x890d;\r
591 \r
592         _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);\r
593         _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
594         _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);\r
595         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
596 \r
597         update_tdls_attrib(padapter, pattrib);\r
598         pattrib->qsel = pattrib->priority;\r
599         if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {\r
600                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);\r
601                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
602                 goto exit;\r
603         }\r
604 \r
605         if (wait_ack) {\r
606                 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);\r
607         } else {\r
608                 dump_mgntframe(padapter, pmgntframe);\r
609                 ret = _SUCCESS;\r
610         }\r
611 \r
612         if(ret == _SUCCESS)\r
613         {\r
614                 if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE){\r
615                         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CS_OFF);\r
616                 }\r
617                 \r
618                 if( ptdls_sta->timer_flag == 1 )\r
619                 {\r
620                         _enter_critical_bh(&(padapter->tdlsinfo.hdl_lock), &irqL);\r
621                         ptdls_sta->timer_flag = 2;\r
622                         _exit_critical_bh(&(padapter->tdlsinfo.hdl_lock), &irqL);\r
623                 }\r
624                 else\r
625                         rtw_tdls_cmd(padapter, ptxmgmt->peer, TDLS_TEAR_STA );\r
626         }\r
627 \r
628 exit:\r
629 \r
630         return ret;\r
631 }\r
632 \r
633 int issue_tdls_dis_req(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)\r
634 {\r
635         struct xmit_frame                       *pmgntframe;\r
636         struct pkt_attrib                       *pattrib;\r
637         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
638         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);\r
639         int ret = _FAIL;\r
640         \r
641         ptxmgmt->action_code = TDLS_DISCOVERY_REQUEST;\r
642         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
643         {\r
644                 goto exit;\r
645         }\r
646 \r
647         //update attribute\r
648         pattrib = &pmgntframe->attrib;\r
649         pmgntframe->frame_tag = DATA_FRAMETAG;\r
650         pattrib->ether_type = 0x890d;\r
651 \r
652         _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);\r
653         _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
654         _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);\r
655         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
656 \r
657         update_tdls_attrib(padapter, pattrib);\r
658         pattrib->qsel = pattrib->priority;\r
659         if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {\r
660                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);\r
661                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
662                 goto exit;\r
663         }\r
664         dump_mgntframe(padapter, pmgntframe);\r
665         DBG_871X("issue tdls dis req\n");\r
666 \r
667         ret = _SUCCESS;\r
668 exit:\r
669 \r
670         return ret;\r
671 }\r
672 \r
673 int issue_tdls_setup_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)\r
674 {\r
675         struct xmit_frame                       *pmgntframe;\r
676         struct pkt_attrib                       *pattrib;\r
677         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);\r
678         int ret = _FAIL;\r
679 \r
680         ptxmgmt->action_code = TDLS_SETUP_RESPONSE;             \r
681         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
682         {\r
683                 goto exit;\r
684         }\r
685         \r
686         //update attribute\r
687         pattrib = &pmgntframe->attrib;\r
688         pmgntframe->frame_tag = DATA_FRAMETAG;\r
689         pattrib->ether_type = 0x890d;\r
690 \r
691         _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);\r
692         _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
693         _rtw_memcpy(pattrib->ra, get_bssid(&(padapter->mlmepriv)), ETH_ALEN);\r
694         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
695 \r
696         update_tdls_attrib(padapter, pattrib);\r
697         pattrib->qsel = pattrib->priority;\r
698         if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {\r
699                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);\r
700                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
701                 goto exit;\r
702         }\r
703 \r
704         dump_mgntframe(padapter, pmgntframe);\r
705 \r
706         ret = _SUCCESS;\r
707 exit:\r
708 \r
709         return ret;\r
710 \r
711 }\r
712 \r
713 int issue_tdls_setup_cfm(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)\r
714 {\r
715         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;\r
716         struct xmit_frame                       *pmgntframe;\r
717         struct pkt_attrib                       *pattrib;\r
718         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);\r
719         int ret = _FAIL;\r
720         \r
721         ptxmgmt->action_code = TDLS_SETUP_CONFIRM;\r
722         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
723         {\r
724                 goto exit;\r
725         }\r
726         \r
727         //update attribute\r
728         pattrib = &pmgntframe->attrib;\r
729         pmgntframe->frame_tag = DATA_FRAMETAG;\r
730         pattrib->ether_type = 0x890d;\r
731 \r
732         _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);\r
733         _rtw_memcpy(pattrib->src, myid(&padapter->eeprompriv), ETH_ALEN);\r
734         _rtw_memcpy(pattrib->ra, get_bssid(&padapter->mlmepriv), ETH_ALEN);\r
735         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
736 \r
737         update_tdls_attrib(padapter, pattrib);\r
738         pattrib->qsel = pattrib->priority;\r
739         if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {\r
740                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);\r
741                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
742                 goto exit;              \r
743         }\r
744 \r
745         dump_mgntframe(padapter, pmgntframe);\r
746 \r
747         ret = _SUCCESS;\r
748 exit:\r
749 \r
750         return ret;\r
751 \r
752 }\r
753 \r
754 //TDLS Discovery Response frame is a management action frame\r
755 int issue_tdls_dis_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 privacy)\r
756 {\r
757         struct xmit_frame               *pmgntframe;\r
758         struct pkt_attrib               *pattrib;\r
759         unsigned char                   *pframe;\r
760         struct rtw_ieee80211_hdr        *pwlanhdr;\r
761         unsigned short          *fctrl;\r
762         struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);\r
763         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
764         int ret = _FAIL;\r
765 \r
766         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
767         {\r
768                 goto exit;\r
769         }\r
770 \r
771         //update attribute\r
772         pattrib = &pmgntframe->attrib;\r
773         update_mgntframe_attrib(padapter, pattrib);\r
774 \r
775         _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);\r
776 \r
777         pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;\r
778         pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;\r
779 \r
780         fctrl = &(pwlanhdr->frame_ctl);\r
781         *(fctrl) = 0;\r
782 \r
783         //      unicast probe request frame\r
784         _rtw_memcpy(pwlanhdr->addr1, ptxmgmt->peer, ETH_ALEN);\r
785         _rtw_memcpy(pattrib->dst, pwlanhdr->addr1, ETH_ALEN);\r
786         _rtw_memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);\r
787         _rtw_memcpy(pattrib->src, pwlanhdr->addr2, ETH_ALEN);\r
788         _rtw_memcpy(pwlanhdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN);\r
789         _rtw_memcpy(pattrib->ra, pwlanhdr->addr3, ETH_ALEN);\r
790         \r
791         SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);\r
792         pmlmeext->mgnt_seq++;\r
793         SetFrameSubType(pframe, WIFI_ACTION);\r
794 \r
795         pframe += sizeof (struct rtw_ieee80211_hdr_3addr);\r
796         pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);\r
797 \r
798         rtw_build_tdls_dis_rsp_ies(padapter, pmgntframe, pframe, ptxmgmt->dialog_token, privacy);\r
799 \r
800         pattrib->nr_frags = 1;\r
801         pattrib->last_txcmdsz = pattrib->pktlen;\r
802 \r
803         dump_mgntframe(padapter, pmgntframe);\r
804         ret = _SUCCESS;\r
805 \r
806 exit:\r
807         return ret;\r
808 }\r
809 \r
810 int issue_tdls_peer_traffic_rsp(_adapter *padapter, struct sta_info *ptdls_sta)\r
811 {\r
812         struct xmit_frame       *pmgntframe;\r
813         struct pkt_attrib       *pattrib;\r
814         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
815         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);\r
816         struct tdls_txmgmt txmgmt;\r
817         int ret = _FAIL;\r
818 \r
819         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
820         txmgmt.action_code = TDLS_PEER_TRAFFIC_RESPONSE;\r
821 \r
822         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
823         {\r
824                 goto exit;\r
825         }\r
826         \r
827         //update attribute\r
828         pattrib = &pmgntframe->attrib;\r
829 \r
830         pmgntframe->frame_tag = DATA_FRAMETAG;\r
831         pattrib->ether_type = 0x890d;\r
832 \r
833         _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);\r
834         _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
835         _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);\r
836         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
837 \r
838         update_tdls_attrib(padapter, pattrib);\r
839         pattrib->qsel = pattrib->priority;\r
840 \r
841         if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) !=_SUCCESS ){\r
842                 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);\r
843                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
844                 goto exit;      \r
845         }\r
846 \r
847         dump_mgntframe(padapter, pmgntframe);\r
848         ret = _SUCCESS;\r
849 \r
850 exit:\r
851 \r
852         return ret;\r
853 }\r
854 \r
855 int issue_tdls_peer_traffic_indication(_adapter *padapter, struct sta_info *ptdls_sta)\r
856 {\r
857         struct xmit_frame                       *pmgntframe;\r
858         struct pkt_attrib                       *pattrib;\r
859         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
860         struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);\r
861         struct tdls_txmgmt txmgmt;\r
862         int ret = _FAIL;\r
863         static u8 dialogtoken=0;\r
864 \r
865         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
866         txmgmt.action_code = TDLS_PEER_TRAFFIC_INDICATION;\r
867 \r
868         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
869         {\r
870                 goto exit;\r
871         }\r
872         \r
873         //update attribute\r
874         pattrib = &pmgntframe->attrib;\r
875 \r
876         pmgntframe->frame_tag = DATA_FRAMETAG;\r
877         pattrib->ether_type = 0x890d;\r
878 \r
879         _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);\r
880         _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
881         _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);\r
882         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
883 \r
884         //for tdls; pattrib->nr_frags is used to fill dialogtoken\r
885         ptdls_sta->dialog = dialogtoken;\r
886         dialogtoken = (dialogtoken+1)%256;\r
887         //PTI frame's priority should be AC_VO\r
888         pattrib->priority = 7; \r
889 \r
890         update_tdls_attrib(padapter, pattrib);\r
891         pattrib->qsel = pattrib->priority;\r
892         if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {\r
893                 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);\r
894                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
895                 goto exit;\r
896         }\r
897 \r
898         dump_mgntframe(padapter, pmgntframe);\r
899         ret = _SUCCESS;\r
900         \r
901 exit:\r
902 \r
903         return ret;\r
904 }\r
905 \r
906 int issue_tdls_ch_switch_req(_adapter *padapter, u8 *mac_addr)\r
907 {\r
908         struct xmit_frame       *pmgntframe;\r
909         struct pkt_attrib       *pattrib;\r
910         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
911         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);\r
912         struct tdls_txmgmt txmgmt;\r
913         int ret = _FAIL;\r
914 \r
915         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
916         txmgmt.action_code = TDLS_CHANNEL_SWITCH_REQUEST;\r
917 \r
918         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
919         {\r
920                 goto exit;\r
921         }\r
922         \r
923         //update attribute\r
924         pattrib = &pmgntframe->attrib;\r
925 \r
926         pmgntframe->frame_tag = DATA_FRAMETAG;\r
927         pattrib->ether_type = 0x890d;\r
928 \r
929         _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);\r
930         _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
931         _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);\r
932         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
933 \r
934         update_tdls_attrib(padapter, pattrib);\r
935         pattrib->qsel = pattrib->priority;\r
936         if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) !=_SUCCESS ){\r
937                 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);\r
938                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
939                 goto exit;\r
940         }\r
941 \r
942         dump_mgntframe(padapter, pmgntframe);\r
943         ret = _SUCCESS;\r
944 exit:\r
945 \r
946         return ret;\r
947 }\r
948 \r
949 int issue_tdls_ch_switch_rsp(_adapter *padapter, u8 *mac_addr)\r
950 {\r
951         struct xmit_frame       *pmgntframe;\r
952         struct pkt_attrib       *pattrib;\r
953         struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;\r
954         struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);\r
955         struct tdls_txmgmt txmgmt;\r
956         int ret = _FAIL;\r
957 \r
958         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
959         txmgmt.action_code = TDLS_CHANNEL_SWITCH_RESPONSE;\r
960 \r
961         if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)\r
962         {\r
963                 goto exit;\r
964         }\r
965         \r
966         //update attribute\r
967         pattrib = &pmgntframe->attrib;\r
968 \r
969         pmgntframe->frame_tag = DATA_FRAMETAG;\r
970         pattrib->ether_type = 0x890d;\r
971 \r
972         _rtw_memcpy(pattrib->dst, mac_addr, ETH_ALEN);\r
973         _rtw_memcpy(pattrib->src, myid(&(padapter->eeprompriv)), ETH_ALEN);\r
974         _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);\r
975         _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);\r
976 \r
977         update_tdls_attrib(padapter, pattrib);\r
978         pattrib->qsel = pattrib->priority;\r
979 /*\r
980         _enter_critical_bh(&pxmitpriv->lock, &irqL);\r
981         if(xmitframe_enqueue_for_tdls_sleeping_sta(padapter, pmgntframe)==_TRUE){\r
982                 _exit_critical_bh(&pxmitpriv->lock, &irqL);\r
983                 return _FALSE;\r
984         }\r
985 */\r
986         if(rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) !=_SUCCESS ){\r
987                 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);\r
988                 rtw_free_xmitframe(pxmitpriv, pmgntframe);\r
989                 goto exit;      \r
990         }\r
991         dump_mgntframe(padapter, pmgntframe);\r
992         ret = _SUCCESS;\r
993 exit:\r
994 \r
995         return ret;\r
996 }\r
997 \r
998 int On_TDLS_Dis_Rsp(_adapter *padapter, union recv_frame *precv_frame)\r
999 {\r
1000         struct sta_info *ptdls_sta = NULL, *psta = rtw_get_stainfo(&(padapter->stapriv), get_bssid(&(padapter->mlmepriv)));\r
1001         struct recv_priv *precvpriv = &(padapter->recvpriv);\r
1002         u8 *ptr = precv_frame->u.hdr.rx_data, *psa;\r
1003         struct rx_pkt_attrib *pattrib = &(precv_frame->u.hdr.attrib);\r
1004         struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);\r
1005         u8 empty_addr[ETH_ALEN] = { 0x00 };\r
1006         int UndecoratedSmoothedPWDB;\r
1007         struct tdls_txmgmt txmgmt;      \r
1008         int ret = _SUCCESS;\r
1009 \r
1010         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
1011         //WFDTDLS: for sigma test, not to setup direct link automatically\r
1012         ptdlsinfo->dev_discovered = 1;\r
1013 \r
1014 #ifdef CONFIG_TDLS_AUTOSETUP\r
1015         psa = get_sa(ptr);\r
1016         ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), psa);\r
1017 \r
1018         if(ptdls_sta != NULL)\r
1019         {\r
1020                 ptdls_sta->tdls_sta_state |= TDLS_ALIVE_STATE;\r
1021 \r
1022                 //Record the tdls sta with lowest signal strength\r
1023                 if( (ptdlsinfo->sta_maximum == _TRUE) && (ptdls_sta->alive_count >= 1) )\r
1024                 {\r
1025                         if( _rtw_memcmp(ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN) )\r
1026                         {\r
1027                                 _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);\r
1028                                 ptdlsinfo->ss_record.RxPWDBAll = pattrib->RxPWDBAll;\r
1029                         }\r
1030                         else\r
1031                         {\r
1032                                 if( ptdlsinfo->ss_record.RxPWDBAll < pattrib->RxPWDBAll )\r
1033                                 {\r
1034                                         _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);\r
1035                                         ptdlsinfo->ss_record.RxPWDBAll = pattrib->RxPWDBAll;\r
1036                                 }\r
1037                         }\r
1038                 }\r
1039 \r
1040         }\r
1041         else\r
1042         {\r
1043                 if( ptdlsinfo->sta_maximum == _TRUE)\r
1044                 {\r
1045                         if( _rtw_memcmp( ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN ) )\r
1046                         {\r
1047                                 //All traffics are busy, do not set up another direct link.\r
1048                                 ret = _FAIL;\r
1049                                 goto exit;\r
1050                         }\r
1051                         else\r
1052                         {\r
1053                                 if( pattrib->RxPWDBAll > ptdlsinfo->ss_record.RxPWDBAll )\r
1054                                 {\r
1055                                         _rtw_memcpy(txmgmt.peer, ptdlsinfo->ss_record.macaddr, ETH_ALEN);\r
1056                                         //issue_tdls_teardown(padapter, ptdlsinfo->ss_record.macaddr, _FALSE);\r
1057                                 }\r
1058                                 else\r
1059                                 {\r
1060                                         ret = _FAIL;\r
1061                                         goto exit;\r
1062                                 }\r
1063                         }\r
1064                 }\r
1065 \r
1066                 padapter->HalFunc.GetHalDefVarHandler(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);\r
1067 \r
1068                 if( pattrib->RxPWDBAll + TDLS_SIGNAL_THRESH >= UndecoratedSmoothedPWDB);\r
1069                 {\r
1070                         DBG_871X("pattrib->RxPWDBAll=%d, pdmpriv->UndecoratedSmoothedPWDB=%d\n", pattrib->RxPWDBAll, UndecoratedSmoothedPWDB);\r
1071                         _rtw_memcpy(txmgmt.peer, psa, ETH_ALEN);\r
1072                         issue_tdls_setup_req(padapter, &txmgmt, _FALSE);\r
1073                 }\r
1074         }\r
1075 #endif //CONFIG_TDLS_AUTOSETUP\r
1076 \r
1077 exit:\r
1078         return ret;\r
1079 \r
1080 }\r
1081 \r
1082 sint On_TDLS_Setup_Req(_adapter *padapter, union recv_frame *precv_frame)\r
1083 {\r
1084         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;\r
1085         u8 *psa, *pmyid;\r
1086         struct sta_info *ptdls_sta= NULL;\r
1087         struct sta_priv *pstapriv = &padapter->stapriv;\r
1088         u8 *ptr = precv_frame->u.hdr.rx_data;\r
1089         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
1090         struct security_priv *psecuritypriv = &padapter->securitypriv;\r
1091         _irqL irqL;\r
1092         struct rx_pkt_attrib    *prx_pkt_attrib = &precv_frame->u.hdr.attrib;\r
1093         u8 *prsnie, *ppairwise_cipher;\r
1094         u8 i, k;\r
1095         u8 ccmp_included=0, rsnie_included=0;\r
1096         u16 j, pairwise_count;\r
1097         u8 SNonce[32];\r
1098         u32 *timeout_interval=NULL;\r
1099         sint parsing_length;    //frame body length, without icv_len\r
1100         PNDIS_802_11_VARIABLE_IEs       pIE;\r
1101         u8 FIXED_IE = 5;\r
1102         unsigned char           supportRate[16];\r
1103         int                             supportRateNum = 0;\r
1104         struct tdls_txmgmt txmgmt;\r
1105 \r
1106         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
1107         psa = get_sa(ptr);\r
1108         ptdls_sta = rtw_get_stainfo(pstapriv, psa);\r
1109 \r
1110         pmyid=myid(&(padapter->eeprompriv));\r
1111         ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;\r
1112         parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len\r
1113                         -prx_pkt_attrib->hdrlen\r
1114                         -prx_pkt_attrib->iv_len\r
1115                         -prx_pkt_attrib->icv_len\r
1116                         -LLC_HEADER_SIZE\r
1117                         -ETH_TYPE_LEN\r
1118                         -PAYLOAD_TYPE_LEN\r
1119                         -FIXED_IE;\r
1120 \r
1121         if(ptdlsinfo->ap_prohibited == _TRUE)\r
1122         {\r
1123                 goto exit;\r
1124         }\r
1125 \r
1126         if(ptdls_sta==NULL){\r
1127                 ptdls_sta = rtw_alloc_stainfo(pstapriv, psa);\r
1128         }else{\r
1129                 if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE){\r
1130                         //If the direct link is already set up\r
1131                         //Process as re-setup after tear down\r
1132                         DBG_871X("re-setup a direct link\n");\r
1133                 }\r
1134                 //already receiving TDLS setup request\r
1135                 else if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){\r
1136                         DBG_871X("receive duplicated TDLS setup request frame in handshaking\n");\r
1137                         goto exit;\r
1138                 }\r
1139                 //When receiving and sending setup_req to the same link at the same time, STA with higher MAC_addr would be initiator\r
1140                 //following is to check out MAC_addr\r
1141                 else if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){\r
1142                         DBG_871X("receive setup_req after sending setup_req\n");\r
1143                         for (i=0;i<6;i++){\r
1144                                 if(*(pmyid+i)==*(psa+i)){\r
1145                                 }\r
1146                                 else if(*(pmyid+i)>*(psa+i)){\r
1147                                         ptdls_sta->tdls_sta_state=TDLS_INITIATOR_STATE;\r
1148                                         break;\r
1149                                 }else if(*(pmyid+i)<*(psa+i)){\r
1150                                         goto exit;\r
1151                                 }\r
1152                         }\r
1153                 }\r
1154         }\r
1155 \r
1156         if(ptdls_sta) \r
1157         {\r
1158                 ptdls_sta->dialog = *(ptr+2);   //copy dialog token\r
1159                 ptdls_sta->stat_code = 0;\r
1160 \r
1161                 //parsing information element\r
1162                 for(j=FIXED_IE; j<parsing_length;){\r
1163 \r
1164                         pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);\r
1165 \r
1166                         switch (pIE->ElementID)\r
1167                         {\r
1168                                 case _SUPPORTEDRATES_IE_:\r
1169                                         _rtw_memcpy(supportRate, pIE->data, pIE->Length);\r
1170                                         supportRateNum = pIE->Length;\r
1171                                         break;\r
1172                                 case _COUNTRY_IE_:\r
1173                                         break;\r
1174                                 case _EXT_SUPPORTEDRATES_IE_:\r
1175                                         if(supportRateNum<=sizeof(supportRate))\r
1176                                         {\r
1177                                                 _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);\r
1178                                                 supportRateNum += pIE->Length;\r
1179                                         }\r
1180                                         break;\r
1181                                 case _SUPPORTED_CH_IE_:\r
1182                                         break;\r
1183                                 case _RSN_IE_2_:\r
1184                                         rsnie_included=1;\r
1185                                         if(prx_pkt_attrib->encrypt){\r
1186                                                 prsnie=(u8*)pIE;\r
1187                                                 //check whether initiator STA has CCMP pairwise_cipher.\r
1188                                                 ppairwise_cipher=prsnie+10;\r
1189                                                 _rtw_memcpy(ptdls_sta->TDLS_RSNIE, pIE->data, pIE->Length);\r
1190                                                 pairwise_count = *(u16*)(ppairwise_cipher-2);\r
1191                                                 for(k=0;k<pairwise_count;k++){\r
1192                                                         if(_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE)\r
1193                                                                 ccmp_included=1;\r
1194                                                 }\r
1195                                                 if(ccmp_included==0){\r
1196                                                         //invalid contents of RSNIE\r
1197                                                         ptdls_sta->stat_code=72;\r
1198                                                 }\r
1199                                         }\r
1200                                         break;\r
1201                                 case _EXT_CAP_IE_:\r
1202                                         break;\r
1203                                 case _VENDOR_SPECIFIC_IE_:\r
1204                                         break;\r
1205                                 case _FTIE_:\r
1206                                         if(prx_pkt_attrib->encrypt)\r
1207                                                 _rtw_memcpy(SNonce, (ptr+j+52), 32);\r
1208                                         break;\r
1209                                 case _TIMEOUT_ITVL_IE_:\r
1210                                         if(prx_pkt_attrib->encrypt)\r
1211                                                 timeout_interval = (u32 *)(ptr+j+3);\r
1212                                         break;\r
1213                                 case _RIC_Descriptor_IE_:\r
1214                                         break;\r
1215                                 case _HT_CAPABILITY_IE_:\r
1216                                         rtw_tdls_process_ht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);\r
1217                                         break;\r
1218                                 case EID_BSSCoexistence:\r
1219                                         break;\r
1220                                 case _LINK_ID_IE_:\r
1221                                         if(_rtw_memcmp(get_bssid(pmlmepriv), pIE->data, 6) == _FALSE)\r
1222                                         {\r
1223                                                 //not in the same BSS\r
1224                                                 ptdls_sta->stat_code=7;\r
1225                                         }\r
1226                                         break;\r
1227                                 default:\r
1228                                         break;\r
1229                         }\r
1230 \r
1231                         j += (pIE->Length + 2);\r
1232                         \r
1233                 }\r
1234 \r
1235                 //check status code\r
1236                 //if responder STA has/hasn't security on AP, but request hasn't/has RSNIE, it should reject\r
1237                 if(ptdls_sta->stat_code == 0 )\r
1238                 {\r
1239                         if(rsnie_included && (prx_pkt_attrib->encrypt==0)){\r
1240                                 //security disabled\r
1241                                 ptdls_sta->stat_code = 5;\r
1242                         }else if(rsnie_included==0 && (prx_pkt_attrib->encrypt)){\r
1243                                 //request haven't RSNIE\r
1244                                 ptdls_sta->stat_code = 38;\r
1245                         }\r
1246 \r
1247 #ifdef CONFIG_WFD\r
1248                         //WFD test plan version 0.18.2 test item 5.1.5\r
1249                         //SoUT does not use TDLS if AP uses weak security\r
1250                         if ( padapter->wdinfo.wfd_tdls_enable )\r
1251                         {\r
1252                                 if(rsnie_included && (prx_pkt_attrib->encrypt != _AES_))\r
1253                                 {\r
1254                                         ptdls_sta->stat_code = 5;\r
1255                                 }\r
1256                         }\r
1257 #endif //CONFIG_WFD\r
1258                 }\r
1259 \r
1260                 ptdls_sta->tdls_sta_state|= TDLS_INITIATOR_STATE;\r
1261                 if(prx_pkt_attrib->encrypt){\r
1262                         _rtw_memcpy(ptdls_sta->SNonce, SNonce, 32);\r
1263                         _rtw_memcpy(&(ptdls_sta->TDLS_PeerKey_Lifetime), timeout_interval, 4);\r
1264                 }\r
1265 \r
1266                 //update station supportRate    \r
1267                 ptdls_sta->bssratelen = supportRateNum;\r
1268                 _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);\r
1269 \r
1270                 if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))\r
1271                         ptdlsinfo->sta_cnt++;\r
1272                 if( ptdlsinfo->sta_cnt == (NUM_STA - 2 - 4) )   // -2: AP + BC/MC sta, -4: default key\r
1273                 {\r
1274                         ptdlsinfo->sta_maximum = _TRUE;\r
1275                 }\r
1276 \r
1277 #ifdef CONFIG_WFD\r
1278                 rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length - FIXED_IE);\r
1279 #endif // CONFIG_WFD\r
1280 \r
1281         }\r
1282         else\r
1283         {\r
1284                 goto exit;\r
1285         }\r
1286 \r
1287         _rtw_memcpy(txmgmt.peer, prx_pkt_attrib->src, ETH_ALEN);\r
1288         issue_tdls_setup_rsp(padapter, &txmgmt);\r
1289 \r
1290         if(ptdls_sta->stat_code==0)\r
1291         {\r
1292                 _set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);\r
1293         }\r
1294         else            //status code!=0 ; setup unsuccess\r
1295         {\r
1296                 free_tdls_sta(padapter, ptdls_sta);\r
1297         }\r
1298                 \r
1299 exit:\r
1300         \r
1301         return _SUCCESS;\r
1302 }\r
1303 \r
1304 int On_TDLS_Setup_Rsp(_adapter *padapter, union recv_frame *precv_frame)\r
1305 {\r
1306         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;\r
1307         struct sta_info *ptdls_sta= NULL;\r
1308         struct sta_priv *pstapriv = &padapter->stapriv;\r
1309         u8 *ptr = precv_frame->u.hdr.rx_data;\r
1310         _irqL irqL;\r
1311         struct rx_pkt_attrib    *prx_pkt_attrib = &precv_frame->u.hdr.attrib;\r
1312         u8 *psa;\r
1313         u16 stat_code;\r
1314         sint parsing_length;    //frame body length, without icv_len\r
1315         PNDIS_802_11_VARIABLE_IEs       pIE;\r
1316         u8 FIXED_IE =7;\r
1317         u8 ANonce[32];\r
1318         u8  *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL, *ppairwise_cipher=NULL;\r
1319         u16 pairwise_count, j, k;\r
1320         u8 verify_ccmp=0;\r
1321         unsigned char           supportRate[16];\r
1322         int                             supportRateNum = 0;\r
1323         struct tdls_txmgmt txmgmt;\r
1324         int ret = _SUCCESS;\r
1325 \r
1326         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
1327         psa = get_sa(ptr);\r
1328         ptdls_sta = rtw_get_stainfo(pstapriv, psa);\r
1329 \r
1330         if ( NULL == ptdls_sta )\r
1331         {\r
1332                 ret = _FAIL;\r
1333                 goto exit;\r
1334         }\r
1335 \r
1336         ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;\r
1337         parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len\r
1338                         -prx_pkt_attrib->hdrlen\r
1339                         -prx_pkt_attrib->iv_len\r
1340                         -prx_pkt_attrib->icv_len\r
1341                         -LLC_HEADER_SIZE\r
1342                         -TYPE_LENGTH_FIELD_SIZE\r
1343                         -1\r
1344                         -FIXED_IE;\r
1345 \r
1346         _rtw_memcpy(&stat_code, ptr+2, 2);\r
1347         \r
1348         if(stat_code!=0)\r
1349         {\r
1350                 DBG_871X( "[%s] status_code = %d, free_tdls_sta\n", __FUNCTION__, stat_code );\r
1351                 free_tdls_sta(padapter, ptdls_sta);\r
1352                 ret = _FAIL;\r
1353                 goto exit;\r
1354         }\r
1355 \r
1356         stat_code = 0;\r
1357 \r
1358         //parsing information element\r
1359         for(j=FIXED_IE; j<parsing_length;)\r
1360         {\r
1361                 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);\r
1362 \r
1363                 switch (pIE->ElementID)\r
1364                 {\r
1365                         case _SUPPORTEDRATES_IE_:\r
1366                                 _rtw_memcpy(supportRate, pIE->data, pIE->Length);\r
1367                                 supportRateNum = pIE->Length;\r
1368                                 break;\r
1369                         case _COUNTRY_IE_:\r
1370                                 break;\r
1371                         case _EXT_SUPPORTEDRATES_IE_:\r
1372                                 if(supportRateNum<=sizeof(supportRate))\r
1373                                 {\r
1374                                         _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);\r
1375                                         supportRateNum += pIE->Length;\r
1376                                 }\r
1377                                 break;\r
1378                         case _SUPPORTED_CH_IE_:\r
1379                                 break;\r
1380                         case _RSN_IE_2_:\r
1381                                 prsnie=(u8*)pIE;\r
1382                                 //check whether responder STA has CCMP pairwise_cipher.\r
1383                                 ppairwise_cipher=prsnie+10;\r
1384                                 _rtw_memcpy(&pairwise_count, (u16*)(ppairwise_cipher-2), 2);\r
1385                                 for(k=0;k<pairwise_count;k++){\r
1386                                         if(_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE)\r
1387                                                 verify_ccmp=1;\r
1388                                 }\r
1389                         case _EXT_CAP_IE_:\r
1390                                 break;\r
1391                         case _VENDOR_SPECIFIC_IE_:\r
1392                                 break;\r
1393                         case _FTIE_:\r
1394                                 pftie=(u8*)pIE;\r
1395                                 //_rtw_memcpy(ptdls_sta->ANonce, (ptr+j+20), 32);\r
1396                                 _rtw_memcpy(ANonce, (ptr+j+20), 32);\r
1397                                 break;\r
1398                         case _TIMEOUT_ITVL_IE_:\r
1399                                 ptimeout_ie=(u8*)pIE;\r
1400                                 break;\r
1401                         case _RIC_Descriptor_IE_:\r
1402                                 break;\r
1403                         case _HT_CAPABILITY_IE_:\r
1404                                 rtw_tdls_process_ht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);\r
1405                                 break;\r
1406                         case EID_BSSCoexistence:\r
1407                                 break;\r
1408                         case _LINK_ID_IE_:\r
1409                                 plinkid_ie=(u8*)pIE;\r
1410                                 break;\r
1411                         default:\r
1412                                 break;\r
1413                 }\r
1414 \r
1415                 j += (pIE->Length + 2);\r
1416                 \r
1417         }\r
1418 \r
1419         //update station's supportRate  \r
1420         ptdls_sta->bssratelen = supportRateNum;\r
1421         _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);\r
1422 \r
1423         _rtw_memcpy(ptdls_sta->ANonce, ANonce, 32);\r
1424 \r
1425 #ifdef CONFIG_WFD\r
1426         rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length - FIXED_IE);\r
1427 #endif // CONFIG_WFD\r
1428 \r
1429         if(stat_code != 0)\r
1430         {\r
1431                 ptdls_sta->stat_code = stat_code;\r
1432         }\r
1433         else\r
1434         {\r
1435                 if(prx_pkt_attrib->encrypt)\r
1436                 {\r
1437                         if(verify_ccmp==1)\r
1438                         {\r
1439                                 wpa_tdls_generate_tpk(padapter, ptdls_sta);\r
1440                                 ptdls_sta->stat_code=0;\r
1441                                 if(tdls_verify_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie)==0)   //0: Invalid, 1: valid\r
1442                                 {\r
1443                                         free_tdls_sta(padapter, ptdls_sta);\r
1444                                         ret = _FAIL;\r
1445                                         goto exit;\r
1446                                 }\r
1447                         }\r
1448                         else\r
1449                         {\r
1450                                 ptdls_sta->stat_code=72;        //invalide contents of RSNIE\r
1451                         }\r
1452 \r
1453                 }else{\r
1454                         ptdls_sta->stat_code=0;\r
1455                 }\r
1456         }\r
1457 \r
1458         DBG_871X("issue_tdls_setup_cfm\n");\r
1459         _rtw_memcpy(txmgmt.peer, prx_pkt_attrib->src, ETH_ALEN);\r
1460         issue_tdls_setup_cfm(padapter, &txmgmt);\r
1461 \r
1462         if(ptdls_sta->stat_code==0)\r
1463         {\r
1464                 ptdlsinfo->link_established = _TRUE;\r
1465 \r
1466                 if( ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE )\r
1467                 {\r
1468                         ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;\r
1469                         _cancel_timer_ex( &ptdls_sta->handshake_timer);\r
1470                 }\r
1471 \r
1472                 rtw_tdls_set_key(padapter, prx_pkt_attrib, ptdls_sta);\r
1473 \r
1474                 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_ESTABLISHED);\r
1475 \r
1476         }\r
1477 \r
1478 exit:\r
1479         return ret;\r
1480 \r
1481 }\r
1482 \r
1483 int On_TDLS_Setup_Cfm(_adapter *padapter, union recv_frame *precv_frame)\r
1484 {\r
1485         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;\r
1486         struct sta_info *ptdls_sta= NULL;\r
1487         struct sta_priv *pstapriv = &padapter->stapriv;\r
1488         u8 *ptr = precv_frame->u.hdr.rx_data;\r
1489         _irqL irqL;\r
1490         struct rx_pkt_attrib    *prx_pkt_attrib = &precv_frame->u.hdr.attrib;\r
1491         u8 *psa; \r
1492         u16 stat_code;\r
1493         sint parsing_length;\r
1494         PNDIS_802_11_VARIABLE_IEs       pIE;\r
1495         u8 FIXED_IE =5;\r
1496         u8  *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL, *ppairwise_cipher=NULL;\r
1497         u16 j, pairwise_count;\r
1498         int ret = _SUCCESS;\r
1499 \r
1500         psa = get_sa(ptr);\r
1501         ptdls_sta = rtw_get_stainfo(pstapriv, psa);\r
1502 \r
1503         if(ptdls_sta == NULL)\r
1504         {\r
1505                 DBG_871X( "[%s] Direct Link Peer = "MAC_FMT" not found\n", __FUNCTION__, MAC_ARG(psa) );\r
1506                 ret = _FAIL;\r
1507                 goto exit;\r
1508         }\r
1509 \r
1510         ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;\r
1511         parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len\r
1512                         -prx_pkt_attrib->hdrlen\r
1513                         -prx_pkt_attrib->iv_len\r
1514                         -prx_pkt_attrib->icv_len\r
1515                         -LLC_HEADER_SIZE\r
1516                         -ETH_TYPE_LEN\r
1517                         -PAYLOAD_TYPE_LEN\r
1518                         -FIXED_IE;\r
1519         _rtw_memcpy(&stat_code, ptr+2, 2);\r
1520 \r
1521         if(stat_code!=0){\r
1522                 DBG_871X( "[%s] stat_code = %d\n, free_tdls_sta", __FUNCTION__, stat_code );\r
1523                 free_tdls_sta(padapter, ptdls_sta);\r
1524                 ret = _FAIL;\r
1525                 goto exit;\r
1526         }\r
1527 \r
1528         if(prx_pkt_attrib->encrypt){\r
1529                 //parsing information element\r
1530                 for(j=FIXED_IE; j<parsing_length;){\r
1531 \r
1532                         pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);\r
1533 \r
1534                         switch (pIE->ElementID)\r
1535                         {\r
1536                                 case _RSN_IE_2_:\r
1537                                         prsnie=(u8*)pIE;\r
1538                                         break;\r
1539                                 case _VENDOR_SPECIFIC_IE_:\r
1540                                         break;\r
1541                                 case _FTIE_:\r
1542                                         pftie=(u8*)pIE;\r
1543                                         break;\r
1544                                 case _TIMEOUT_ITVL_IE_:\r
1545                                         ptimeout_ie=(u8*)pIE;\r
1546                                         break;\r
1547                                 case _HT_EXTRA_INFO_IE_:\r
1548                                         break;\r
1549                                 case _LINK_ID_IE_:\r
1550                                         plinkid_ie=(u8*)pIE;\r
1551                                         break;\r
1552                                 default:\r
1553                                         break;\r
1554                         }\r
1555 \r
1556                         j += (pIE->Length + 2);\r
1557                         \r
1558                 }\r
1559 \r
1560                 //verify mic in FTIE MIC field\r
1561                 if(tdls_verify_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie)==0){  //0: Invalid, 1: Valid\r
1562                         free_tdls_sta(padapter, ptdls_sta);\r
1563                         ret = _FAIL;\r
1564                         goto exit;\r
1565                 }\r
1566 \r
1567         }\r
1568 \r
1569         ptdlsinfo->link_established = _TRUE;\r
1570         if( ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE )\r
1571         {\r
1572                 ptdls_sta->tdls_sta_state|=TDLS_LINKED_STATE;\r
1573                 _cancel_timer_ex( &ptdls_sta->handshake_timer);\r
1574         }\r
1575 \r
1576         rtw_tdls_set_key(padapter, prx_pkt_attrib, ptdls_sta);\r
1577 \r
1578         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_ESTABLISHED);\r
1579 \r
1580 exit:\r
1581         return ret;\r
1582 \r
1583 }\r
1584 \r
1585 int On_TDLS_Dis_Req(_adapter *padapter, union recv_frame *precv_frame)\r
1586 {\r
1587         struct rx_pkt_attrib    *prx_pkt_attrib = &precv_frame->u.hdr.attrib;\r
1588         struct sta_priv *pstapriv = &padapter->stapriv;\r
1589         struct sta_info *psta_ap;\r
1590         u8 *ptr = precv_frame->u.hdr.rx_data;\r
1591         sint parsing_length;    //frame body length, without icv_len\r
1592         PNDIS_802_11_VARIABLE_IEs       pIE;\r
1593         u8 FIXED_IE = 3, *dst;\r
1594         u16 j;\r
1595         struct tdls_txmgmt txmgmt;\r
1596         int ret = _SUCCESS;\r
1597 \r
1598         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
1599         ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE + 1;\r
1600         txmgmt.dialog_token = *(ptr+2);\r
1601         _rtw_memcpy(&txmgmt.peer, precv_frame->u.hdr.attrib.src, ETH_ALEN);\r
1602         txmgmt.action_code = TDLS_DISCOVERY_RESPONSE;\r
1603         parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len\r
1604                         -prx_pkt_attrib->hdrlen\r
1605                         -prx_pkt_attrib->iv_len\r
1606                         -prx_pkt_attrib->icv_len\r
1607                         -LLC_HEADER_SIZE\r
1608                         -TYPE_LENGTH_FIELD_SIZE\r
1609                         -1\r
1610                         -FIXED_IE;\r
1611 \r
1612         //parsing information element\r
1613         for(j=FIXED_IE; j<parsing_length;){\r
1614 \r
1615                 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);\r
1616 \r
1617                 switch (pIE->ElementID)\r
1618                 {\r
1619                         case _LINK_ID_IE_:\r
1620                                 psta_ap = rtw_get_stainfo(pstapriv, pIE->data);\r
1621                                 if(psta_ap == NULL)\r
1622                                 {\r
1623                                         goto exit;\r
1624                                 }\r
1625                                 dst = pIE->data + 12;\r
1626                                 if( (MacAddr_isBcst(dst) == _FALSE) && (_rtw_memcmp(myid(&(padapter->eeprompriv)), dst, 6) == _FALSE) )\r
1627                                 {\r
1628                                         goto exit;\r
1629                                 }\r
1630                                 break;\r
1631                         default:\r
1632                                 break;\r
1633                 }\r
1634 \r
1635                 j += (pIE->Length + 2);\r
1636                 \r
1637         }\r
1638 \r
1639         issue_tdls_dis_rsp(padapter, &txmgmt, prx_pkt_attrib->privacy);\r
1640 \r
1641 exit:\r
1642         return ret;\r
1643         \r
1644 }\r
1645 \r
1646 int On_TDLS_Teardown(_adapter *padapter, union recv_frame *precv_frame)\r
1647 {\r
1648         u8 *psa;\r
1649         u8 *ptr = precv_frame->u.hdr.rx_data;\r
1650         struct rx_pkt_attrib    *prx_pkt_attrib = &precv_frame->u.hdr.attrib;\r
1651         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);   \r
1652         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
1653         struct sta_priv         *pstapriv = &padapter->stapriv;\r
1654         struct sta_info *ptdls_sta= NULL;\r
1655         _irqL irqL;\r
1656 \r
1657         psa = get_sa(ptr);\r
1658 \r
1659         ptdls_sta = rtw_get_stainfo(pstapriv, psa);\r
1660         if(ptdls_sta!=NULL){\r
1661                 if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE){\r
1662                         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CS_OFF);\r
1663                 }\r
1664                 free_tdls_sta(padapter, ptdls_sta);\r
1665         }\r
1666                 \r
1667         return _SUCCESS;\r
1668         \r
1669 }\r
1670 \r
1671 u8 TDLS_check_ch_state(uint state){\r
1672         if(     (state & TDLS_CH_SWITCH_ON_STATE) &&\r
1673                 (state & TDLS_AT_OFF_CH_STATE) &&\r
1674                 (state & TDLS_PEER_AT_OFF_STATE) ){\r
1675 \r
1676                 if(state & TDLS_PEER_SLEEP_STATE)\r
1677                         return 2;       //U-APSD + ch. switch\r
1678                 else\r
1679                         return 1;       //ch. switch\r
1680         }else\r
1681                 return 0;\r
1682 }\r
1683 \r
1684 int On_TDLS_Peer_Traffic_Indication(_adapter *padapter, union recv_frame *precv_frame)\r
1685 {\r
1686         struct rx_pkt_attrib    *pattrib = &precv_frame->u.hdr.attrib;\r
1687         struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->src); \r
1688         u8 *ptr = precv_frame->u.hdr.rx_data;\r
1689 \r
1690         ptr +=pattrib->hdrlen + pattrib->iv_len + LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE + 1;\r
1691 \r
1692         if(ptdls_sta != NULL)\r
1693         {\r
1694                 ptdls_sta->dialog = *(ptr+2);\r
1695                 issue_tdls_peer_traffic_rsp(padapter, ptdls_sta);\r
1696 \r
1697                 //issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 0, 0);\r
1698         }\r
1699         else\r
1700         {\r
1701                 DBG_871X("from unknown sta:"MAC_FMT"\n", MAC_ARG(pattrib->src));\r
1702                 return _FAIL;\r
1703         }\r
1704 \r
1705         return _SUCCESS;\r
1706 }\r
1707 \r
1708 //we process buffered data for 1. U-APSD, 2. ch. switch, 3. U-APSD + ch. switch here\r
1709 int On_TDLS_Peer_Traffic_Rsp(_adapter *padapter, union recv_frame *precv_frame)\r
1710 {\r
1711         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;\r
1712         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
1713         struct rx_pkt_attrib    *pattrib = & precv_frame->u.hdr.attrib;\r
1714         struct sta_priv *pstapriv = &padapter->stapriv;\r
1715         //get peer sta infomation\r
1716         struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->src);\r
1717         u8 wmmps_ac=0, state=TDLS_check_ch_state(ptdls_sta->tdls_sta_state);\r
1718         int i;\r
1719         \r
1720         ptdls_sta->sta_stats.rx_data_pkts++;\r
1721 \r
1722         ptdls_sta->tdls_sta_state &= ~(TDLS_WAIT_PTR_STATE);\r
1723 \r
1724         //receive peer traffic response frame, sleeping STA wakes up\r
1725         //ptdls_sta->tdls_sta_state &= ~(TDLS_PEER_SLEEP_STATE);\r
1726         //process_wmmps_data( padapter, precv_frame);\r
1727 \r
1728         // if noticed peer STA wakes up by receiving peer traffic response\r
1729         // and we want to do channel swtiching, then we will transmit channel switch request first\r
1730         if(ptdls_sta->tdls_sta_state & TDLS_APSD_CHSW_STATE){\r
1731                 issue_tdls_ch_switch_req(padapter, pattrib->src);\r
1732                 ptdls_sta->tdls_sta_state &= ~(TDLS_APSD_CHSW_STATE);\r
1733                 return  _SUCCESS;\r
1734         }\r
1735 \r
1736         //check 4-AC queue bit\r
1737         if(ptdls_sta->uapsd_vo || ptdls_sta->uapsd_vi || ptdls_sta->uapsd_be || ptdls_sta->uapsd_bk)\r
1738                 wmmps_ac=1;\r
1739 \r
1740         //if it's a direct link and have buffered frame\r
1741         if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE){\r
1742                 //[TDLS] UAPSD\r
1743                 //if(wmmps_ac && state)\r
1744                 if(wmmps_ac && 1)\r
1745                 {\r
1746                         _irqL irqL;      \r
1747                         _list   *xmitframe_plist, *xmitframe_phead;\r
1748                         struct xmit_frame *pxmitframe=NULL;\r
1749                 \r
1750                         _enter_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);    \r
1751 \r
1752                         xmitframe_phead = get_list_head(&ptdls_sta->sleep_q);\r
1753                         xmitframe_plist = get_next(xmitframe_phead);\r
1754 \r
1755                         //transmit buffered frames\r
1756                         while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)\r
1757                         {                       \r
1758                                 pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);\r
1759                                 xmitframe_plist = get_next(xmitframe_plist);\r
1760                                 rtw_list_delete(&pxmitframe->list);\r
1761 \r
1762                                 ptdls_sta->sleepq_len--;\r
1763                                 ptdls_sta->sleepq_ac_len--;\r
1764                                 if(ptdls_sta->sleepq_len>0){\r
1765                                         pxmitframe->attrib.mdata = 1;\r
1766                                         pxmitframe->attrib.eosp = 0;\r
1767                                 }else{\r
1768                                         pxmitframe->attrib.mdata = 0;\r
1769                                         pxmitframe->attrib.eosp = 1;\r
1770                                 }\r
1771                                 pxmitframe->attrib.triggered = 1;\r
1772 \r
1773                                 rtw_hal_xmitframe_enqueue(padapter, pxmitframe);\r
1774 \r
1775 \r
1776                         }\r
1777 \r
1778                         if(ptdls_sta->sleepq_len==0)\r
1779                         {\r
1780                                 DBG_871X("no buffered packets for tdls to xmit\n");\r
1781                                 //on U-APSD + CH. switch state, when there is no buffered date to xmit,\r
1782                                 // we should go back to base channel\r
1783                                 if(state==2){\r
1784                                         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CS_OFF);\r
1785                                 }else if(ptdls_sta->tdls_sta_state&TDLS_SW_OFF_STATE){\r
1786                                                 ptdls_sta->tdls_sta_state &= ~(TDLS_SW_OFF_STATE);\r
1787                                                 ptdlsinfo->candidate_ch= pmlmeext->cur_channel;\r
1788                                                 issue_tdls_ch_switch_req(padapter, pattrib->src);\r
1789                                                 DBG_871X("issue tdls ch switch req back to base channel\n");\r
1790                                 }\r
1791                                 \r
1792                         }\r
1793                         else\r
1794                         {\r
1795                                 DBG_871X("error!psta->sleepq_len=%d\n", ptdls_sta->sleepq_len);\r
1796                                 ptdls_sta->sleepq_len=0;                                                \r
1797                         }\r
1798 \r
1799                         _exit_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);                     \r
1800                 \r
1801                 }\r
1802 \r
1803         }\r
1804 \r
1805         return _SUCCESS;\r
1806 }\r
1807 \r
1808 sint On_TDLS_Ch_Switch_Req(_adapter *padapter, union recv_frame *precv_frame)\r
1809 {\r
1810         struct sta_info *ptdls_sta= NULL;\r
1811         struct sta_priv *pstapriv = &padapter->stapriv;\r
1812         u8 *ptr = precv_frame->u.hdr.rx_data;\r
1813         struct rx_pkt_attrib    *prx_pkt_attrib = &precv_frame->u.hdr.attrib;\r
1814         u8 *psa; \r
1815         sint parsing_length;\r
1816         PNDIS_802_11_VARIABLE_IEs       pIE;\r
1817         u8 FIXED_IE =3;\r
1818         u16 j;\r
1819         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
1820 \r
1821         psa = get_sa(ptr);\r
1822         ptdls_sta = rtw_get_stainfo(pstapriv, psa);\r
1823         \r
1824         ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;\r
1825         parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len\r
1826                         -prx_pkt_attrib->hdrlen\r
1827                         -prx_pkt_attrib->iv_len\r
1828                         -prx_pkt_attrib->icv_len\r
1829                         -LLC_HEADER_SIZE\r
1830                         -ETH_TYPE_LEN\r
1831                         -PAYLOAD_TYPE_LEN\r
1832                         -FIXED_IE;\r
1833 \r
1834         ptdls_sta->off_ch = *(ptr+2);\r
1835         \r
1836         //parsing information element\r
1837         for(j=FIXED_IE; j<parsing_length;){\r
1838 \r
1839                 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);\r
1840 \r
1841                 switch (pIE->ElementID)\r
1842                 {\r
1843                         case _COUNTRY_IE_:\r
1844                                 break;\r
1845                         case _CH_SWTICH_ANNOUNCE_:\r
1846                                 break;\r
1847                         case _LINK_ID_IE_:\r
1848                                 break;\r
1849                         case _CH_SWITCH_TIMING_:\r
1850                                 _rtw_memcpy(&ptdls_sta->ch_switch_time, pIE->data, 2);\r
1851                                 _rtw_memcpy(&ptdls_sta->ch_switch_timeout, pIE->data+2, 2);\r
1852                         default:\r
1853                                 break;\r
1854                 }\r
1855 \r
1856                 j += (pIE->Length + 2);\r
1857                 \r
1858         }\r
1859 \r
1860         //todo: check status\r
1861         ptdls_sta->stat_code=0;\r
1862         ptdls_sta->tdls_sta_state |= TDLS_CH_SWITCH_ON_STATE;\r
1863 \r
1864         issue_nulldata(padapter, NULL, 1, 0, 0);\r
1865 \r
1866         issue_tdls_ch_switch_rsp(padapter, psa);\r
1867 \r
1868         DBG_871X("issue tdls channel switch response\n");\r
1869 \r
1870         if((ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE) && ptdls_sta->off_ch==pmlmeext->cur_channel){\r
1871                 DBG_871X("back to base channel %x\n", pmlmeext->cur_channel);\r
1872                 ptdls_sta->option=TDLS_BASE_CH;\r
1873                 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_BASE_CH);\r
1874         }else{          \r
1875                 ptdls_sta->option=TDLS_OFF_CH;\r
1876                 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_OFF_CH);\r
1877         }\r
1878         return _SUCCESS;\r
1879 }\r
1880 \r
1881 sint On_TDLS_Ch_Switch_Rsp(_adapter *padapter, union recv_frame *precv_frame)\r
1882 {\r
1883         struct sta_info *ptdls_sta= NULL;\r
1884         struct sta_priv *pstapriv = &padapter->stapriv;\r
1885         u8 *ptr = precv_frame->u.hdr.rx_data;\r
1886         struct rx_pkt_attrib    *prx_pkt_attrib = &precv_frame->u.hdr.attrib;\r
1887         u8 *psa; \r
1888         sint parsing_length;\r
1889         PNDIS_802_11_VARIABLE_IEs       pIE;\r
1890         u8 FIXED_IE =4;\r
1891         u16 stat_code, j, switch_time, switch_timeout;\r
1892         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
1893         int ret = _SUCCESS;\r
1894 \r
1895         psa = get_sa(ptr);\r
1896         ptdls_sta = rtw_get_stainfo(pstapriv, psa);\r
1897 \r
1898         //if channel switch is running and receiving Unsolicited TDLS Channel Switch Response,\r
1899         //it will go back to base channel and terminate this channel switch procedure\r
1900         if(ptdls_sta->tdls_sta_state & TDLS_CH_SWITCH_ON_STATE ){\r
1901                 if(pmlmeext->cur_channel==ptdls_sta->off_ch){\r
1902                         DBG_871X("back to base channel %x\n", pmlmeext->cur_channel);\r
1903                         ptdls_sta->option=TDLS_BASE_CH;\r
1904                         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_BASE_CH);\r
1905                 }else{\r
1906                         DBG_871X("receive unsolicited channel switch response \n");\r
1907                         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CS_OFF);\r
1908                 }\r
1909                 ret = _FAIL;\r
1910                 goto exit;\r
1911         }\r
1912 \r
1913         //avoiding duplicated or unconditional ch. switch. rsp\r
1914         if(!(ptdls_sta->tdls_sta_state & TDLS_CH_SW_INITIATOR_STATE))\r
1915         {\r
1916                 ret = _FAIL;\r
1917                 goto exit;\r
1918         }\r
1919 \r
1920         ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+TYPE_LENGTH_FIELD_SIZE+1;\r
1921         parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len\r
1922                         -prx_pkt_attrib->hdrlen\r
1923                         -prx_pkt_attrib->iv_len\r
1924                         -prx_pkt_attrib->icv_len\r
1925                         -LLC_HEADER_SIZE\r
1926                         -ETH_TYPE_LEN\r
1927                         -PAYLOAD_TYPE_LEN\r
1928                         -FIXED_IE;\r
1929 \r
1930         _rtw_memcpy(&stat_code, ptr+2, 2);\r
1931 \r
1932         if(stat_code!=0){\r
1933                 ret = _FAIL;\r
1934                 goto exit;\r
1935         }\r
1936         \r
1937         //parsing information element\r
1938         for(j=FIXED_IE; j<parsing_length;){\r
1939 \r
1940                 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);\r
1941 \r
1942                 switch (pIE->ElementID)\r
1943                 {\r
1944                         case _LINK_ID_IE_:\r
1945                                 break;\r
1946                         case _CH_SWITCH_TIMING_:\r
1947                                 _rtw_memcpy(&switch_time, pIE->data, 2);\r
1948                                 if(switch_time > ptdls_sta->ch_switch_time)\r
1949                                         _rtw_memcpy(&ptdls_sta->ch_switch_time, &switch_time, 2);\r
1950 \r
1951                                 _rtw_memcpy(&switch_timeout, pIE->data+2, 2);\r
1952                                 if(switch_timeout > ptdls_sta->ch_switch_timeout)\r
1953                                         _rtw_memcpy(&ptdls_sta->ch_switch_timeout, &switch_timeout, 2);\r
1954 \r
1955                         default:\r
1956                                 break;\r
1957                 }\r
1958 \r
1959                 j += (pIE->Length + 2);\r
1960                 \r
1961         }\r
1962 \r
1963         ptdls_sta->tdls_sta_state &= ~(TDLS_CH_SW_INITIATOR_STATE);\r
1964         ptdls_sta->tdls_sta_state |=TDLS_CH_SWITCH_ON_STATE;\r
1965 \r
1966         //goto set_channel_workitem_callback()\r
1967         ptdls_sta->option=TDLS_OFF_CH;\r
1968         rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_OFF_CH);\r
1969 \r
1970 exit:\r
1971         return ret;\r
1972 }\r
1973 \r
1974 #ifdef CONFIG_WFD\r
1975 void wfd_ie_tdls(_adapter * padapter, u8 *pframe, u32 *pktlen )\r
1976 {\r
1977         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;\r
1978         struct wifi_display_info        *pwfd_info = padapter->tdlsinfo.wfd_info;\r
1979         u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };\r
1980         u32 wfdielen = 0;\r
1981 \r
1982         //      WFD OUI\r
1983         wfdielen = 0;\r
1984         wfdie[ wfdielen++ ] = 0x50;\r
1985         wfdie[ wfdielen++ ] = 0x6F;\r
1986         wfdie[ wfdielen++ ] = 0x9A;\r
1987         wfdie[ wfdielen++ ] = 0x0A;     //      WFA WFD v1.0\r
1988 \r
1989         //      Commented by Albert 20110825\r
1990         //      According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes\r
1991         //      1. WFD Device Information\r
1992         //      2. Associated BSSID ( Optional )\r
1993         //      3. Local IP Adress ( Optional )\r
1994 \r
1995         //      WFD Device Information ATTR\r
1996         //      Type:\r
1997         wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;\r
1998 \r
1999         //      Length:\r
2000         //      Note: In the WFD specification, the size of length field is 2.\r
2001         RTW_PUT_BE16(wfdie + wfdielen, 0x0006);\r
2002         wfdielen += 2;\r
2003 \r
2004         //      Value1:\r
2005         //      WFD device information\r
2006         //      available for WFD session + Preferred TDLS + WSD ( WFD Service Discovery )\r
2007         RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL \r
2008                                                                 | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_WSD);\r
2009         wfdielen += 2;\r
2010 \r
2011         //      Value2:\r
2012         //      Session Management Control Port\r
2013         //      Default TCP port for RTSP messages is 554\r
2014         RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );\r
2015         wfdielen += 2;\r
2016 \r
2017         //      Value3:\r
2018         //      WFD Device Maximum Throughput\r
2019         //      300Mbps is the maximum throughput\r
2020         RTW_PUT_BE16(wfdie + wfdielen, 300);\r
2021         wfdielen += 2;\r
2022 \r
2023         //      Associated BSSID ATTR\r
2024         //      Type:\r
2025         wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;\r
2026 \r
2027         //      Length:\r
2028         //      Note: In the WFD specification, the size of length field is 2.\r
2029         RTW_PUT_BE16(wfdie + wfdielen, 0x0006);\r
2030         wfdielen += 2;\r
2031 \r
2032         //      Value:\r
2033         //      Associated BSSID\r
2034         if ( check_fwstate( pmlmepriv, _FW_LINKED) == _TRUE )\r
2035         {\r
2036                 _rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );\r
2037         }\r
2038         else\r
2039         {\r
2040                 _rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );\r
2041         }\r
2042 \r
2043         //      Local IP Address ATTR\r
2044         wfdie[ wfdielen++ ] = WFD_ATTR_LOCAL_IP_ADDR;\r
2045 \r
2046         //      Length:\r
2047         //      Note: In the WFD specification, the size of length field is 2.\r
2048         RTW_PUT_BE16(wfdie + wfdielen, 0x0005);\r
2049         wfdielen += 2;\r
2050 \r
2051         //      Version:\r
2052         //      0x01: Version1;IPv4\r
2053         wfdie[ wfdielen++ ] = 0x01;     \r
2054 \r
2055         //      IPv4 Address\r
2056         _rtw_memcpy( wfdie + wfdielen, pwfd_info->ip_address, 4 );\r
2057         wfdielen += 4;\r
2058         \r
2059         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, pktlen);\r
2060         \r
2061 }\r
2062 #endif //CONFIG_WFD\r
2063 \r
2064 void rtw_build_tdls_setup_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)\r
2065 {\r
2066         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;\r
2067         struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;\r
2068         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2069         struct registry_priv    *pregistrypriv = &padapter->registrypriv;\r
2070         struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);\r
2071 \r
2072         u8 payload_type = 0x02;\r
2073         u8 category = RTW_WLAN_CATEGORY_TDLS;\r
2074         u8 action = TDLS_SETUP_REQUEST;\r
2075         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
2076         int     bssrate_len = 0, i = 0 ;\r
2077         u8 more_supportedrates = 0;\r
2078         unsigned int ie_len;\r
2079         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;\r
2080         u8 link_id_addr[18] = {0};\r
2081         u8 iedata=0;\r
2082         u8 sup_ch[ 30 * 2 ] = {0x00 }, sup_ch_idx = 0, idx_5g = 2;      //For supported channel\r
2083         u8 timeout_itvl[5];     //set timeout interval to maximum value\r
2084         u32 time;\r
2085         u8 *pframe_head;\r
2086 \r
2087         //SNonce        \r
2088         if(pattrib->encrypt){\r
2089                 for(i=0;i<8;i++){\r
2090                         time=rtw_get_current_time();\r
2091                         _rtw_memcpy(&ptdls_sta->SNonce[4*i], (u8 *)&time, 4);\r
2092                 }\r
2093         }\r
2094 \r
2095         pframe_head = pframe;   // For rtw_tdls_set_ht_cap()\r
2096 \r
2097         //payload type\r
2098         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));\r
2099         //category, action, dialog token\r
2100         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2101         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
2102         pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));\r
2103 \r
2104         //capability\r
2105         _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);\r
2106 \r
2107         if(pattrib->encrypt)\r
2108                 *pframe =*pframe | cap_Privacy;\r
2109         pframe += 2;\r
2110         pattrib->pktlen += 2;\r
2111 \r
2112         //supported rates\r
2113         if(pmlmeext->cur_channel < 14 )\r
2114         {\r
2115                 rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N);\r
2116                 bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN;\r
2117         }\r
2118         else\r
2119         {\r
2120                 rtw_set_supported_rate(bssrate, WIRELESS_11A_5N);\r
2121                 bssrate_len = IEEE80211_NUM_OFDM_RATESLEN;\r
2122         }\r
2123 \r
2124         //country(optional)\r
2125 \r
2126         if (bssrate_len > 8)\r
2127         {\r
2128                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));\r
2129                 more_supportedrates = 1;\r
2130         }\r
2131         else\r
2132         {\r
2133                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));\r
2134         }\r
2135 \r
2136         //extended supported rates\r
2137         if(more_supportedrates==1){\r
2138                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));\r
2139         }\r
2140 \r
2141         //supported channels\r
2142         pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);\r
2143         \r
2144         //      SRC IE\r
2145         pframe = rtw_set_ie( pframe, _SRC_IE_, sizeof(TDLS_SRC), TDLS_SRC, &(pattrib->pktlen));\r
2146         \r
2147         //RSNIE\r
2148         if(pattrib->encrypt)\r
2149                 pframe = rtw_set_ie(pframe, _RSN_IE_2_, sizeof(TDLS_RSNIE), TDLS_RSNIE, &(pattrib->pktlen));\r
2150         \r
2151         //extended capabilities\r
2152         pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , sizeof(TDLS_EXT_CAPIE), TDLS_EXT_CAPIE, &(pattrib->pktlen));\r
2153 \r
2154         //QoS capability(WMM_IE)\r
2155         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(TDLS_WMMIE), TDLS_WMMIE,  &(pattrib->pktlen));\r
2156 \r
2157 \r
2158         if(pattrib->encrypt){\r
2159                 //FTIE\r
2160                 _rtw_memset(pframe, 0, 84);     //All fields except SNonce shall be set to 0\r
2161                 _rtw_memset(pframe, _FTIE_, 1); //version\r
2162                 _rtw_memset((pframe+1), 82, 1); //length\r
2163                 _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32);\r
2164                 pframe += 84;\r
2165                 pattrib->pktlen += 84;\r
2166 \r
2167                 //Timeout interval\r
2168                 timeout_itvl[0]=0x02;\r
2169                 _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);\r
2170                 pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl,  &(pattrib->pktlen));\r
2171         }\r
2172 \r
2173         //Sup_reg_classes(optional)\r
2174         //HT capabilities\r
2175         pframe += rtw_tdls_set_ht_cap(padapter, pframe_head, pattrib);\r
2176 \r
2177         //20/40 BSS coexistence\r
2178         if(pmlmepriv->num_FortyMHzIntolerant>0)\r
2179                 iedata |= BIT(2);//20 MHz BSS Width Request\r
2180         pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));\r
2181         \r
2182         //Link identifier\r
2183         _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2184         _rtw_memcpy((link_id_addr+6), pattrib->src, 6);\r
2185         _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);\r
2186         pframe = rtw_set_ie(pframe, _LINK_ID_IE_,  18, link_id_addr, &(pattrib->pktlen));\r
2187 \r
2188 #ifdef CONFIG_WFD\r
2189         wfd_ie_tdls( padapter, pframe, &(pattrib->pktlen) );\r
2190 #endif //CONFIG_WFD\r
2191 \r
2192 }\r
2193 \r
2194 void rtw_build_tdls_setup_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)\r
2195 {\r
2196         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2197         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2198         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2199         struct sta_info *ptdls_sta;\r
2200         struct registry_priv    *pregistrypriv = &padapter->registrypriv;\r
2201 \r
2202         u8 payload_type = 0x02; \r
2203         unsigned char category = RTW_WLAN_CATEGORY_TDLS;\r
2204         unsigned char action = TDLS_SETUP_RESPONSE;\r
2205         unsigned char   bssrate[NDIS_802_11_LENGTH_RATES_EX];   \r
2206         int     bssrate_len = 0;\r
2207         u8 more_supportedrates = 0;\r
2208         unsigned int ie_len;\r
2209         unsigned char *p;\r
2210         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;\r
2211         u8 link_id_addr[18] = {0};\r
2212         u8 iedata=0;\r
2213         u8 timeout_itvl[5];     //setup response timeout interval will copy from request\r
2214         u8 ANonce[32];  //maybe it can put in ontdls_req\r
2215         u8 k;           //for random ANonce\r
2216         u8  *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL;\r
2217         u32 time;\r
2218         u8 *pframe_head;\r
2219 \r
2220         ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);\r
2221 \r
2222         if(ptdls_sta == NULL )\r
2223         {\r
2224                 DBG_871X("[%s] %d\n", __FUNCTION__, __LINE__);\r
2225                 return;\r
2226         }\r
2227 \r
2228         if(pattrib->encrypt){\r
2229                 for(k=0;k<8;k++){\r
2230                         time=rtw_get_current_time();\r
2231                         _rtw_memcpy(&ptdls_sta->ANonce[4*k], (u8*)&time, 4);\r
2232                 }\r
2233         }\r
2234 \r
2235         pframe_head = pframe;\r
2236 \r
2237         //payload type\r
2238         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));      \r
2239         //category, action, status code\r
2240         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2241         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
2242         pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));\r
2243 \r
2244         if(ptdls_sta->stat_code!=0)     //invalid setup request\r
2245         {\r
2246                 DBG_871X("ptdls_sta->stat_code:%04x \n", ptdls_sta->stat_code);         \r
2247                 return;\r
2248         }\r
2249         \r
2250         //dialog token\r
2251         pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));\r
2252 \r
2253         //capability\r
2254         _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);\r
2255 \r
2256         if(pattrib->encrypt )\r
2257                 *pframe =*pframe | cap_Privacy;\r
2258         pframe += 2;\r
2259         pattrib->pktlen += 2;\r
2260 \r
2261         //supported rates\r
2262         //supported rates\r
2263         if(pmlmeext->cur_channel < 14 )\r
2264         {\r
2265                 rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N);\r
2266                 bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN;\r
2267         }\r
2268         else\r
2269         {\r
2270                 rtw_set_supported_rate(bssrate, WIRELESS_11A_5N);\r
2271                 bssrate_len = IEEE80211_NUM_OFDM_RATESLEN;\r
2272         }\r
2273 \r
2274         if (bssrate_len > 8)\r
2275         {\r
2276                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));\r
2277                 more_supportedrates = 1;\r
2278         }\r
2279         else\r
2280         {\r
2281                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));\r
2282         }\r
2283 \r
2284         //country(optional)\r
2285         //extended supported rates\r
2286         if(more_supportedrates==1){\r
2287                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));\r
2288         }\r
2289 \r
2290         //supported channels\r
2291         pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);\r
2292         \r
2293         // SRC IE\r
2294         pframe = rtw_set_ie(pframe, _SRC_IE_ , sizeof(TDLS_SRC), TDLS_SRC, &(pattrib->pktlen));\r
2295 \r
2296         //RSNIE\r
2297         if(pattrib->encrypt){\r
2298                 prsnie = pframe;\r
2299                 pframe = rtw_set_ie(pframe, _RSN_IE_2_, sizeof(ptdls_sta->TDLS_RSNIE), ptdls_sta->TDLS_RSNIE, &(pattrib->pktlen));\r
2300         }\r
2301 \r
2302         //extended capabilities\r
2303         pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , sizeof(TDLS_EXT_CAPIE), TDLS_EXT_CAPIE, &(pattrib->pktlen));\r
2304 \r
2305         //QoS capability(WMM_IE)\r
2306         pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(TDLS_WMMIE), TDLS_WMMIE,  &(pattrib->pktlen));\r
2307 \r
2308         if(pattrib->encrypt){\r
2309                 wpa_tdls_generate_tpk(padapter, ptdls_sta);\r
2310 \r
2311                 //FTIE\r
2312                 pftie = pframe;\r
2313                 pftie_mic = pframe+4;\r
2314                 _rtw_memset(pframe, 0, 84);     //All fields except SNonce shall be set to 0\r
2315                 _rtw_memset(pframe, _FTIE_, 1); //version\r
2316                 _rtw_memset((pframe+1), 82, 1); //length\r
2317                 _rtw_memcpy((pframe+20), ptdls_sta->ANonce, 32);\r
2318                 _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32);\r
2319                 pframe += 84;\r
2320                 pattrib->pktlen += 84;\r
2321 \r
2322                 //Timeout interval\r
2323                 ptimeout_ie = pframe;\r
2324                 timeout_itvl[0]=0x02;\r
2325                 _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);\r
2326                 pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl,  &(pattrib->pktlen));\r
2327         }\r
2328 \r
2329         //Sup_reg_classes(optional)\r
2330         //HT capabilities\r
2331         pframe += rtw_tdls_set_ht_cap(padapter, pframe_head, pattrib);\r
2332 \r
2333         //20/40 BSS coexistence\r
2334         if(pmlmepriv->num_FortyMHzIntolerant>0)\r
2335                 iedata |= BIT(2);//20 MHz BSS Width Request\r
2336         pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));\r
2337 \r
2338         //Link identifier\r
2339         plinkid_ie = pframe;\r
2340         _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2341         _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);\r
2342         _rtw_memcpy((link_id_addr+12), pattrib->src, 6);\r
2343         pframe = rtw_set_ie(pframe, _LINK_ID_IE_,  18, link_id_addr, &(pattrib->pktlen));\r
2344 \r
2345         //fill FTIE mic\r
2346         if(pattrib->encrypt)\r
2347                 wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);\r
2348 \r
2349 #ifdef CONFIG_WFD\r
2350         wfd_ie_tdls( padapter, pframe, &(pattrib->pktlen) );\r
2351 #endif //CONFIG_WFD\r
2352 \r
2353 }\r
2354 \r
2355 void rtw_build_tdls_setup_cfm_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)\r
2356 {\r
2357 \r
2358         struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);\r
2359         struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);\r
2360         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2361         struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);\r
2362 \r
2363         u8 payload_type = 0x02; \r
2364         unsigned char category = RTW_WLAN_CATEGORY_TDLS;\r
2365         unsigned char action = TDLS_SETUP_CONFIRM;\r
2366         u8 more_supportedrates = 0;\r
2367         unsigned int ie_len;\r
2368         unsigned char *p;\r
2369         u8 timeout_itvl[5];     //set timeout interval to maximum value\r
2370         u8 wmm_param_ele[24] = {0};\r
2371         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;\r
2372         u8      link_id_addr[18] = {0};\r
2373         u8  *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL;\r
2374 \r
2375         //payload type\r
2376         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));\r
2377         //category, action, status code, dialog token\r
2378         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2379         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
2380         pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));\r
2381         pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));\r
2382 \r
2383         if(ptdls_sta->stat_code!=0)     //invalid setup request\r
2384                 return;\r
2385         \r
2386         //RSNIE\r
2387         if(pattrib->encrypt){\r
2388                 prsnie = pframe;\r
2389                 pframe = rtw_set_ie(pframe, _RSN_IE_2_, sizeof(TDLS_RSNIE), TDLS_RSNIE, &(pattrib->pktlen));\r
2390         }\r
2391         \r
2392         //EDCA param set; WMM param ele.\r
2393         if(pattrib->encrypt){\r
2394                 //FTIE\r
2395                 pftie = pframe;\r
2396                 pftie_mic = pframe+4;\r
2397                 _rtw_memset(pframe, 0, 84);     //All fields except SNonce shall be set to 0\r
2398                 _rtw_memset(pframe, _FTIE_, 1); //version\r
2399                 _rtw_memset((pframe+1), 82, 1); //length\r
2400                 _rtw_memcpy((pframe+20), ptdls_sta->ANonce, 32);\r
2401                 _rtw_memcpy((pframe+52), ptdls_sta->SNonce, 32);\r
2402                 pframe += 84;\r
2403                 pattrib->pktlen += 84;\r
2404 \r
2405                 //Timeout interval\r
2406                 ptimeout_ie = pframe;\r
2407                 timeout_itvl[0]=0x02;\r
2408                 _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);\r
2409                 ptdls_sta->TPK_count=0;\r
2410                 _set_timer(&ptdls_sta->TPK_timer, ptdls_sta->TDLS_PeerKey_Lifetime/TPK_RESEND_COUNT);\r
2411                 pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl,  &(pattrib->pktlen));\r
2412         }\r
2413 \r
2414         //HT operation; todo\r
2415         //Link identifier\r
2416         plinkid_ie = pframe;\r
2417         _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2418         _rtw_memcpy((link_id_addr+6), pattrib->src, 6);\r
2419         _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);\r
2420         pframe = rtw_set_ie(pframe, _LINK_ID_IE_,  18, link_id_addr, &(pattrib->pktlen));\r
2421 \r
2422         //FTIE mic\r
2423         if(pattrib->encrypt)\r
2424                 wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);\r
2425 \r
2426         //WMM Parameter Set\r
2427         if(&pmlmeinfo->WMM_param)\r
2428         {\r
2429                 _rtw_memcpy(wmm_param_ele, WMM_PARA_OUI, 6);\r
2430                 _rtw_memcpy(wmm_param_ele+6, (u8 *)&pmlmeinfo->WMM_param, sizeof(pmlmeinfo->WMM_param));\r
2431                 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_,  24, wmm_param_ele, &(pattrib->pktlen));              \r
2432         }\r
2433 \r
2434 }\r
2435 \r
2436 void rtw_build_tdls_teardown_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)\r
2437 {\r
2438 \r
2439         struct pkt_attrib *pattrib = &pxmitframe->attrib;\r
2440         u8 payload_type = 0x02;\r
2441         unsigned char category = RTW_WLAN_CATEGORY_TDLS;\r
2442         u8 action = ptxmgmt->action_code;\r
2443         u8 link_id_addr[18] = {0};\r
2444         struct sta_info *ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);\r
2445 \r
2446         //payload type\r
2447         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));      \r
2448         //category, action, reason code\r
2449         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2450         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
2451         pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptxmgmt->status_code, &(pattrib->pktlen));\r
2452 \r
2453         //Link identifier\r
2454         if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){   \r
2455                 _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2456                 _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);\r
2457                 _rtw_memcpy((link_id_addr+12), pattrib->src, 6);\r
2458         }else  if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){\r
2459                 _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2460                 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);\r
2461                 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);\r
2462         }\r
2463         pframe = rtw_set_ie(pframe, _LINK_ID_IE_,  18, link_id_addr, &(pattrib->pktlen));\r
2464         \r
2465 }\r
2466 \r
2467 void rtw_build_tdls_dis_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)\r
2468 {\r
2469 \r
2470         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2471         u8 payload_type = 0x02;\r
2472         u8 category = RTW_WLAN_CATEGORY_TDLS;\r
2473         u8 action = TDLS_DISCOVERY_REQUEST;\r
2474         u8      link_id_addr[18] = {0};\r
2475         static u8 dialogtoken=0;\r
2476 \r
2477         //payload type\r
2478         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));              \r
2479         //category, action, reason code\r
2480         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2481         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
2482         if(ptxmgmt->external_support == _TRUE) {\r
2483                 pframe = rtw_set_fixed_ie(pframe, 1, &(ptxmgmt->dialog_token), &(pattrib->pktlen));\r
2484         } else {\r
2485                 pframe = rtw_set_fixed_ie(pframe, 1, &(dialogtoken), &(pattrib->pktlen));\r
2486                 dialogtoken = (dialogtoken+1)%256;\r
2487         }\r
2488 \r
2489         //Link identifier\r
2490         _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2491         _rtw_memcpy((link_id_addr+6), pattrib->src, 6);\r
2492         _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);\r
2493         pframe = rtw_set_ie(pframe, _LINK_ID_IE_,  18, link_id_addr, &(pattrib->pktlen));\r
2494         \r
2495 }\r
2496 \r
2497 void rtw_build_tdls_dis_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, u8 dialog, u8 privacy)\r
2498 {\r
2499         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;\r
2500         struct mlme_ext_info    *pmlmeinfo = &pmlmeext->mlmext_info;\r
2501         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2502         struct registry_priv    *pregistrypriv = &padapter->registrypriv;\r
2503 \r
2504         u8 category = RTW_WLAN_CATEGORY_PUBLIC;\r
2505         u8 action = TDLS_DISCOVERY_RESPONSE;\r
2506         u8 bssrate[NDIS_802_11_LENGTH_RATES_EX];\r
2507         int bssrate_len = 0;\r
2508         u8 more_supportedrates = 0;\r
2509         u8 *p;\r
2510         struct mlme_priv                *pmlmepriv = &padapter->mlmepriv;\r
2511         u8 link_id_addr[18] = {0};\r
2512         u8 iedata=0;\r
2513         u8 timeout_itvl[5];     //set timeout interval to maximum value\r
2514         u32 timeout_interval= TPK_RESEND_COUNT * 1000;\r
2515         u8 *pframe_head, pktlen_index;\r
2516 \r
2517         pktlen_index = pattrib->pktlen; // For mgmt frame, pattrib->pktlen would count frame header\r
2518         pframe_head = pframe;\r
2519 \r
2520         //category, action, dialog token\r
2521         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2522         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
2523         pframe = rtw_set_fixed_ie(pframe, 1, &(dialog), &(pattrib->pktlen));\r
2524 \r
2525         //capability\r
2526         _rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);\r
2527 \r
2528         if(privacy)\r
2529                 *pframe =*pframe | cap_Privacy;\r
2530         pframe += 2;\r
2531         pattrib->pktlen += 2;\r
2532 \r
2533         //supported rates\r
2534         rtw_set_supported_rate(bssrate, WIRELESS_11BG_24N);\r
2535         bssrate_len = IEEE80211_CCK_RATE_LEN + IEEE80211_NUM_OFDM_RATESLEN;\r
2536 \r
2537         if (bssrate_len > 8)\r
2538         {\r
2539                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));\r
2540                 more_supportedrates = 1;\r
2541         }\r
2542         else\r
2543         {\r
2544                 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));\r
2545         }\r
2546 \r
2547         //extended supported rates\r
2548         if(more_supportedrates==1){\r
2549                 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));\r
2550         }\r
2551 \r
2552         //supported channels\r
2553         pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);\r
2554 \r
2555         //RSNIE\r
2556         if(privacy)\r
2557                 pframe = rtw_set_ie(pframe, _RSN_IE_2_, sizeof(TDLS_RSNIE), TDLS_RSNIE, &(pattrib->pktlen));\r
2558 \r
2559         //extended capability\r
2560         pframe = rtw_set_ie(pframe, _EXT_CAP_IE_ , sizeof(TDLS_EXT_CAPIE), TDLS_EXT_CAPIE, &(pattrib->pktlen));\r
2561 \r
2562         if(privacy){\r
2563                 //FTIE\r
2564                 _rtw_memset(pframe, 0, 84);     //All fields shall be set to 0\r
2565                 _rtw_memset(pframe, _FTIE_, 1); //version\r
2566                 _rtw_memset((pframe+1), 82, 1); //length\r
2567                 pframe += 84;\r
2568                 pattrib->pktlen += 84;\r
2569 \r
2570                 //Timeout interval\r
2571                 timeout_itvl[0]=0x02;\r
2572                 _rtw_memcpy(timeout_itvl+1, &timeout_interval, 4);\r
2573                 pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl,  &(pattrib->pktlen));\r
2574         }\r
2575 \r
2576         //Sup_reg_classes(optional)\r
2577         //HT capabilities\r
2578         pframe += rtw_tdls_set_ht_cap(padapter, pframe_head - pktlen_index, pattrib);\r
2579 \r
2580         //20/40 BSS coexistence\r
2581         if(pmlmepriv->num_FortyMHzIntolerant>0)\r
2582                 iedata |= BIT(2);//20 MHz BSS Width Request\r
2583         pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));\r
2584 \r
2585         //Link identifier\r
2586         _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2587         _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);\r
2588         _rtw_memcpy((link_id_addr+12), pattrib->src, 6);\r
2589         pframe = rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));\r
2590 \r
2591 }\r
2592 \r
2593 void rtw_build_tdls_peer_traffic_indication_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)\r
2594 {\r
2595 \r
2596         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2597         u8 payload_type = 0x02;\r
2598         unsigned char category = RTW_WLAN_CATEGORY_TDLS;\r
2599         unsigned char action = TDLS_PEER_TRAFFIC_INDICATION;\r
2600 \r
2601         u8      link_id_addr[18] = {0};\r
2602         u8 AC_queue=0;\r
2603         struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);\r
2604 \r
2605         //payload type\r
2606         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));      \r
2607         //category, action, reason code\r
2608         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2609         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
2610         pframe = rtw_set_fixed_ie(pframe, 1, &(ptdls_sta->dialog), &(pattrib->pktlen));\r
2611 \r
2612         //Link identifier\r
2613         if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){   \r
2614                 _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2615                 _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);\r
2616                 _rtw_memcpy((link_id_addr+12), pattrib->src, 6);\r
2617         }else  if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){\r
2618                 _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2619                 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);\r
2620                 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);\r
2621         }\r
2622         pframe = rtw_set_ie(pframe, _LINK_ID_IE_,  18, link_id_addr, &(pattrib->pktlen));\r
2623 \r
2624         //PTI control\r
2625         //PU buffer status\r
2626         if(ptdls_sta->uapsd_bk&BIT(1))\r
2627                 AC_queue=BIT(0);\r
2628         if(ptdls_sta->uapsd_be&BIT(1))\r
2629                 AC_queue=BIT(1);\r
2630         if(ptdls_sta->uapsd_vi&BIT(1))\r
2631                 AC_queue=BIT(2);\r
2632         if(ptdls_sta->uapsd_vo&BIT(1))\r
2633                 AC_queue=BIT(3);\r
2634         pframe = rtw_set_ie(pframe, _PTI_BUFFER_STATUS_, 1, &AC_queue, &(pattrib->pktlen));\r
2635         \r
2636 }\r
2637 \r
2638 void rtw_build_tdls_peer_traffic_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)\r
2639 {\r
2640 \r
2641         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2642         u8 payload_type = 0x02;\r
2643         u8 category = RTW_WLAN_CATEGORY_TDLS;\r
2644         u8 action = TDLS_PEER_TRAFFIC_RESPONSE;\r
2645         u8      link_id_addr[18] = {0};\r
2646         struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);\r
2647         static u8 dialogtoken=0;\r
2648 \r
2649         //payload type\r
2650         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));              \r
2651         //category, action, reason code\r
2652         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2653         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
2654         pframe = rtw_set_fixed_ie(pframe, 1, &ptdls_sta->dialog, &(pattrib->pktlen));\r
2655 \r
2656         //Link identifier\r
2657         if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){   \r
2658                 _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2659                 _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);\r
2660                 _rtw_memcpy((link_id_addr+12), pattrib->src, 6);\r
2661         }else  if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){\r
2662                 _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2663                 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);\r
2664                 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);\r
2665         }\r
2666         pframe = rtw_set_ie(pframe, _LINK_ID_IE_,  18, link_id_addr, &(pattrib->pktlen));\r
2667 \r
2668 }\r
2669 \r
2670 void rtw_build_tdls_ch_switch_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)\r
2671 {\r
2672 \r
2673         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2674         struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;\r
2675         u8 payload_type = 0x02;\r
2676         unsigned char category = RTW_WLAN_CATEGORY_TDLS;\r
2677         unsigned char action = TDLS_CHANNEL_SWITCH_REQUEST;\r
2678         u8      link_id_addr[18] = {0};\r
2679         struct sta_priv         *pstapriv = &padapter->stapriv; \r
2680         struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);\r
2681         u8 ch_switch_timing[4] = {0};\r
2682         u16 switch_time= CH_SWITCH_TIME, switch_timeout=CH_SWITCH_TIMEOUT;      \r
2683 \r
2684         //payload type\r
2685         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));      \r
2686         //category, action, target_ch\r
2687         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2688         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
2689         pframe = rtw_set_fixed_ie(pframe, 1, &(ptdlsinfo->candidate_ch), &(pattrib->pktlen));\r
2690 \r
2691         //Link identifier\r
2692         if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){   \r
2693                 _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2694                 _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);\r
2695                 _rtw_memcpy((link_id_addr+12), pattrib->src, 6);\r
2696         }else  if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){\r
2697                 _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2698                 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);\r
2699                 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);\r
2700         }\r
2701         pframe = rtw_set_ie(pframe, _LINK_ID_IE_,  18, link_id_addr, &(pattrib->pktlen));\r
2702 \r
2703         //ch switch timing\r
2704         _rtw_memcpy(ch_switch_timing, &switch_time, 2);\r
2705         _rtw_memcpy(ch_switch_timing+2, &switch_timeout, 2);\r
2706         pframe = rtw_set_ie(pframe, _CH_SWITCH_TIMING_,  4, ch_switch_timing, &(pattrib->pktlen));\r
2707 \r
2708         //update ch switch attrib to sta_info\r
2709         ptdls_sta->off_ch=ptdlsinfo->candidate_ch;\r
2710         ptdls_sta->ch_switch_time=switch_time;\r
2711         ptdls_sta->ch_switch_timeout=switch_timeout;\r
2712 \r
2713 }\r
2714 \r
2715 void rtw_build_tdls_ch_switch_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)\r
2716 {\r
2717 \r
2718         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2719         u8 payload_type = 0x02;\r
2720         unsigned char category = RTW_WLAN_CATEGORY_TDLS;\r
2721         unsigned char action = TDLS_CHANNEL_SWITCH_RESPONSE;\r
2722         u8      link_id_addr[18] = {0};\r
2723         struct sta_priv         *pstapriv = &padapter->stapriv; \r
2724         struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);\r
2725         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;\r
2726         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;\r
2727         u8 ch_switch_timing[4] = {0};\r
2728 \r
2729         //payload type\r
2730         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));      \r
2731         //category, action, status_code\r
2732         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2733         pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));\r
2734         pframe = rtw_set_fixed_ie(pframe, 2, (u8 *)&ptdls_sta->stat_code, &(pattrib->pktlen));\r
2735 \r
2736         //Link identifier\r
2737         if(ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE){   \r
2738                 _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2739                 _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);\r
2740                 _rtw_memcpy((link_id_addr+12), pattrib->src, 6);\r
2741         }else  if(ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE){\r
2742                 _rtw_memcpy(link_id_addr, pattrib->ra, 6);\r
2743                 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);\r
2744                 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);\r
2745         }\r
2746         pframe = rtw_set_ie(pframe, _LINK_ID_IE_,  18, link_id_addr, &(pattrib->pktlen));\r
2747 \r
2748         //ch switch timing\r
2749         _rtw_memcpy(ch_switch_timing, &ptdls_sta->ch_switch_time, 2);\r
2750         _rtw_memcpy(ch_switch_timing+2, &ptdls_sta->ch_switch_timeout, 2);\r
2751         pframe = rtw_set_ie(pframe, _CH_SWITCH_TIMING_,  4, ch_switch_timing, &(pattrib->pktlen));\r
2752 \r
2753 }\r
2754 \r
2755 #ifdef CONFIG_WFD\r
2756 void rtw_build_tunneled_probe_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)\r
2757 {\r
2758 \r
2759         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2760         struct wifidirect_info *pwdinfo = &padapter->wdinfo;\r
2761         struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;\r
2762         u8 payload_type = 0x02;\r
2763         u8 category = RTW_WLAN_CATEGORY_P2P;\r
2764         u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};\r
2765         u8 probe_req = 4;\r
2766         u8 wfdielen = 0;\r
2767 \r
2768         //payload type\r
2769         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));              \r
2770         //category, OUI, frame_body_type\r
2771         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2772         pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));\r
2773         pframe = rtw_set_fixed_ie(pframe, 1, &(probe_req), &(pattrib->pktlen));\r
2774 \r
2775         if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))\r
2776         {\r
2777                 wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);\r
2778                 pframe += wfdielen;\r
2779                 pattrib->pktlen += wfdielen;\r
2780         }\r
2781         else if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))\r
2782         {\r
2783                 wfdielen = build_probe_req_wfd_ie(pbuddy_wdinfo, pframe);\r
2784                 pframe += wfdielen;\r
2785                 pattrib->pktlen += wfdielen;\r
2786         }\r
2787         \r
2788 }\r
2789 \r
2790 void rtw_build_tunneled_probe_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)\r
2791 {\r
2792 \r
2793         struct pkt_attrib       *pattrib = &pxmitframe->attrib;\r
2794         struct wifidirect_info *pwdinfo = &padapter->wdinfo;\r
2795         struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;\r
2796         u8 payload_type = 0x02;\r
2797         u8 category = RTW_WLAN_CATEGORY_P2P;\r
2798         u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};\r
2799         u8 probe_rsp = 5;\r
2800         u8 wfdielen = 0;\r
2801 \r
2802         //payload type\r
2803         pframe = rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));              \r
2804         //category, OUI, frame_body_type\r
2805         pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));\r
2806         pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));\r
2807         pframe = rtw_set_fixed_ie(pframe, 1, &(probe_rsp), &(pattrib->pktlen));\r
2808 \r
2809         if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))\r
2810         {\r
2811                 wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 1);\r
2812                 pframe += wfdielen;\r
2813                 pattrib->pktlen += wfdielen;\r
2814         }\r
2815         else if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))\r
2816         {\r
2817                 wfdielen = build_probe_resp_wfd_ie(pbuddy_wdinfo, pframe, 1);\r
2818                 pframe += wfdielen;\r
2819                 pattrib->pktlen += wfdielen;\r
2820         }\r
2821 \r
2822 }\r
2823 #endif //CONFIG_WFD\r
2824 \r
2825 void _tdls_tpk_timer_hdl(void *FunctionContext)\r
2826 {\r
2827         struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;\r
2828         struct tdls_txmgmt txmgmt;\r
2829 \r
2830         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
2831         ptdls_sta->TPK_count++;\r
2832         //TPK_timer set 1000 as default\r
2833         //retry timer should set at least 301 sec.\r
2834         if(ptdls_sta->TPK_count==TPK_RESEND_COUNT){\r
2835                 ptdls_sta->TPK_count=0;\r
2836                 _rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);\r
2837                 issue_tdls_setup_req(ptdls_sta->padapter, &txmgmt, _FALSE);\r
2838         }\r
2839         \r
2840         _set_timer(&ptdls_sta->TPK_timer, ptdls_sta->TDLS_PeerKey_Lifetime/TPK_RESEND_COUNT);\r
2841 }\r
2842 \r
2843 // TDLS_DONE_CH_SEN: channel sensing and report candidate channel\r
2844 // TDLS_OFF_CH: first time set channel to off channel\r
2845 // TDLS_BASE_CH: when go back to the channel linked with AP, send null data to peer STA as an indication\r
2846 void _tdls_ch_switch_timer_hdl(void *FunctionContext)\r
2847 {\r
2848 \r
2849         struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;\r
2850         _adapter *padapter = ptdls_sta->padapter;\r
2851         \r
2852         if( ptdls_sta->option == TDLS_DONE_CH_SEN ){\r
2853                 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_DONE_CH_SEN);\r
2854         }else if( ptdls_sta->option == TDLS_OFF_CH ){\r
2855                 issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta->hwaddr, 0, 0, 0);\r
2856                 _set_timer(&ptdls_sta->base_ch_timer, 500);\r
2857         }else if( ptdls_sta->option == TDLS_BASE_CH){\r
2858                 issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta->hwaddr, 0, 0, 0);\r
2859         }\r
2860 }\r
2861 \r
2862 void _tdls_base_ch_timer_hdl(void *FunctionContext)\r
2863 {\r
2864         struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;\r
2865         rtw_tdls_cmd(ptdls_sta->padapter, ptdls_sta->hwaddr, TDLS_P_OFF_CH);\r
2866 }\r
2867 \r
2868 void _tdls_off_ch_timer_hdl(void *FunctionContext)\r
2869 {\r
2870         struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;\r
2871         rtw_tdls_cmd(ptdls_sta->padapter, ptdls_sta->hwaddr, TDLS_P_BASE_CH );\r
2872 }\r
2873 \r
2874 void _tdls_handshake_timer_hdl(void *FunctionContext)\r
2875 {\r
2876         struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;\r
2877 \r
2878         if(ptdls_sta != NULL)\r
2879         {\r
2880                 if( !(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) )\r
2881                 {\r
2882                         DBG_871X("tdls handshake time out\n");\r
2883                         rtw_tdls_cmd(ptdls_sta->padapter, ptdls_sta->hwaddr, TDLS_TEAR_STA );\r
2884                 }\r
2885         }\r
2886 }\r
2887 \r
2888 void _tdls_pti_timer_hdl(void *FunctionContext)\r
2889 {\r
2890         struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;\r
2891         _adapter *padapter = ptdls_sta->padapter;\r
2892         struct tdls_txmgmt txmgmt;\r
2893 \r
2894         _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));\r
2895         _rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);\r
2896         txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_;\r
2897 \r
2898         if(ptdls_sta != NULL)\r
2899         {\r
2900                 if( ptdls_sta->tdls_sta_state & TDLS_WAIT_PTR_STATE )\r
2901                 {\r
2902                         DBG_871X("Doesn't receive PTR from peer dev:"MAC_FMT"; Send TDLS Tear Down\n", MAC_ARG(ptdls_sta->hwaddr));\r
2903                         issue_tdls_teardown(padapter, &txmgmt, _FALSE);\r
2904                 }\r
2905         }\r
2906 }\r
2907 \r
2908 void rtw_init_tdls_timer(_adapter *padapter, struct sta_info *psta)\r
2909 {\r
2910         psta->padapter=padapter;\r
2911         _init_timer(&psta->TPK_timer, padapter->pnetdev, _tdls_tpk_timer_hdl, psta);\r
2912         _init_timer(&psta->option_timer, padapter->pnetdev, _tdls_ch_switch_timer_hdl, psta);\r
2913         _init_timer(&psta->base_ch_timer, padapter->pnetdev, _tdls_base_ch_timer_hdl, psta);\r
2914         _init_timer(&psta->off_ch_timer, padapter->pnetdev, _tdls_off_ch_timer_hdl, psta);\r
2915         _init_timer(&psta->handshake_timer, padapter->pnetdev, _tdls_handshake_timer_hdl, psta);\r
2916         _init_timer(&psta->pti_timer, padapter->pnetdev, _tdls_pti_timer_hdl, psta);\r
2917 }\r
2918 \r
2919 void rtw_free_tdls_timer(struct sta_info *psta)\r
2920 {\r
2921         _cancel_timer_ex(&psta->TPK_timer);\r
2922         _cancel_timer_ex(&psta->option_timer);\r
2923         _cancel_timer_ex(&psta->base_ch_timer);\r
2924         _cancel_timer_ex(&psta->off_ch_timer);\r
2925         _cancel_timer_ex(&psta->handshake_timer);\r
2926         _cancel_timer_ex(&psta->pti_timer);\r
2927 }\r
2928 \r
2929 u8      update_sgi_tdls(_adapter *padapter, struct sta_info *psta)\r
2930 {\r
2931         return query_ra_short_GI(psta);\r
2932 }\r
2933 \r
2934 u32 update_mask_tdls(_adapter *padapter, struct sta_info *psta)\r
2935 {\r
2936         unsigned char sta_band = 0;\r
2937         unsigned int tx_ra_bitmap=0;\r
2938         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);\r
2939         WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;\r
2940 \r
2941         rtw_hal_update_sta_rate_mask(padapter, psta);\r
2942         tx_ra_bitmap = psta->ra_mask;\r
2943 \r
2944         if ( pcur_network->Configuration.DSConfig > 14 ) {\r
2945                 // 5G band\r
2946                 if (tx_ra_bitmap & 0xffff000)\r
2947                         sta_band |= WIRELESS_11_5N | WIRELESS_11A;\r
2948                 else\r
2949                         sta_band |= WIRELESS_11A;\r
2950         } else {\r
2951                 if (tx_ra_bitmap & 0xffff000)\r
2952                         sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;\r
2953                 else if (tx_ra_bitmap & 0xff0)\r
2954                         sta_band |= WIRELESS_11G |WIRELESS_11B;\r
2955                 else\r
2956                         sta_band |= WIRELESS_11B;\r
2957         }\r
2958 \r
2959         psta->wireless_mode = sta_band;\r
2960 \r
2961         psta->raid = rtw_hal_networktype_to_raid(padapter,psta);\r
2962         tx_ra_bitmap |= ((psta->raid<<28)&0xf0000000);\r
2963         return tx_ra_bitmap;\r
2964 }\r
2965 \r
2966 #endif //CONFIG_TDLS\r
2967 \r