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