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