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