1 /******************************************************************************
\r
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
\r
5 * This program is free software; you can redistribute it and/or modify it
\r
6 * under the terms of version 2 of the GNU General Public License as
\r
7 * published by the Free Software Foundation.
\r
9 * This program is distributed in the hope that it will be useful, but WITHOUT
\r
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
\r
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
14 * You should have received a copy of the GNU General Public License along with
\r
15 * this program; if not, write to the Free Software Foundation, Inc.,
\r
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
\r
19 ******************************************************************************/
\r
20 #define _RTW_TDLS_C_
\r
22 #include <drv_types.h>
\r
25 #define ONE_SEC 1000 /* 1000 ms */
\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
31 void rtw_reset_tdls_info(_adapter* padapter)
\r
33 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
35 ptdlsinfo->ap_prohibited = _FALSE;
\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
40 ptdlsinfo->ch_switch_prohibited = _FALSE;
\r
44 ptdlsinfo->ch_switch_prohibited = _TRUE;
\r
47 ptdlsinfo->link_established = _FALSE;
\r
48 ptdlsinfo->sta_cnt = 0;
\r
49 ptdlsinfo->sta_maximum = _FALSE;
\r
51 #ifdef CONFIG_TDLS_CH_SW
\r
52 ptdlsinfo->chsw_info.ch_sw_state = TDLS_STATE_NONE;
\r
53 ATOMIC_SET(&ptdlsinfo->chsw_info.chsw_on, _FALSE);
\r
54 ptdlsinfo->chsw_info.off_ch_num = 0;
\r
55 ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
\r
56 ptdlsinfo->chsw_info.cur_time = 0;
\r
57 ptdlsinfo->chsw_info.delay_switch_back = _FALSE;
\r
58 ptdlsinfo->chsw_info.dump_stack = _FALSE;
\r
61 ptdlsinfo->ch_sensing = 0;
\r
62 ptdlsinfo->watchdog_count = 0;
\r
63 ptdlsinfo->dev_discovered = _FALSE;
\r
66 ptdlsinfo->wfd_info = &padapter->wfd_info;
\r
70 int rtw_init_tdls_info(_adapter* padapter)
\r
73 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
75 rtw_reset_tdls_info(padapter);
\r
77 ptdlsinfo->tdls_enable = _TRUE;
\r
78 #ifdef CONFIG_TDLS_DRIVER_SETUP
\r
79 ptdlsinfo->driver_setup = _TRUE;
\r
81 ptdlsinfo->driver_setup = _FALSE;
\r
82 #endif /* CONFIG_TDLS_DRIVER_SETUP */
\r
84 _rtw_spinlock_init(&ptdlsinfo->cmd_lock);
\r
85 _rtw_spinlock_init(&ptdlsinfo->hdl_lock);
\r
91 void rtw_free_tdls_info(struct tdls_info *ptdlsinfo)
\r
93 _rtw_spinlock_free(&ptdlsinfo->cmd_lock);
\r
94 _rtw_spinlock_free(&ptdlsinfo->hdl_lock);
\r
96 _rtw_memset(ptdlsinfo, 0, sizeof(struct tdls_info) );
\r
100 int check_ap_tdls_prohibited(u8 *pframe, u8 pkt_len)
\r
102 u8 tdls_prohibited_bit = 0x40; /* bit(38); TDLS_prohibited */
\r
109 if ((*pframe) & tdls_prohibited_bit)
\r
115 int check_ap_tdls_ch_switching_prohibited(u8 *pframe, u8 pkt_len)
\r
117 u8 tdls_ch_swithcing_prohibited_bit = 0x80; /* bit(39); TDLS_channel_switching prohibited */
\r
124 if ((*pframe) & tdls_ch_swithcing_prohibited_bit)
\r
130 u8 rtw_tdls_is_setup_allowed(_adapter *padapter)
\r
132 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
134 if (ptdlsinfo->ap_prohibited == _TRUE)
\r
140 #ifdef CONFIG_TDLS_CH_SW
\r
141 u8 rtw_tdls_is_chsw_allowed(_adapter *padapter)
\r
143 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
145 if (ptdlsinfo->ch_switch_prohibited == _TRUE)
\r
148 if (padapter->registrypriv.wifi_spec == 0)
\r
155 int _issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
\r
158 struct xmit_frame *pmgntframe;
\r
159 struct pkt_attrib *pattrib;
\r
160 unsigned char *pframe;
\r
161 struct rtw_ieee80211_hdr *pwlanhdr;
\r
162 unsigned short *fctrl, *qc;
\r
163 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
164 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
165 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
167 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
170 pattrib = &pmgntframe->attrib;
\r
171 update_mgntframe_attrib(padapter, pattrib);
\r
173 pattrib->hdrlen +=2;
\r
174 pattrib->qos_en = _TRUE;
\r
176 pattrib->ack_policy = 0;
\r
177 pattrib->mdata = 0;
\r
178 pattrib->retry_ctrl = _FALSE;
\r
180 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
\r
182 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
\r
183 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
\r
185 fctrl = &(pwlanhdr->frame_ctl);
\r
191 qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
\r
193 SetPriority(qc, 7); /* Set priority to VO */
\r
195 SetEOSP(qc, pattrib->eosp);
\r
197 SetAckpolicy(qc, pattrib->ack_policy);
\r
199 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
\r
200 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
\r
201 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
\r
203 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
\r
204 pmlmeext->mgnt_seq++;
\r
205 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
\r
207 pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
\r
208 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
\r
210 pattrib->last_txcmdsz = pattrib->pktlen;
\r
213 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
\r
215 dump_mgntframe(padapter, pmgntframe);
\r
225 *wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
226 *wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
227 *try_cnt means the maximal TX count to try
229 int issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
\r
233 u32 start = rtw_get_current_time();
\r
234 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
235 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
238 psta = rtw_get_stainfo(&padapter->stapriv, da);
\r
241 rtw_hal_macid_sleep(padapter, psta->mac_id);
\r
243 rtw_hal_macid_wakeup(padapter, psta->mac_id);
\r
245 DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",
\r
246 FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup");
\r
252 ret = _issue_nulldata_to_TDLS_peer_STA(padapter, da, power_mode, wait_ms>0 ? _TRUE : _FALSE);
\r
256 if (RTW_CANNOT_RUN(padapter))
\r
259 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
\r
260 rtw_msleep_os(wait_ms);
\r
262 } while ((i < try_cnt) && (ret==_FAIL || wait_ms==0));
\r
264 if (ret != _FAIL) {
\r
266 #ifndef DBG_XMIT_ACK
\r
271 if (try_cnt && wait_ms) {
\r
273 DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
\r
274 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
\r
275 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
\r
277 DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
\r
278 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
\r
279 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
\r
285 void free_tdls_sta(_adapter *padapter, struct sta_info *ptdls_sta)
\r
287 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
288 struct sta_priv *pstapriv = &padapter->stapriv;
\r
291 /* free peer sta_info */
\r
292 _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
293 if (ptdlsinfo->sta_cnt != 0)
\r
294 ptdlsinfo->sta_cnt--;
\r
295 _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
296 /* -2: AP + BC/MC sta, -4: default key */
\r
297 if (ptdlsinfo->sta_cnt < MAX_ALLOWED_TDLS_STA_NUM) {
\r
298 ptdlsinfo->sta_maximum = _FALSE;
\r
299 _rtw_memset( &ptdlsinfo->ss_record, 0x00, sizeof(struct tdls_ss_record) );
\r
303 rtw_clearstakey_cmd(padapter, ptdls_sta, _TRUE);
\r
305 if (ptdlsinfo->sta_cnt == 0) {
\r
306 rtw_tdls_cmd(padapter, NULL, TDLS_RS_RCR);
\r
307 ptdlsinfo->link_established = _FALSE;
\r
310 DBG_871X("Remain tdls sta:%02x\n", ptdlsinfo->sta_cnt);
\r
312 rtw_free_stainfo(padapter, ptdls_sta);
\r
317 /* TDLS encryption(if needed) will always be CCMP */
\r
318 void rtw_tdls_set_key(_adapter *padapter, struct sta_info *ptdls_sta)
\r
320 ptdls_sta->dot118021XPrivacy=_AES_;
\r
321 rtw_setstakey_cmd(padapter, ptdls_sta, TDLS_KEY, _TRUE);
\r
324 #ifdef CONFIG_80211N_HT
\r
325 void rtw_tdls_process_ht_cap(_adapter *padapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)
\r
327 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
328 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
329 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
330 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
\r
331 u8 max_AMPDU_len, min_MPDU_spacing;
\r
332 u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, cur_beamform_cap = 0;
\r
334 /* Save HT capabilities in the sta object */
\r
335 _rtw_memset(&ptdls_sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
\r
336 if (data && Length >= sizeof(struct rtw_ieee80211_ht_cap)) {
\r
337 ptdls_sta->flags |= WLAN_STA_HT;
\r
338 ptdls_sta->flags |= WLAN_STA_WME;
\r
340 _rtw_memcpy(&ptdls_sta->htpriv.ht_cap, data, sizeof(struct rtw_ieee80211_ht_cap));
\r
342 ptdls_sta->flags &= ~WLAN_STA_HT;
\r
344 if (ptdls_sta->flags & WLAN_STA_HT) {
\r
345 if (padapter->registrypriv.ht_enable == _TRUE) {
\r
346 ptdls_sta->htpriv.ht_option = _TRUE;
\r
347 ptdls_sta->qos_option = _TRUE;
\r
349 ptdls_sta->htpriv.ht_option = _FALSE;
\r
350 ptdls_sta->qos_option = _FALSE;
\r
354 /* HT related cap */
\r
355 if (ptdls_sta->htpriv.ht_option) {
\r
356 /* Check if sta supports rx ampdu */
\r
357 if (padapter->registrypriv.ampdu_enable == 1)
\r
358 ptdls_sta->htpriv.ampdu_enable = _TRUE;
\r
360 /* AMPDU Parameters field */
\r
361 /* Get MIN of MAX AMPDU Length Exp */
\r
362 if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (data[2] & 0x3))
\r
363 max_AMPDU_len = (data[2] & 0x3);
\r
365 max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);
\r
366 /* Get MAX of MIN MPDU Start Spacing */
\r
367 if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (data[2] & 0x1c))
\r
368 min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);
\r
370 min_MPDU_spacing = (data[2] & 0x1c);
\r
371 ptdls_sta->htpriv.rx_ampdu_min_spacing = max_AMPDU_len | min_MPDU_spacing;
\r
373 /* Check if sta support s Short GI 20M */
\r
374 if (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
\r
375 ptdls_sta->htpriv.sgi_20m = _TRUE;
\r
377 /* Check if sta support s Short GI 40M */
\r
378 if (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))
\r
379 ptdls_sta->htpriv.sgi_40m = _TRUE;
\r
381 /* Bwmode would still followed AP's setting */
\r
382 if (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) {
\r
383 if (padapter->mlmeextpriv.cur_bwmode >= CHANNEL_WIDTH_40)
\r
384 ptdls_sta->bw_mode = CHANNEL_WIDTH_40;
\r
385 ptdls_sta->htpriv.ch_offset = padapter->mlmeextpriv.cur_ch_offset;
\r
388 /* Config LDPC Coding Capability */
\r
389 if (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX) && GET_HT_CAP_ELE_LDPC_CAP(data)) {
\r
390 SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));
391 DBG_871X("Enable HT Tx LDPC!\n");
393 ptdls_sta->htpriv.ldpc_cap = cur_ldpc_cap;
\r
395 /* Config STBC setting */
\r
396 if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX) && GET_HT_CAP_ELE_RX_STBC(data)) {
\r
397 SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX));
\r
398 DBG_871X("Enable HT Tx STBC!\n");
400 ptdls_sta->htpriv.stbc_cap = cur_stbc_cap;
\r
402 #ifdef CONFIG_BEAMFORMING
403 /* Config Tx beamforming setting */
\r
404 if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) &&
405 GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(data)) {
\r
406 SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
409 if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&
410 GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(data)) {
\r
411 SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
413 ptdls_sta->htpriv.beamform_cap = cur_beamform_cap;
\r
414 if (cur_beamform_cap)
\r
415 DBG_871X("Client HT Beamforming Cap = 0x%02X\n", cur_beamform_cap);
\r
416 #endif /* CONFIG_BEAMFORMING */
\r
421 u8 *rtw_tdls_set_ht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
423 rtw_ht_use_default_setting(padapter);
\r
425 rtw_restructure_ht_ie(padapter, NULL, pframe, 0, &(pattrib->pktlen), padapter->mlmeextpriv.cur_channel);
\r
427 return pframe + pattrib->pktlen;
\r
431 #ifdef CONFIG_80211AC_VHT
\r
432 void rtw_tdls_process_vht_cap(_adapter *padapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)
\r
434 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
435 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
\r
436 u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, cur_beamform_cap = 0, rf_type = RF_1T1R;
\r
440 _rtw_memset(&ptdls_sta->vhtpriv, 0, sizeof(struct vht_priv));
\r
441 if (data && Length == 12) {
\r
442 ptdls_sta->flags |= WLAN_STA_VHT;
\r
444 _rtw_memcpy(ptdls_sta->vhtpriv.vht_cap, data, 12);
\r
447 if (elems.vht_op_mode_notify && elems.vht_op_mode_notify_len == 1) {
448 _rtw_memcpy(&pstat->vhtpriv.vht_op_mode_notify, elems.vht_op_mode_notify, 1);
449 } else /* for Frame without Operating Mode notify ie; default: 80M */ {
\r
450 pstat->vhtpriv.vht_op_mode_notify = CHANNEL_WIDTH_80;
453 ptdls_sta->vhtpriv.vht_op_mode_notify = CHANNEL_WIDTH_80;
\r
456 ptdls_sta->flags &= ~WLAN_STA_VHT;
\r
458 if (ptdls_sta->flags & WLAN_STA_VHT) {
\r
459 if (REGSTY_IS_11AC_ENABLE(&padapter->registrypriv)
\r
460 && hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
\r
461 && (!pmlmepriv->country_ent || COUNTRY_CHPLAN_EN_11AC(pmlmepriv->country_ent)))
\r
462 ptdls_sta->vhtpriv.vht_option = _TRUE;
\r
464 ptdls_sta->vhtpriv.vht_option = _FALSE;
\r
468 if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX) &&
469 GET_VHT_CAPABILITY_ELE_RX_LDPC(data)) {
\r
470 SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
471 DBG_871X("Current VHT LDPC Setting = %02X\n", cur_ldpc_cap);
473 ptdls_sta->vhtpriv.ldpc_cap = cur_ldpc_cap;
\r
475 /* B5 Short GI for 80 MHz */
\r
476 ptdls_sta->vhtpriv.sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(data) & pvhtpriv->sgi_80m) ? _TRUE : _FALSE;
\r
478 /* B8 B9 B10 Rx STBC */
\r
479 if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX) &&
480 GET_VHT_CAPABILITY_ELE_RX_STBC(data)) {
\r
481 SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
482 DBG_871X("Current VHT STBC Setting = %02X\n", cur_stbc_cap);
484 ptdls_sta->vhtpriv.stbc_cap = cur_stbc_cap;
\r
486 /* B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee */
\r
487 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
488 GET_VHT_CAPABILITY_ELE_SU_BFEE(data)) {
\r
489 SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
492 /* B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer */
\r
493 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
494 GET_VHT_CAPABILITY_ELE_SU_BFER(data)) {
\r
495 SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
497 ptdls_sta->vhtpriv.beamform_cap = cur_beamform_cap;
\r
498 if (cur_beamform_cap)
\r
499 DBG_871X("Current VHT Beamforming Setting = %02X\n", cur_beamform_cap);
501 /* B23 B24 B25 Maximum A-MPDU Length Exponent */
\r
502 ptdls_sta->vhtpriv.ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(data);
\r
504 pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(data);
\r
505 _rtw_memcpy(vht_mcs, pcap_mcs, 2);
507 rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
508 if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
510 else if (rf_type == RF_2T2R)
512 else if (rf_type == RF_3T3R)
515 _rtw_memcpy(ptdls_sta->vhtpriv.vht_mcs_map, vht_mcs, 2);
\r
517 ptdls_sta->vhtpriv.vht_highest_rate = rtw_get_vht_highest_rate(ptdls_sta->vhtpriv.vht_mcs_map);
\r
520 u8 *rtw_tdls_set_aid(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
522 return rtw_set_ie(pframe, EID_AID, 2, (u8 *)&(padapter->mlmepriv.cur_network.aid), &(pattrib->pktlen));
\r
525 u8 *rtw_tdls_set_vht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
529 rtw_vht_use_default_setting(padapter);
\r
531 ie_len = rtw_build_vht_cap_ie(padapter, pframe);
\r
532 pattrib->pktlen += ie_len;
\r
534 return pframe + ie_len;
\r
537 u8 *rtw_tdls_set_vht_operation(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib, u8 channel)
\r
541 ie_len = rtw_build_vht_operation_ie(padapter, pframe, channel);
\r
542 pattrib->pktlen += ie_len;
\r
544 return pframe + ie_len;
\r
547 u8 *rtw_tdls_set_vht_op_mode_notify(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib, u8 bw)
\r
551 ie_len = rtw_build_vht_op_mode_notify_ie(padapter, pframe, bw);
\r
552 pattrib->pktlen += ie_len;
\r
554 return pframe + ie_len;
\r
559 u8 *rtw_tdls_set_sup_ch(struct mlme_ext_priv *pmlmeext, u8 *pframe, struct pkt_attrib *pattrib)
\r
561 u8 sup_ch[30 * 2] = {0x00}, ch_set_idx = 0, sup_ch_idx = 2;
\r
564 if (pmlmeext->channel_set[ch_set_idx].ChannelNum <= 14) {
\r
565 sup_ch[0] = 1; /* First channel number */
\r
566 sup_ch[1] = pmlmeext->channel_set[ch_set_idx].ChannelNum; /* Number of channel */
\r
568 sup_ch[sup_ch_idx++] = pmlmeext->channel_set[ch_set_idx].ChannelNum;
\r
569 sup_ch[sup_ch_idx++] = 1;
\r
572 } while (pmlmeext->channel_set[ch_set_idx].ChannelNum != 0 && ch_set_idx < MAX_CHANNEL_NUM);
\r
574 return rtw_set_ie(pframe, _SUPPORTED_CH_IE_, sup_ch_idx, sup_ch, &(pattrib->pktlen));
\r
577 u8 *rtw_tdls_set_rsnie(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, int init, struct sta_info *ptdls_sta)
\r
582 if (ptxmgmt->len > 0)
\r
583 p = rtw_get_ie(ptxmgmt->buf, _RSN_IE_2_, &len, ptxmgmt->len);
\r
586 return rtw_set_ie(pframe, _RSN_IE_2_, len, p+2, &(pattrib->pktlen));
\r
589 return rtw_set_ie(pframe, _RSN_IE_2_, sizeof(TDLS_RSNIE), TDLS_RSNIE, &(pattrib->pktlen));
\r
591 return rtw_set_ie(pframe, _RSN_IE_2_, sizeof(ptdls_sta->TDLS_RSNIE), ptdls_sta->TDLS_RSNIE, &(pattrib->pktlen));
\r
594 u8 *rtw_tdls_set_ext_cap(u8 *pframe, struct pkt_attrib *pattrib)
\r
596 return rtw_set_ie(pframe, _EXT_CAP_IE_ , sizeof(TDLS_EXT_CAPIE), TDLS_EXT_CAPIE, &(pattrib->pktlen));
\r
599 u8 *rtw_tdls_set_qos_cap(u8 *pframe, struct pkt_attrib *pattrib)
\r
601 return rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(TDLS_WMMIE), TDLS_WMMIE, &(pattrib->pktlen));
\r
604 u8 *rtw_tdls_set_ftie(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, u8 *ANonce, u8 *SNonce)
\r
606 struct wpa_tdls_ftie FTIE = {0};
\r
610 if (ptxmgmt->len > 0)
\r
611 p = rtw_get_ie(ptxmgmt->buf, _FTIE_, &len, ptxmgmt->len);
\r
614 return rtw_set_ie(pframe, _FTIE_, len, p+2, &(pattrib->pktlen));
\r
616 if (ANonce != NULL)
\r
617 _rtw_memcpy(FTIE.Anonce, ANonce, WPA_NONCE_LEN);
\r
618 if (SNonce != NULL)
\r
619 _rtw_memcpy(FTIE.Snonce, SNonce, WPA_NONCE_LEN);
\r
620 return rtw_set_ie(pframe, _FTIE_ , 82, (u8 *)FTIE.mic_ctrl, &(pattrib->pktlen));
\r
624 u8 *rtw_tdls_set_timeout_interval(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, int init, struct sta_info *ptdls_sta)
\r
626 u8 timeout_itvl[5]; /* set timeout interval to maximum value */
\r
627 u32 timeout_interval = TDLS_TPK_RESEND_COUNT;
\r
631 if (ptxmgmt->len > 0)
\r
632 p = rtw_get_ie(ptxmgmt->buf, _TIMEOUT_ITVL_IE_, &len, ptxmgmt->len);
\r
635 return rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, len, p+2, &(pattrib->pktlen));
\r
637 /* Timeout interval */
\r
638 timeout_itvl[0]=0x02;
\r
640 _rtw_memcpy(timeout_itvl+1, &timeout_interval, 4);
\r
642 _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);
\r
644 return rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
\r
648 u8 *rtw_tdls_set_bss_coexist(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
652 if (padapter->mlmepriv.num_FortyMHzIntolerant > 0)
\r
653 iedata |= BIT(2); /* 20 MHz BSS Width Request */
\r
655 /* Information Bit should be set by TDLS test plan 5.9 */
\r
657 return rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
\r
660 u8 *rtw_tdls_set_payload_type(u8 *pframe, struct pkt_attrib *pattrib)
\r
662 u8 payload_type = 0x02;
\r
663 return rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
666 u8 *rtw_tdls_set_category(u8 *pframe, struct pkt_attrib *pattrib, u8 category)
\r
668 return rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
671 u8 *rtw_tdls_set_action(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)
\r
673 return rtw_set_fixed_ie(pframe, 1, &(ptxmgmt->action_code), &(pattrib->pktlen));
\r
676 u8 *rtw_tdls_set_status_code(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)
\r
678 return rtw_set_fixed_ie(pframe, 2, (u8 *)&(ptxmgmt->status_code), &(pattrib->pktlen));
\r
681 u8 *rtw_tdls_set_dialog(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)
\r
683 u8 dialogtoken = 1;
\r
684 if (ptxmgmt->dialog_token)
\r
685 return rtw_set_fixed_ie(pframe, 1, &(ptxmgmt->dialog_token), &(pattrib->pktlen));
\r
687 return rtw_set_fixed_ie(pframe, 1, &(dialogtoken), &(pattrib->pktlen));
\r
690 u8 *rtw_tdls_set_reg_class(u8 *pframe, struct pkt_attrib *pattrib, struct sta_info *ptdls_sta)
\r
693 return rtw_set_fixed_ie(pframe, 1, &(reg_class), &(pattrib->pktlen));
\r
696 u8 *rtw_tdls_set_second_channel_offset(u8 *pframe, struct pkt_attrib *pattrib, u8 ch_offset)
\r
698 return rtw_set_ie(pframe, EID_SecondaryChnlOffset , 1, &ch_offset, &(pattrib->pktlen));
\r
701 u8 *rtw_tdls_set_capability(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
703 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
704 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
\r
705 u8 cap_from_ie[2] = {0};
\r
707 _rtw_memcpy(cap_from_ie, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
\r
709 return rtw_set_fixed_ie(pframe, 2, cap_from_ie, &(pattrib->pktlen));
\r
712 u8 *rtw_tdls_set_supported_rate(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
714 u8 bssrate[NDIS_802_11_LENGTH_RATES_EX];
\r
715 int bssrate_len = 0;
\r
716 u8 more_supportedrates = 0;
\r
718 rtw_set_supported_rate(bssrate, (padapter->registrypriv.wireless_mode == WIRELESS_MODE_MAX) ? padapter->mlmeextpriv.cur_wireless_mode : padapter->registrypriv.wireless_mode);
\r
719 bssrate_len = rtw_get_rateset_len(bssrate);
\r
721 if (bssrate_len > 8) {
\r
722 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
\r
723 more_supportedrates = 1;
\r
725 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
\r
728 /* extended supported rates */
\r
729 if (more_supportedrates == 1) {
\r
730 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
\r
736 u8 *rtw_tdls_set_sup_reg_class(u8 *pframe, struct pkt_attrib *pattrib)
\r
738 return rtw_set_ie(pframe, _SRC_IE_ , sizeof(TDLS_SRC), TDLS_SRC, &(pattrib->pktlen));
\r
741 u8 *rtw_tdls_set_linkid(u8 *pframe, struct pkt_attrib *pattrib, u8 init)
\r
743 u8 link_id_addr[18] = {0};
\r
744 if (init == _TRUE) {
\r
745 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
746 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
\r
747 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
\r
749 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
750 _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);
\r
751 _rtw_memcpy((link_id_addr+12), pattrib->src, 6);
\r
753 return rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
756 #ifdef CONFIG_TDLS_CH_SW
\r
757 u8 *rtw_tdls_set_target_ch(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
760 if (padapter->tdlsinfo.chsw_info.off_ch_num)
\r
761 return rtw_set_fixed_ie(pframe, 1, &(padapter->tdlsinfo.chsw_info.off_ch_num), &(pattrib->pktlen));
\r
763 return rtw_set_fixed_ie(pframe, 1, &(target_ch), &(pattrib->pktlen));
\r
766 u8 *rtw_tdls_set_ch_sw(u8 *pframe, struct pkt_attrib *pattrib, struct sta_info *ptdls_sta)
\r
768 u8 ch_switch_timing[4] = {0};
\r
769 u16 switch_time = (ptdls_sta->ch_switch_time >= TDLS_CH_SWITCH_TIME * 1000) ?
\r
770 ptdls_sta->ch_switch_time : TDLS_CH_SWITCH_TIME;
\r
771 u16 switch_timeout = (ptdls_sta->ch_switch_timeout >= TDLS_CH_SWITCH_TIMEOUT * 1000) ?
\r
772 ptdls_sta->ch_switch_timeout : TDLS_CH_SWITCH_TIMEOUT;
\r
774 _rtw_memcpy(ch_switch_timing, &switch_time, 2);
\r
775 _rtw_memcpy(ch_switch_timing + 2, &switch_timeout, 2);
\r
777 return rtw_set_ie(pframe, _CH_SWITCH_TIMING_, 4, ch_switch_timing, &(pattrib->pktlen));
\r
780 void rtw_tdls_set_ch_sw_oper_control(_adapter *padapter, u8 enable)
\r
782 if (ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on) != enable)
\r
783 ATOMIC_SET(&padapter->tdlsinfo.chsw_info.chsw_on, enable);
\r
785 rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_BCN_EARLY_C2H_RPT, &enable);
\r
786 DBG_871X("[TDLS] %s Bcn Early C2H Report\n", (enable == _TRUE) ? "Start" : "Stop");
\r
789 void rtw_tdls_ch_sw_back_to_base_chnl(_adapter *padapter)
\r
791 struct mlme_priv *pmlmepriv;
\r
792 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
794 pmlmepriv = &padapter->mlmepriv;
\r
796 if ((ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE) &&
\r
797 (padapter->mlmeextpriv.cur_channel != rtw_get_oper_ch(padapter)))
\r
798 rtw_tdls_cmd(padapter, pchsw_info->addr, TDLS_CH_SW_TO_BASE_CHNL_UNSOLICITED);
\r
801 static void rtw_tdls_chsw_oper_init(_adapter *padapter, u32 timeout_ms)
\r
803 struct submit_ctx *chsw_sctx = &padapter->tdlsinfo.chsw_info.chsw_sctx;
\r
805 rtw_sctx_init(chsw_sctx, timeout_ms);
\r
808 static int rtw_tdls_chsw_oper_wait(_adapter *padapter)
\r
810 struct submit_ctx *chsw_sctx = &padapter->tdlsinfo.chsw_info.chsw_sctx;
\r
812 return rtw_sctx_wait(chsw_sctx, __func__);
\r
815 void rtw_tdls_chsw_oper_done(_adapter *padapter)
\r
817 struct submit_ctx *chsw_sctx = &padapter->tdlsinfo.chsw_info.chsw_sctx;
\r
819 rtw_sctx_done(&chsw_sctx);
\r
822 s32 rtw_tdls_do_ch_sw(_adapter *padapter, u8 chnl_type, u8 channel, u8 channel_offset, u16 bwmode, u16 ch_switch_time)
\r
824 u32 ch_sw_time_start, ch_sw_time_spent, wait_time;
\r
828 ch_sw_time_start = rtw_systime_to_ms(rtw_get_current_time());
\r
830 rtw_tdls_chsw_oper_init(padapter, TDLS_CH_SWITCH_OPER_OFFLOAD_TIMEOUT);
\r
832 /* channel switch IOs offload to FW */
\r
833 if (rtw_hal_ch_sw_oper_offload(padapter, channel, channel_offset, bwmode) == _SUCCESS) {
\r
834 if (rtw_tdls_chsw_oper_wait(padapter) == _SUCCESS) {
\r
835 /* set channel and bw related variables in driver */
\r
836 _enter_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);
\r
837 rtw_set_oper_ch(padapter, channel);
\r
838 rtw_set_oper_choffset(padapter, channel_offset);
\r
839 rtw_set_oper_bw(padapter, bwmode);
\r
840 _exit_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);
\r
842 rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk);
\r
843 if (take_care_iqk == _TRUE)
\r
844 rtw_hal_ch_sw_iqk_info_restore(padapter, CH_SW_USE_CASE_TDLS);
\r
846 ch_sw_time_spent = rtw_systime_to_ms(rtw_get_current_time()) - ch_sw_time_start;
\r
848 if (chnl_type == TDLS_CH_SW_OFF_CHNL) {
\r
849 if ((u32)ch_switch_time / 1000 > ch_sw_time_spent)
\r
850 wait_time = (u32)ch_switch_time / 1000 - ch_sw_time_spent;
\r
855 rtw_msleep_os(wait_time);
\r
860 DBG_871X("[TDLS] chsw oper wait fail !!\n");
\r
867 u8 *rtw_tdls_set_wmm_params(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
869 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
870 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
871 u8 wmm_param_ele[24] = {0};
\r
873 if (&pmlmeinfo->WMM_param) {
\r
874 _rtw_memcpy(wmm_param_ele, WMM_PARA_OUI, 6);
\r
875 if (_rtw_memcmp(&pmlmeinfo->WMM_param, &wmm_param_ele[6], 18) == _TRUE)
\r
876 /* Use default WMM Param */
\r
877 _rtw_memcpy(wmm_param_ele + 6, (u8 *)&TDLS_WMM_PARAM_IE, sizeof(TDLS_WMM_PARAM_IE));
\r
879 _rtw_memcpy(wmm_param_ele + 6, (u8 *)&pmlmeinfo->WMM_param, sizeof(pmlmeinfo->WMM_param));
\r
880 return rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 24, wmm_param_ele, &(pattrib->pktlen));
\r
887 void rtw_tdls_process_wfd_ie(struct tdls_info *ptdlsinfo, u8 *ptr, u8 length)
\r
892 if (!hal_chk_wl_func(tdls_info_to_adapter(ptdlsinfo), WL_FUNC_MIRACAST))
\r
895 /* Try to get the TCP port information when receiving the negotiation response. */
\r
897 wfd_ie = rtw_get_wfd_ie(ptr, length, NULL, &wfd_ielen);
\r
900 u32 attr_contentlen = 0;
\r
903 DBG_871X( "[%s] WFD IE Found!!\n", __FUNCTION__ );
\r
904 attr_content = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &attr_contentlen);
\r
905 if (attr_content && attr_contentlen) {
\r
906 ptdlsinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );
\r
907 DBG_871X( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, ptdlsinfo->wfd_info->peer_rtsp_ctrlport );
\r
910 attr_content = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_LOCAL_IP_ADDR, NULL, &attr_contentlen);
\r
911 if (attr_content && attr_contentlen) {
\r
912 _rtw_memcpy(ptdlsinfo->wfd_info->peer_ip_address, ( attr_content + 1 ), 4);
\r
913 DBG_871X("[%s] Peer IP = %02u.%02u.%02u.%02u\n", __FUNCTION__,
\r
914 ptdlsinfo->wfd_info->peer_ip_address[0], ptdlsinfo->wfd_info->peer_ip_address[1],
\r
915 ptdlsinfo->wfd_info->peer_ip_address[2], ptdlsinfo->wfd_info->peer_ip_address[3]);
\r
918 wfd_ie = rtw_get_wfd_ie(wfd_ie + wfd_ielen, (ptr + length) - (wfd_ie + wfd_ielen), NULL, &wfd_ielen);
\r
922 int issue_tunneled_probe_req(_adapter *padapter)
\r
924 struct xmit_frame *pmgntframe;
\r
925 struct pkt_attrib *pattrib;
\r
926 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
927 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
928 u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
\r
929 struct tdls_txmgmt txmgmt;
\r
932 DBG_871X("[%s]\n", __FUNCTION__);
\r
934 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
935 txmgmt.action_code = TUNNELED_PROBE_REQ;
\r
937 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
940 pattrib = &pmgntframe->attrib;
\r
942 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
943 pattrib->ether_type = 0x890d;
\r
945 _rtw_memcpy(pattrib->dst, baddr, ETH_ALEN);
\r
946 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
947 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
948 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
950 update_tdls_attrib(padapter, pattrib);
\r
951 pattrib->qsel = pattrib->priority;
\r
952 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {
\r
953 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
954 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
957 dump_mgntframe(padapter, pmgntframe);
\r
964 int issue_tunneled_probe_rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
966 struct xmit_frame *pmgntframe;
\r
967 struct pkt_attrib *pattrib;
\r
968 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
969 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
970 struct tdls_txmgmt txmgmt;
\r
973 DBG_871X("[%s]\n", __FUNCTION__);
\r
975 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
976 txmgmt.action_code = TUNNELED_PROBE_RSP;
\r
978 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
981 pattrib = &pmgntframe->attrib;
\r
983 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
984 pattrib->ether_type = 0x890d;
\r
986 _rtw_memcpy(pattrib->dst, precv_frame->u.hdr.attrib.src, ETH_ALEN);
\r
987 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
988 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
989 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
991 update_tdls_attrib(padapter, pattrib);
\r
992 pattrib->qsel = pattrib->priority;
\r
993 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {
\r
994 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
995 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
998 dump_mgntframe(padapter, pmgntframe);
\r
1004 #endif /* CONFIG_WFD */
\r
1006 int issue_tdls_setup_req(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, int wait_ack)
\r
1008 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
1009 struct xmit_frame *pmgntframe;
\r
1010 struct pkt_attrib *pattrib;
\r
1011 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1012 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1013 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1014 struct sta_info *ptdls_sta= NULL;
\r
1017 /* Retry timer should be set at least 301 sec, using TPK_count counting 301 times. */
\r
1018 u32 timeout_interval = TDLS_TPK_RESEND_COUNT;
\r
1020 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1022 ptxmgmt->action_code = TDLS_SETUP_REQUEST;
\r
1023 if (rtw_tdls_is_setup_allowed(padapter) == _FALSE)
\r
1026 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1029 pattrib = &pmgntframe->attrib;
\r
1030 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1031 pattrib->ether_type = 0x890d;
\r
1033 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
1034 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1035 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
1036 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1038 update_tdls_attrib(padapter, pattrib);
\r
1040 /* init peer sta_info */
\r
1041 ptdls_sta = rtw_get_stainfo(pstapriv, ptxmgmt->peer);
\r
1042 if (ptdls_sta == NULL) {
\r
1043 ptdls_sta = rtw_alloc_stainfo(pstapriv, ptxmgmt->peer);
\r
1044 if (ptdls_sta == NULL) {
\r
1045 DBG_871X("[%s] rtw_alloc_stainfo fail\n", __FUNCTION__);
\r
1046 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
1047 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1052 if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
\r
1053 ptdlsinfo->sta_cnt++;
\r
1055 if (ptdlsinfo->sta_cnt == MAX_ALLOWED_TDLS_STA_NUM)
\r
1056 ptdlsinfo->sta_maximum = _TRUE;
\r
1058 ptdls_sta->tdls_sta_state |= TDLS_RESPONDER_STATE;
\r
1060 if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
\r
1061 ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
\r
1062 _set_timer(&ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);
\r
1065 pattrib->qsel = pattrib->priority;
\r
1067 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) !=_SUCCESS) {
\r
1068 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
1069 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1074 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
\r
1076 dump_mgntframe(padapter, pmgntframe);
\r
1085 int _issue_tdls_teardown(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 wait_ack)
\r
1087 struct xmit_frame *pmgntframe;
\r
1088 struct pkt_attrib *pattrib;
\r
1089 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1090 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1091 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1092 struct sta_info *ptdls_sta=NULL;
\r
1096 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1098 ptxmgmt->action_code = TDLS_TEARDOWN;
\r
1099 ptdls_sta = rtw_get_stainfo(pstapriv, ptxmgmt->peer);
\r
1100 if (ptdls_sta == NULL) {
\r
1101 DBG_871X("Np tdls_sta for tearing down\n");
\r
1105 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1108 rtw_set_scan_deny(padapter, 550);
\r
1110 rtw_scan_abort(padapter);
\r
1111 #ifdef CONFIG_CONCURRENT_MODE
\r
1112 if (rtw_buddy_adapter_up(padapter))
\r
1113 rtw_scan_abort(padapter->pbuddy_adapter);
\r
1114 #endif /* CONFIG_CONCURRENT_MODE */
\r
1116 pattrib = &pmgntframe->attrib;
\r
1118 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1119 pattrib->ether_type = 0x890d;
\r
1121 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
1122 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1123 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
1124 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1126 update_tdls_attrib(padapter, pattrib);
\r
1127 pattrib->qsel = pattrib->priority;
\r
1128 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
\r
1129 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
1130 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1134 if (rtw_tdls_is_driver_setup(padapter) == _TRUE)
\r
1135 if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)
\r
1136 if (pattrib->encrypt)
\r
1137 _cancel_timer_ex(&ptdls_sta->TPK_timer);
\r
1140 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
\r
1142 dump_mgntframe(padapter, pmgntframe);
\r
1146 if (rtw_tdls_is_driver_setup(padapter))
\r
1147 rtw_tdls_cmd(padapter, ptxmgmt->peer, TDLS_TEARDOWN_STA_LOCALLY);
\r
1154 int issue_tdls_teardown(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 wait_ack)
\r
1158 ret = _issue_tdls_teardown(padapter, ptxmgmt, wait_ack);
\r
1159 if ((ptxmgmt->status_code == _RSON_TDLS_TEAR_UN_RSN_) && (ret == _FAIL)) {
\r
1160 /* Change status code and send teardown again via AP */
\r
1161 ptxmgmt->status_code = _RSON_TDLS_TEAR_TOOFAR_;
\r
1162 ret = _issue_tdls_teardown(padapter, ptxmgmt, wait_ack);
\r
1168 int issue_tdls_dis_req(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)
\r
1170 struct xmit_frame *pmgntframe;
\r
1171 struct pkt_attrib *pattrib;
\r
1172 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1173 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1176 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1178 ptxmgmt->action_code = TDLS_DISCOVERY_REQUEST;
\r
1179 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1182 pattrib = &pmgntframe->attrib;
\r
1183 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1184 pattrib->ether_type = 0x890d;
\r
1186 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
1187 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1188 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
1189 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1191 update_tdls_attrib(padapter, pattrib);
\r
1192 pattrib->qsel = pattrib->priority;
\r
1193 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
\r
1194 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
1195 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1198 dump_mgntframe(padapter, pmgntframe);
\r
1199 DBG_871X("issue tdls dis req\n");
\r
1207 int issue_tdls_setup_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)
\r
1209 struct xmit_frame *pmgntframe;
\r
1210 struct pkt_attrib *pattrib;
\r
1211 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1214 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1216 ptxmgmt->action_code = TDLS_SETUP_RESPONSE;
\r
1217 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1220 pattrib = &pmgntframe->attrib;
\r
1221 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1222 pattrib->ether_type = 0x890d;
\r
1224 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
1225 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1226 _rtw_memcpy(pattrib->ra, get_bssid(&(padapter->mlmepriv)), ETH_ALEN);
\r
1227 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1229 update_tdls_attrib(padapter, pattrib);
\r
1230 pattrib->qsel = pattrib->priority;
\r
1231 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
\r
1232 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
1233 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1237 dump_mgntframe(padapter, pmgntframe);
\r
1246 int issue_tdls_setup_cfm(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)
\r
1248 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
1249 struct xmit_frame *pmgntframe;
\r
1250 struct pkt_attrib *pattrib;
\r
1251 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1254 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1256 ptxmgmt->action_code = TDLS_SETUP_CONFIRM;
\r
1257 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1260 pattrib = &pmgntframe->attrib;
\r
1261 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1262 pattrib->ether_type = 0x890d;
\r
1264 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
1265 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1266 _rtw_memcpy(pattrib->ra, get_bssid(&padapter->mlmepriv), ETH_ALEN);
\r
1267 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1269 update_tdls_attrib(padapter, pattrib);
\r
1270 pattrib->qsel = pattrib->priority;
\r
1271 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
\r
1272 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
1273 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1277 dump_mgntframe(padapter, pmgntframe);
\r
1286 /* TDLS Discovery Response frame is a management action frame */
\r
1287 int issue_tdls_dis_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 privacy)
\r
1289 struct xmit_frame *pmgntframe;
\r
1290 struct pkt_attrib *pattrib;
\r
1291 unsigned char *pframe;
\r
1292 struct rtw_ieee80211_hdr *pwlanhdr;
\r
1293 unsigned short *fctrl;
\r
1294 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1295 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
1298 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1300 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1303 pattrib = &pmgntframe->attrib;
\r
1304 update_mgntframe_attrib(padapter, pattrib);
\r
1306 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
\r
1308 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
\r
1309 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
\r
1311 fctrl = &(pwlanhdr->frame_ctl);
\r
1314 /* unicast probe request frame */
\r
1315 _rtw_memcpy(pwlanhdr->addr1, ptxmgmt->peer, ETH_ALEN);
\r
1316 _rtw_memcpy(pattrib->dst, pwlanhdr->addr1, ETH_ALEN);
\r
1317 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
\r
1318 _rtw_memcpy(pattrib->src, pwlanhdr->addr2, ETH_ALEN);
\r
1319 _rtw_memcpy(pwlanhdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN);
\r
1320 _rtw_memcpy(pattrib->ra, pwlanhdr->addr3, ETH_ALEN);
\r
1322 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
\r
1323 pmlmeext->mgnt_seq++;
\r
1324 SetFrameSubType(pframe, WIFI_ACTION);
\r
1326 pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
\r
1327 pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
\r
1329 rtw_build_tdls_dis_rsp_ies(padapter, pmgntframe, pframe, ptxmgmt, privacy);
\r
1331 pattrib->nr_frags = 1;
\r
1332 pattrib->last_txcmdsz = pattrib->pktlen;
\r
1334 dump_mgntframe(padapter, pmgntframe);
\r
1341 int issue_tdls_peer_traffic_rsp(_adapter *padapter, struct sta_info *ptdls_sta, struct tdls_txmgmt *ptxmgmt)
\r
1343 struct xmit_frame *pmgntframe;
\r
1344 struct pkt_attrib *pattrib;
\r
1345 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1346 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1349 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1351 ptxmgmt->action_code = TDLS_PEER_TRAFFIC_RESPONSE;
\r
1353 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1356 pattrib = &pmgntframe->attrib;
\r
1358 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1359 pattrib->ether_type = 0x890d;
\r
1361 _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
\r
1362 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1363 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
1364 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1366 update_tdls_attrib(padapter, pattrib);
\r
1367 pattrib->qsel = pattrib->priority;
\r
1369 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) !=_SUCCESS) {
\r
1370 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
1371 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1375 dump_mgntframe(padapter, pmgntframe);
\r
1383 int issue_tdls_peer_traffic_indication(_adapter *padapter, struct sta_info *ptdls_sta)
\r
1385 struct xmit_frame *pmgntframe;
\r
1386 struct pkt_attrib *pattrib;
\r
1387 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1388 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1389 struct tdls_txmgmt txmgmt;
\r
1392 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1394 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1395 txmgmt.action_code = TDLS_PEER_TRAFFIC_INDICATION;
\r
1397 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1400 pattrib = &pmgntframe->attrib;
\r
1402 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1403 pattrib->ether_type = 0x890d;
\r
1405 _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
\r
1406 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1407 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
1408 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1410 /* PTI frame's priority should be AC_VO */
\r
1411 pattrib->priority = 7;
\r
1413 update_tdls_attrib(padapter, pattrib);
\r
1414 pattrib->qsel = pattrib->priority;
\r
1415 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {
\r
1416 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
1417 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1421 dump_mgntframe(padapter, pmgntframe);
\r
1429 #ifdef CONFIG_TDLS_CH_SW
\r
1430 int issue_tdls_ch_switch_req(_adapter *padapter, struct sta_info *ptdls_sta)
\r
1432 struct xmit_frame *pmgntframe;
\r
1433 struct pkt_attrib *pattrib;
\r
1434 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1435 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1436 struct tdls_txmgmt txmgmt;
\r
1439 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1441 if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {
\r
1442 DBG_871X("[TDLS] Ignore %s since channel switch is not allowed\n", __func__);
\r
1446 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1447 txmgmt.action_code = TDLS_CHANNEL_SWITCH_REQUEST;
\r
1449 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1452 pattrib = &pmgntframe->attrib;
\r
1454 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1455 pattrib->ether_type = 0x890d;
\r
1457 _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
\r
1458 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1459 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
1460 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1462 update_tdls_attrib(padapter, pattrib);
\r
1463 pattrib->qsel = pattrib->priority;
\r
1464 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) !=_SUCCESS) {
\r
1465 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
1466 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1470 dump_mgntframe(padapter, pmgntframe);
\r
1477 int issue_tdls_ch_switch_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, int wait_ack)
\r
1479 struct xmit_frame *pmgntframe;
\r
1480 struct pkt_attrib *pattrib;
\r
1481 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1482 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1485 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1487 if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {
\r
1488 DBG_871X("[TDLS] Ignore %s since channel switch is not allowed\n", __func__);
\r
1492 ptxmgmt->action_code = TDLS_CHANNEL_SWITCH_RESPONSE;
\r
1494 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1497 pattrib = &pmgntframe->attrib;
\r
1499 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1500 pattrib->ether_type = 0x890d;
\r
1502 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
1503 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1504 _rtw_memcpy(pattrib->ra, ptxmgmt->peer, ETH_ALEN);
\r
1505 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1507 update_tdls_attrib(padapter, pattrib);
\r
1508 pattrib->qsel = pattrib->priority;
\r
1510 _enter_critical_bh(&pxmitpriv->lock, &irqL);
\r
1511 if(xmitframe_enqueue_for_tdls_sleeping_sta(padapter, pmgntframe)==_TRUE){
\r
1512 _exit_critical_bh(&pxmitpriv->lock, &irqL);
\r
1516 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) !=_SUCCESS) {
\r
1517 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
1518 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1523 ret = dump_mgntframe_and_wait_ack_timeout(padapter, pmgntframe, 10);
\r
1525 dump_mgntframe(padapter, pmgntframe);
\r
1534 int On_TDLS_Dis_Rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
1536 struct sta_info *ptdls_sta = NULL, *psta = rtw_get_stainfo(&(padapter->stapriv), get_bssid(&(padapter->mlmepriv)));
\r
1537 struct recv_priv *precvpriv = &(padapter->recvpriv);
\r
1538 u8 *ptr = precv_frame->u.hdr.rx_data, *psa;
\r
1539 struct rx_pkt_attrib *pattrib = &(precv_frame->u.hdr.attrib);
\r
1540 struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);
\r
1541 u8 empty_addr[ETH_ALEN] = { 0x00 };
\r
1542 int UndecoratedSmoothedPWDB;
\r
1543 struct tdls_txmgmt txmgmt;
\r
1544 int ret = _SUCCESS;
\r
1546 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1547 /* WFDTDLS: for sigma test, not to setup direct link automatically */
\r
1548 ptdlsinfo->dev_discovered = _TRUE;
\r
1550 psa = get_sa(ptr);
\r
1551 ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), psa);
\r
1552 if (ptdls_sta != NULL)
\r
1553 ptdls_sta->sta_stats.rx_tdls_disc_rsp_pkts++;
\r
1555 #ifdef CONFIG_TDLS_AUTOSETUP
\r
1556 if (ptdls_sta != NULL) {
\r
1557 /* Record the tdls sta with lowest signal strength */
\r
1558 if (ptdlsinfo->sta_maximum == _TRUE && ptdls_sta->alive_count >= 1 ) {
\r
1559 if (_rtw_memcmp(ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN)) {
\r
1560 _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);
\r
1561 ptdlsinfo->ss_record.RxPWDBAll = pattrib->phy_info.RxPWDBAll;
\r
1563 if (ptdlsinfo->ss_record.RxPWDBAll < pattrib->phy_info.RxPWDBAll) {
\r
1564 _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);
\r
1565 ptdlsinfo->ss_record.RxPWDBAll = pattrib->phy_info.RxPWDBAll;
\r
1570 if (ptdlsinfo->sta_maximum == _TRUE) {
\r
1571 if (_rtw_memcmp( ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN)) {
\r
1572 /* All traffics are busy, do not set up another direct link. */
\r
1576 if (pattrib->phy_info.RxPWDBAll > ptdlsinfo->ss_record.RxPWDBAll) {
\r
1577 _rtw_memcpy(txmgmt.peer, ptdlsinfo->ss_record.macaddr, ETH_ALEN);
\r
1578 /* issue_tdls_teardown(padapter, ptdlsinfo->ss_record.macaddr, _FALSE); */
\r
1586 rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
\r
1588 if (pattrib->phy_info.RxPWDBAll + TDLS_SIGNAL_THRESH >= UndecoratedSmoothedPWDB) {
\r
1589 DBG_871X("pattrib->RxPWDBAll=%d, pdmpriv->UndecoratedSmoothedPWDB=%d\n", pattrib->phy_info.RxPWDBAll, UndecoratedSmoothedPWDB);
\r
1590 _rtw_memcpy(txmgmt.peer, psa, ETH_ALEN);
\r
1591 issue_tdls_setup_req(padapter, &txmgmt, _FALSE);
\r
1594 #endif /* CONFIG_TDLS_AUTOSETUP */
\r
1601 sint On_TDLS_Setup_Req(_adapter *padapter, union recv_frame *precv_frame)
\r
1603 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
1605 struct sta_info *ptdls_sta= NULL;
\r
1606 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1607 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1608 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
1609 struct security_priv *psecuritypriv = &padapter->securitypriv;
\r
1611 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1612 u8 *prsnie, *ppairwise_cipher;
\r
1614 u8 ccmp_included=0, rsnie_included=0;
\r
1615 u16 j, pairwise_count;
\r
1617 u32 timeout_interval = TDLS_TPK_RESEND_COUNT;
\r
1618 sint parsing_length; /* Frame body length, without icv_len */
\r
1619 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1621 unsigned char supportRate[16];
\r
1622 int supportRateNum = 0;
\r
1623 struct tdls_txmgmt txmgmt;
\r
1625 if (rtw_tdls_is_setup_allowed(padapter) == _FALSE)
\r
1628 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1629 psa = get_sa(ptr);
\r
1630 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1632 pmyid = adapter_mac_addr(padapter);
\r
1633 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
1634 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1635 -prx_pkt_attrib->hdrlen
\r
1636 -prx_pkt_attrib->iv_len
\r
1637 -prx_pkt_attrib->icv_len
\r
1643 if (ptdls_sta == NULL) {
\r
1644 ptdls_sta = rtw_alloc_stainfo(pstapriv, psa);
\r
1646 if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {
\r
1647 /* If the direct link is already set up */
\r
1648 /* Process as re-setup after tear down */
\r
1649 DBG_871X("re-setup a direct link\n");
\r
1651 /* Already receiving TDLS setup request */
\r
1652 else if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE) {
\r
1653 DBG_871X("receive duplicated TDLS setup request frame in handshaking\n");
\r
1656 /* When receiving and sending setup_req to the same link at the same time */
\r
1657 /* STA with higher MAC_addr would be initiator */
\r
1658 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE) {
\r
1659 DBG_871X("receive setup_req after sending setup_req\n");
\r
1660 for (i=0;i<6;i++){
\r
1661 if(*(pmyid+i)==*(psa+i)){
\r
1663 else if(*(pmyid+i)>*(psa+i)){
\r
1664 ptdls_sta->tdls_sta_state = TDLS_INITIATOR_STATE;
\r
1666 }else if(*(pmyid+i)<*(psa+i)){
\r
1674 txmgmt.dialog_token = *(ptr+2); /* Copy dialog token */
\r
1675 txmgmt.status_code = _STATS_SUCCESSFUL_;
\r
1677 /* Parsing information element */
\r
1678 for (j=FIXED_IE; j<parsing_length;) {
\r
1680 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1682 switch (pIE->ElementID) {
\r
1683 case _SUPPORTEDRATES_IE_:
\r
1684 _rtw_memcpy(supportRate, pIE->data, pIE->Length);
\r
1685 supportRateNum = pIE->Length;
\r
1687 case _COUNTRY_IE_:
\r
1689 case _EXT_SUPPORTEDRATES_IE_:
\r
1690 if (supportRateNum<=sizeof(supportRate)) {
\r
1691 _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);
\r
1692 supportRateNum += pIE->Length;
\r
1695 case _SUPPORTED_CH_IE_:
\r
1699 if (prx_pkt_attrib->encrypt) {
\r
1701 /* Check CCMP pairwise_cipher presence. */
\r
1702 ppairwise_cipher=prsnie+10;
\r
1703 _rtw_memcpy(ptdls_sta->TDLS_RSNIE, pIE->data, pIE->Length);
\r
1704 pairwise_count = *(u16*)(ppairwise_cipher-2);
\r
1705 for (k=0; k<pairwise_count; k++) {
\r
1706 if (_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE)
\r
1710 if (ccmp_included == 0)
\r
1711 txmgmt.status_code=_STATS_INVALID_RSNIE_;
\r
1714 case _EXT_CAP_IE_:
\r
1716 case _VENDOR_SPECIFIC_IE_:
\r
1719 if (prx_pkt_attrib->encrypt)
\r
1720 _rtw_memcpy(SNonce, (ptr+j+52), 32);
\r
1722 case _TIMEOUT_ITVL_IE_:
\r
1723 if (prx_pkt_attrib->encrypt)
\r
1724 timeout_interval = cpu_to_le32(*(u32*)(ptr+j+3));
\r
1726 case _RIC_Descriptor_IE_:
\r
1728 #ifdef CONFIG_80211N_HT
\r
1729 case _HT_CAPABILITY_IE_:
\r
1730 rtw_tdls_process_ht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);
\r
1733 #ifdef CONFIG_80211AC_VHT
\r
1736 case EID_VHTCapability:
\r
1737 rtw_tdls_process_vht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);
\r
1740 case EID_BSSCoexistence:
\r
1742 case _LINK_ID_IE_:
\r
1743 if (_rtw_memcmp(get_bssid(pmlmepriv), pIE->data, 6) == _FALSE)
\r
1744 txmgmt.status_code=_STATS_NOT_IN_SAME_BSS_;
\r
1750 j += (pIE->Length + 2);
\r
1754 /* Check status code */
\r
1755 /* If responder STA has/hasn't security on AP, but request hasn't/has RSNIE, it should reject */
\r
1756 if (txmgmt.status_code == _STATS_SUCCESSFUL_) {
\r
1757 if (rsnie_included && prx_pkt_attrib->encrypt == 0)
\r
1758 txmgmt.status_code = _STATS_SEC_DISABLED_;
\r
1759 else if (rsnie_included==0 && prx_pkt_attrib->encrypt)
\r
1760 txmgmt.status_code = _STATS_INVALID_PARAMETERS_;
\r
1763 /* WFD test plan version 0.18.2 test item 5.1.5 */
\r
1764 /* SoUT does not use TDLS if AP uses weak security */
\r
1765 if (padapter->wdinfo.wfd_tdls_enable && (rsnie_included && prx_pkt_attrib->encrypt != _AES_))
\r
1766 txmgmt.status_code = _STATS_SEC_DISABLED_;
\r
1767 #endif /* CONFIG_WFD */
\r
1770 ptdls_sta->tdls_sta_state|= TDLS_INITIATOR_STATE;
\r
1771 if (prx_pkt_attrib->encrypt) {
\r
1772 _rtw_memcpy(ptdls_sta->SNonce, SNonce, 32);
\r
1774 if (timeout_interval <= 300)
\r
1775 ptdls_sta->TDLS_PeerKey_Lifetime = TDLS_TPK_RESEND_COUNT;
\r
1777 ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
\r
1780 /* Update station supportRate */
\r
1781 ptdls_sta->bssratelen = supportRateNum;
\r
1782 _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);
\r
1784 if (!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
\r
1785 ptdlsinfo->sta_cnt++;
\r
1786 /* -2: AP + BC/MC sta, -4: default key */
\r
1787 if (ptdlsinfo->sta_cnt == MAX_ALLOWED_TDLS_STA_NUM)
\r
1788 ptdlsinfo->sta_maximum = _TRUE;
\r
1791 rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length);
\r
1798 _rtw_memcpy(txmgmt.peer, prx_pkt_attrib->src, ETH_ALEN);
\r
1800 if (rtw_tdls_is_driver_setup(padapter)) {
\r
1801 issue_tdls_setup_rsp(padapter, &txmgmt);
\r
1803 if (txmgmt.status_code==_STATS_SUCCESSFUL_) {
\r
1804 _set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);
\r
1806 free_tdls_sta(padapter, ptdls_sta);
\r
1815 int On_TDLS_Setup_Rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
1817 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
1818 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
1819 struct sta_info *ptdls_sta= NULL;
\r
1820 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1821 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1823 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1825 u16 status_code=0;
\r
1826 sint parsing_length; /* Frame body length, without icv_len */
\r
1827 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1830 u8 *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL, *ppairwise_cipher=NULL;
\r
1831 u16 pairwise_count, j, k;
\r
1833 unsigned char supportRate[16];
\r
1834 int supportRateNum = 0;
\r
1835 struct tdls_txmgmt txmgmt;
\r
1836 int ret = _SUCCESS;
\r
1837 u32 timeout_interval = TDLS_TPK_RESEND_COUNT;
\r
1839 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1840 psa = get_sa(ptr);
\r
1841 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1843 if (ptdls_sta == NULL) {
\r
1844 DBG_871X("[%s] Direct Link Peer = "MAC_FMT" not found\n", __func__, MAC_ARG(psa));
\r
1849 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
1850 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1851 -prx_pkt_attrib->hdrlen
\r
1852 -prx_pkt_attrib->iv_len
\r
1853 -prx_pkt_attrib->icv_len
\r
1859 _rtw_memcpy(&status_code, ptr+2, 2);
\r
1861 if (status_code != 0) {
\r
1862 DBG_871X( "[TDLS] %s status_code = %d, free_tdls_sta\n", __FUNCTION__, status_code );
\r
1863 free_tdls_sta(padapter, ptdls_sta);
\r
1870 /* parsing information element */
\r
1871 for (j = FIXED_IE; j<parsing_length;) {
\r
1872 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1874 switch (pIE->ElementID) {
\r
1875 case _SUPPORTEDRATES_IE_:
\r
1876 _rtw_memcpy(supportRate, pIE->data, pIE->Length);
\r
1877 supportRateNum = pIE->Length;
\r
1879 case _COUNTRY_IE_:
\r
1881 case _EXT_SUPPORTEDRATES_IE_:
\r
1882 if (supportRateNum<=sizeof(supportRate)) {
\r
1883 _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);
\r
1884 supportRateNum += pIE->Length;
\r
1887 case _SUPPORTED_CH_IE_:
\r
1891 /* Check CCMP pairwise_cipher presence. */
\r
1892 ppairwise_cipher=prsnie+10;
\r
1893 _rtw_memcpy(&pairwise_count, (u16*)(ppairwise_cipher-2), 2);
\r
1894 for (k=0;k<pairwise_count;k++) {
\r
1895 if (_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4) == _TRUE)
\r
1898 case _EXT_CAP_IE_:
\r
1900 case _VENDOR_SPECIFIC_IE_:
\r
1901 if (_rtw_memcmp((u8 *)pIE + 2, WMM_INFO_OUI, 6) == _TRUE) {
\r
1902 /* WMM Info ID and OUI */
\r
1903 if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))
\r
1904 ptdls_sta->qos_option = _TRUE;
\r
1909 _rtw_memcpy(ANonce, (ptr+j+20), 32);
\r
1911 case _TIMEOUT_ITVL_IE_:
\r
1912 ptimeout_ie=(u8*)pIE;
\r
1913 timeout_interval = cpu_to_le32(*(u32*)(ptimeout_ie+3));
\r
1915 case _RIC_Descriptor_IE_:
\r
1917 #ifdef CONFIG_80211N_HT
\r
1918 case _HT_CAPABILITY_IE_:
\r
1919 rtw_tdls_process_ht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);
\r
1922 #ifdef CONFIG_80211AC_VHT
\r
1924 /* todo in the future if necessary */
\r
1926 case EID_VHTCapability:
\r
1927 rtw_tdls_process_vht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);
\r
1929 case EID_OpModeNotification:
\r
1930 rtw_process_vht_op_mode_notify(padapter, pIE->data, ptdls_sta);
\r
1933 case EID_BSSCoexistence:
\r
1935 case _LINK_ID_IE_:
\r
1936 plinkid_ie=(u8*)pIE;
\r
1942 j += (pIE->Length + 2);
\r
1946 ptdls_sta->bssratelen = supportRateNum;
\r
1947 _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);
\r
1948 _rtw_memcpy(ptdls_sta->ANonce, ANonce, 32);
\r
1951 rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length);
\r
1954 if (status_code != _STATS_SUCCESSFUL_) {
\r
1955 txmgmt.status_code = status_code;
\r
1957 if (prx_pkt_attrib->encrypt) {
\r
1958 if (verify_ccmp == 1) {
\r
1959 txmgmt.status_code = _STATS_SUCCESSFUL_;
\r
1960 if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
\r
1961 wpa_tdls_generate_tpk(padapter, ptdls_sta);
\r
1962 if (tdls_verify_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie) == _FAIL) {
\r
1963 DBG_871X( "[TDLS] %s tdls_verify_mic fail, free_tdls_sta\n", __FUNCTION__);
\r
1964 free_tdls_sta(padapter, ptdls_sta);
\r
1968 ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
\r
1973 txmgmt.status_code = _STATS_INVALID_RSNIE_;
\r
1977 txmgmt.status_code = _STATS_SUCCESSFUL_;
\r
1981 if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
\r
1982 _rtw_memcpy(txmgmt.peer, prx_pkt_attrib->src, ETH_ALEN);
\r
1983 issue_tdls_setup_cfm(padapter, &txmgmt);
\r
1985 if (txmgmt.status_code == _STATS_SUCCESSFUL_) {
\r
1986 ptdlsinfo->link_established = _TRUE;
\r
1988 if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE) {
\r
1989 ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;
\r
1990 ptdls_sta->state |= _FW_LINKED;
\r
1991 _cancel_timer_ex( &ptdls_sta->handshake_timer);
\r
1994 if (prx_pkt_attrib->encrypt)
\r
1995 rtw_tdls_set_key(padapter, ptdls_sta);
\r
1997 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_ESTABLISHED);
\r
2003 if (rtw_tdls_is_driver_setup(padapter) == _TRUE)
\r
2010 int On_TDLS_Setup_Cfm(_adapter *padapter, union recv_frame *precv_frame)
\r
2012 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
2013 struct sta_info *ptdls_sta= NULL;
\r
2014 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2015 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
2017 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
2019 u16 status_code=0;
\r
2020 sint parsing_length;
\r
2021 PNDIS_802_11_VARIABLE_IEs pIE;
\r
2023 u8 *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL, *ppairwise_cipher=NULL;
\r
2024 u16 j, pairwise_count;
\r
2025 int ret = _SUCCESS;
\r
2027 psa = get_sa(ptr);
\r
2028 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
2030 if (ptdls_sta == NULL) {
\r
2031 DBG_871X("[%s] Direct Link Peer = "MAC_FMT" not found\n", __FUNCTION__, MAC_ARG(psa));
\r
2036 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
2037 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
2038 -prx_pkt_attrib->hdrlen
\r
2039 -prx_pkt_attrib->iv_len
\r
2040 -prx_pkt_attrib->icv_len
\r
2046 _rtw_memcpy(&status_code, ptr+2, 2);
\r
2048 if (status_code!= 0) {
\r
2049 DBG_871X("[%s] status_code = %d\n, free_tdls_sta", __FUNCTION__, status_code);
\r
2050 free_tdls_sta(padapter, ptdls_sta);
\r
2055 /* Parsing information element */
\r
2056 for (j = FIXED_IE; j < parsing_length;) {
\r
2058 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr + j);
\r
2060 switch (pIE->ElementID) {
\r
2062 prsnie = (u8 *)pIE;
\r
2064 case _VENDOR_SPECIFIC_IE_:
\r
2065 if (_rtw_memcmp((u8 *)pIE + 2, WMM_PARA_OUI, 6) == _TRUE) {
\r
2066 /* WMM Parameter ID and OUI */
\r
2067 ptdls_sta->qos_option = _TRUE;
\r
2071 pftie = (u8 *)pIE;
\r
2073 case _TIMEOUT_ITVL_IE_:
\r
2074 ptimeout_ie = (u8 *)pIE;
\r
2076 #ifdef CONFIG_80211N_HT
\r
2077 case _HT_EXTRA_INFO_IE_:
\r
2080 #ifdef CONFIG_80211AC_VHT
\r
2081 case EID_VHTOperation:
\r
2083 case EID_OpModeNotification:
\r
2084 rtw_process_vht_op_mode_notify(padapter, pIE->data, ptdls_sta);
\r
2087 case _LINK_ID_IE_:
\r
2088 plinkid_ie = (u8 *)pIE;
\r
2094 j += (pIE->Length + 2);
\r
2098 if (prx_pkt_attrib->encrypt) {
\r
2099 /* Verify mic in FTIE MIC field */
\r
2100 if (rtw_tdls_is_driver_setup(padapter) &&
\r
2101 (tdls_verify_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie) == _FAIL)) {
\r
2102 free_tdls_sta(padapter, ptdls_sta);
\r
2108 if (rtw_tdls_is_driver_setup(padapter)) {
\r
2109 ptdlsinfo->link_established = _TRUE;
\r
2111 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE) {
\r
2112 ptdls_sta->tdls_sta_state|=TDLS_LINKED_STATE;
\r
2113 ptdls_sta->state |= _FW_LINKED;
\r
2114 _cancel_timer_ex(&ptdls_sta->handshake_timer);
\r
2117 if (prx_pkt_attrib->encrypt) {
\r
2118 rtw_tdls_set_key(padapter, ptdls_sta);
\r
2120 /* Start TPK timer */
\r
2121 ptdls_sta->TPK_count = 0;
\r
2122 _set_timer(&ptdls_sta->TPK_timer, ONE_SEC);
\r
2125 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_ESTABLISHED);
\r
2133 int On_TDLS_Dis_Req(_adapter *padapter, union recv_frame *precv_frame)
\r
2135 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
2136 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2137 struct sta_info *psta_ap;
\r
2138 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
2139 sint parsing_length; /* Frame body length, without icv_len */
\r
2140 PNDIS_802_11_VARIABLE_IEs pIE;
\r
2141 u8 FIXED_IE = 3, *dst;
\r
2143 struct tdls_txmgmt txmgmt;
\r
2144 int ret = _SUCCESS;
\r
2146 if (rtw_tdls_is_driver_setup(padapter) == _FALSE)
\r
2149 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
2150 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
2151 txmgmt.dialog_token = *(ptr+2);
\r
2152 _rtw_memcpy(&txmgmt.peer, precv_frame->u.hdr.attrib.src, ETH_ALEN);
\r
2153 txmgmt.action_code = TDLS_DISCOVERY_RESPONSE;
\r
2154 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
2155 -prx_pkt_attrib->hdrlen
\r
2156 -prx_pkt_attrib->iv_len
\r
2157 -prx_pkt_attrib->icv_len
\r
2163 /* Parsing information element */
\r
2164 for (j=FIXED_IE; j<parsing_length;) {
\r
2166 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
2168 switch (pIE->ElementID) {
\r
2169 case _LINK_ID_IE_:
\r
2170 psta_ap = rtw_get_stainfo(pstapriv, pIE->data);
\r
2171 if (psta_ap == NULL)
\r
2173 dst = pIE->data + 12;
\r
2174 if (MacAddr_isBcst(dst) == _FALSE && (_rtw_memcmp(adapter_mac_addr(padapter), dst, 6) == _FALSE))
\r
2181 j += (pIE->Length + 2);
\r
2185 issue_tdls_dis_rsp(padapter, &txmgmt, prx_pkt_attrib->privacy);
\r
2192 int On_TDLS_Teardown(_adapter *padapter, union recv_frame *precv_frame)
\r
2195 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
2196 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
2197 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2198 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
2199 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2200 struct sta_info *ptdls_sta= NULL;
\r
2204 reason = *(ptr + prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN + 2);
\r
2205 DBG_871X("[TDLS] %s Reason code(%d)\n", __FUNCTION__,reason);
\r
2207 psa = get_sa(ptr);
\r
2209 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
2210 if (ptdls_sta != NULL) {
\r
2211 if (rtw_tdls_is_driver_setup(padapter))
\r
2212 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_TEARDOWN_STA_LOCALLY);
\r
2220 u8 TDLS_check_ch_state(uint state){
\r
2221 if (state & TDLS_CH_SWITCH_ON_STATE &&
\r
2222 state & TDLS_PEER_AT_OFF_STATE) {
\r
2223 if (state & TDLS_PEER_SLEEP_STATE)
\r
2224 return 2; /* U-APSD + ch. switch */
\r
2226 return 1; /* ch. switch */
\r
2232 int On_TDLS_Peer_Traffic_Indication(_adapter *padapter, union recv_frame *precv_frame)
\r
2234 struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
\r
2235 struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->src);
\r
2236 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
2237 struct tdls_txmgmt txmgmt;
\r
2239 ptr +=pattrib->hdrlen + pattrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
2240 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
2242 if (ptdls_sta != NULL) {
\r
2243 txmgmt.dialog_token = *(ptr+2);
\r
2244 issue_tdls_peer_traffic_rsp(padapter, ptdls_sta, &txmgmt);
\r
2245 //issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 0, 0);
\r
2247 DBG_871X("from unknown sta:"MAC_FMT"\n", MAC_ARG(pattrib->src));
\r
2254 /* We process buffered data for 1. U-APSD, 2. ch. switch, 3. U-APSD + ch. switch here */
\r
2255 int On_TDLS_Peer_Traffic_Rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
2257 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
2258 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2259 struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib;
\r
2260 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2261 struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->src);
\r
2263 /* u8 state=TDLS_check_ch_state(ptdls_sta->tdls_sta_state); */
\r
2266 ptdls_sta->sta_stats.rx_data_pkts++;
\r
2268 ptdls_sta->tdls_sta_state &= ~(TDLS_WAIT_PTR_STATE);
\r
2270 /* Check 4-AC queue bit */
\r
2271 if (ptdls_sta->uapsd_vo || ptdls_sta->uapsd_vi || ptdls_sta->uapsd_be || ptdls_sta->uapsd_bk)
\r
2274 /* If it's a direct link and have buffered frame */
\r
2275 if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {
\r
2278 _list *xmitframe_plist, *xmitframe_phead;
\r
2279 struct xmit_frame *pxmitframe=NULL;
\r
2281 _enter_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);
\r
2283 xmitframe_phead = get_list_head(&ptdls_sta->sleep_q);
\r
2284 xmitframe_plist = get_next(xmitframe_phead);
\r
2286 /* transmit buffered frames */
\r
2287 while (rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == _FALSE) {
\r
2288 pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
\r
2289 xmitframe_plist = get_next(xmitframe_plist);
\r
2290 rtw_list_delete(&pxmitframe->list);
\r
2292 ptdls_sta->sleepq_len--;
\r
2293 ptdls_sta->sleepq_ac_len--;
\r
2294 if (ptdls_sta->sleepq_len>0) {
\r
2295 pxmitframe->attrib.mdata = 1;
\r
2296 pxmitframe->attrib.eosp = 0;
\r
2298 pxmitframe->attrib.mdata = 0;
\r
2299 pxmitframe->attrib.eosp = 1;
\r
2301 pxmitframe->attrib.triggered = 1;
\r
2303 rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
\r
2306 if (ptdls_sta->sleepq_len==0)
\r
2307 DBG_871X("no buffered packets for tdls to xmit\n");
\r
2309 DBG_871X("error!psta->sleepq_len=%d\n", ptdls_sta->sleepq_len);
\r
2310 ptdls_sta->sleepq_len=0;
\r
2313 _exit_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);
\r
2322 #ifdef CONFIG_TDLS_CH_SW
\r
2323 sint On_TDLS_Ch_Switch_Req(_adapter *padapter, union recv_frame *precv_frame)
\r
2325 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
2326 struct sta_info *ptdls_sta= NULL;
\r
2327 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2328 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
2329 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
2331 sint parsing_length;
\r
2332 PNDIS_802_11_VARIABLE_IEs pIE;
\r
2335 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2336 struct tdls_txmgmt txmgmt;
\r
2337 u8 zaddr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
\r
2338 u16 switch_time = TDLS_CH_SWITCH_TIME * 1000, switch_timeout = TDLS_CH_SWITCH_TIMEOUT * 1000;
\r
2341 if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {
\r
2342 DBG_871X("[TDLS] Ignore %s since channel switch is not allowed\n", __func__);
\r
2346 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
2347 psa = get_sa(ptr);
\r
2348 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
2350 if (ptdls_sta == NULL) {
\r
2351 DBG_871X("[%s] Direct Link Peer = "MAC_FMT" not found\n", __func__, MAC_ARG(psa));
\r
2355 ptdls_sta->ch_switch_time=switch_time;
\r
2356 ptdls_sta->ch_switch_timeout=switch_timeout;
\r
2358 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
2359 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
2360 -prx_pkt_attrib->hdrlen
\r
2361 -prx_pkt_attrib->iv_len
\r
2362 -prx_pkt_attrib->icv_len
\r
2368 pchsw_info->off_ch_num = *(ptr + 2);
\r
2370 if ((*(ptr + 2) == 2) && (hal_is_band_support(padapter, BAND_ON_5G))) {
\r
2371 pchsw_info->off_ch_num = 44;
\r
2374 if (pchsw_info->off_ch_num != pmlmeext->cur_channel) {
\r
2375 pchsw_info->delay_switch_back = _FALSE;
\r
2378 /* Parsing information element */
\r
2379 for (j=FIXED_IE; j<parsing_length;) {
\r
2380 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
2382 switch (pIE->ElementID) {
\r
2383 case EID_SecondaryChnlOffset:
\r
2384 switch (*(pIE->data)) {
\r
2385 case EXTCHNL_OFFSET_UPPER:
\r
2386 pchsw_info->ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
\r
2389 case EXTCHNL_OFFSET_LOWER:
\r
2390 pchsw_info->ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
\r
2394 pchsw_info->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
\r
2398 case _LINK_ID_IE_:
\r
2400 case _CH_SWITCH_TIMING_:
\r
2401 ptdls_sta->ch_switch_time = (RTW_GET_LE16(pIE->data) >= TDLS_CH_SWITCH_TIME * 1000) ?
\r
2402 RTW_GET_LE16(pIE->data) : TDLS_CH_SWITCH_TIME * 1000;
\r
2403 ptdls_sta->ch_switch_timeout = (RTW_GET_LE16(pIE->data + 2) >= TDLS_CH_SWITCH_TIMEOUT * 1000) ?
\r
2404 RTW_GET_LE16(pIE->data + 2) : TDLS_CH_SWITCH_TIMEOUT * 1000;
\r
2405 DBG_871X("[TDLS] %s ch_switch_time:%d, ch_switch_timeout:%d\n"
\r
2406 , __FUNCTION__, RTW_GET_LE16(pIE->data), RTW_GET_LE16(pIE->data + 2));
\r
2411 j += (pIE->Length + 2);
\r
2414 rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk);
\r
2415 if (take_care_iqk == _TRUE) {
\r
2419 bw_mode = (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20;
\r
2420 central_chnl = rtw_get_center_ch(pchsw_info->off_ch_num, bw_mode, pchsw_info->ch_offset);
\r
2421 if (rtw_hal_ch_sw_iqk_info_search(padapter, central_chnl, bw_mode) < 0) {
\r
2422 if (!(pchsw_info->ch_sw_state & TDLS_CH_SWITCH_PREPARE_STATE))
\r
2423 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_PREPARE);
\r
2429 /* cancel ch sw monitor timer for responder */
\r
2430 if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE))
\r
2431 _cancel_timer_ex(&ptdls_sta->ch_sw_monitor_timer);
\r
2433 /* Todo: check status */
\r
2434 txmgmt.status_code = 0;
\r
2435 _rtw_memcpy(txmgmt.peer, psa, ETH_ALEN);
\r
2437 if (_rtw_memcmp(pchsw_info->addr, zaddr, ETH_ALEN) == _TRUE)
\r
2438 _rtw_memcpy(pchsw_info->addr, ptdls_sta->hwaddr, ETH_ALEN);
\r
2440 if (ATOMIC_READ(&pchsw_info->chsw_on) == _FALSE)
\r
2441 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_START);
\r
2443 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_RESP);
\r
2448 sint On_TDLS_Ch_Switch_Rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
2450 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
2451 struct sta_info *ptdls_sta= NULL;
\r
2452 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2453 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
2454 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
2456 sint parsing_length;
\r
2457 PNDIS_802_11_VARIABLE_IEs pIE;
\r
2459 u16 status_code, j, switch_time, switch_timeout;
\r
2460 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2461 int ret = _SUCCESS;
\r
2463 if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {
\r
2464 DBG_871X("[TDLS] Ignore %s since channel switch is not allowed\n", __func__);
\r
2468 psa = get_sa(ptr);
\r
2469 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
2471 if (ptdls_sta == NULL) {
\r
2472 DBG_871X("[%s] Direct Link Peer = "MAC_FMT" not found\n", __func__, MAC_ARG(psa));
\r
2476 /* If we receive Unsolicited TDLS Channel Switch Response when channel switch is running, */
\r
2477 /* we will go back to base channel and terminate this channel switch procedure */
\r
2478 if (ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE) {
\r
2479 if (pmlmeext->cur_channel != rtw_get_oper_ch(padapter)) {
\r
2480 DBG_871X("[TDLS] Rx unsolicited channel switch response\n");
\r
2481 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_TO_BASE_CHNL);
\r
2486 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
2487 parsing_length = ((union recv_frame *)precv_frame)->u.hdr.len
\r
2488 -prx_pkt_attrib->hdrlen
\r
2489 -prx_pkt_attrib->iv_len
\r
2490 -prx_pkt_attrib->icv_len
\r
2496 _rtw_memcpy(&status_code, ptr+2, 2);
\r
2498 if (status_code != 0) {
\r
2499 DBG_871X("[TDLS] %s status_code:%d\n", __func__, status_code);
\r
2500 pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE);
\r
2501 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_END);
\r
2506 /* Parsing information element */
\r
2507 for (j = FIXED_IE; j < parsing_length;) {
\r
2508 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
2510 switch (pIE->ElementID) {
\r
2511 case _LINK_ID_IE_:
\r
2513 case _CH_SWITCH_TIMING_:
\r
2514 _rtw_memcpy(&switch_time, pIE->data, 2);
\r
2515 if (switch_time > ptdls_sta->ch_switch_time)
\r
2516 _rtw_memcpy(&ptdls_sta->ch_switch_time, &switch_time, 2);
\r
2518 _rtw_memcpy(&switch_timeout, pIE->data + 2, 2);
\r
2519 if (switch_timeout > ptdls_sta->ch_switch_timeout)
\r
2520 _rtw_memcpy(&ptdls_sta->ch_switch_timeout, &switch_timeout, 2);
\r
2526 j += (pIE->Length + 2);
\r
2529 if ((pmlmeext->cur_channel == rtw_get_oper_ch(padapter)) &&
\r
2530 (pchsw_info->ch_sw_state & TDLS_WAIT_CH_RSP_STATE)) {
\r
2531 if (ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE)
\r
2532 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_TO_OFF_CHNL);
\r
2538 #endif /* CONFIG_TDLS_CH_SW */
\r
2541 void wfd_ie_tdls(_adapter * padapter, u8 *pframe, u32 *pktlen )
\r
2543 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
2544 struct wifi_display_info *pwfd_info = padapter->tdlsinfo.wfd_info;
\r
2545 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
\r
2548 if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
\r
2553 wfdie[ wfdielen++ ] = 0x50;
\r
2554 wfdie[ wfdielen++ ] = 0x6F;
\r
2555 wfdie[ wfdielen++ ] = 0x9A;
\r
2556 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
\r
2559 * Commented by Albert 20110825
\r
2560 * According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
\r
2561 * 1. WFD Device Information
\r
2562 * 2. Associated BSSID ( Optional )
\r
2563 * 3. Local IP Adress ( Optional )
\r
2566 /* WFD Device Information ATTR */
\r
2568 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
\r
2571 /* Note: In the WFD specification, the size of length field is 2. */
\r
2572 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
\r
2576 /* WFD device information */
\r
2577 /* available for WFD session + Preferred TDLS + WSD ( WFD Service Discovery ) */
\r
2578 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL
\r
2579 | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_WSD);
\r
2583 /* Session Management Control Port */
\r
2584 /* Default TCP port for RTSP messages is 554 */
\r
2585 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->tdls_rtsp_ctrlport);
2589 /* WFD Device Maximum Throughput */
\r
2590 /* 300Mbps is the maximum throughput */
\r
2591 RTW_PUT_BE16(wfdie + wfdielen, 300);
\r
2594 /* Associated BSSID ATTR */
\r
2596 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
\r
2599 /* Note: In the WFD specification, the size of length field is 2. */
\r
2600 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
\r
2604 /* Associated BSSID */
\r
2605 if (check_fwstate( pmlmepriv, _FW_LINKED) == _TRUE)
\r
2606 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
\r
2608 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
\r
2610 /* Local IP Address ATTR */
\r
2611 wfdie[ wfdielen++ ] = WFD_ATTR_LOCAL_IP_ADDR;
\r
2614 /* Note: In the WFD specification, the size of length field is 2. */
\r
2615 RTW_PUT_BE16(wfdie + wfdielen, 0x0005);
\r
2619 /* 0x01: Version1;IPv4 */
\r
2620 wfdie[ wfdielen++ ] = 0x01;
\r
2622 /* IPv4 Address */
\r
2623 _rtw_memcpy( wfdie + wfdielen, pwfd_info->ip_address, 4 );
\r
2626 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, pktlen);
\r
2629 #endif /* CONFIG_WFD */
\r
2631 void rtw_build_tdls_setup_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2633 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
2634 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2635 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2636 struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);
\r
2643 if (pattrib->encrypt) {
\r
2644 for (i=0;i<8;i++) {
\r
2645 time=rtw_get_current_time();
\r
2646 _rtw_memcpy(&ptdls_sta->SNonce[4*i], (u8 *)&time, 4);
\r
2650 pframe_head = pframe; /* For rtw_tdls_set_ht_cap() */
\r
2652 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2653 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2654 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2655 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2657 pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);
\r
2658 pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);
\r
2659 pframe = rtw_tdls_set_sup_ch(&(padapter->mlmeextpriv), pframe, pattrib);
\r
2660 pframe = rtw_tdls_set_sup_reg_class(pframe, pattrib);
\r
2662 if (pattrib->encrypt)
\r
2663 pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
\r
2665 pframe = rtw_tdls_set_ext_cap(pframe, pattrib);
\r
2667 if (pattrib->encrypt) {
\r
2668 pframe = rtw_tdls_set_ftie(ptxmgmt
\r
2672 , ptdls_sta->SNonce);
\r
2674 pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
\r
2677 #ifdef CONFIG_80211N_HT
\r
2678 /* Sup_reg_classes(optional) */
\r
2679 if (pregistrypriv->ht_enable == _TRUE)
\r
2680 pframe = rtw_tdls_set_ht_cap(padapter, pframe_head, pattrib);
\r
2683 pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);
\r
2685 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2687 if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))
\r
2688 pframe = rtw_tdls_set_qos_cap(pframe, pattrib);
\r
2690 #ifdef CONFIG_80211AC_VHT
\r
2691 if ((padapter->mlmepriv.htpriv.ht_option == _TRUE) && (pmlmeext->cur_channel > 14)
\r
2692 && REGSTY_IS_11AC_ENABLE(pregistrypriv)
\r
2693 && hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
\r
2694 && (!padapter->mlmepriv.country_ent || COUNTRY_CHPLAN_EN_11AC(padapter->mlmepriv.country_ent))
\r
2696 pframe = rtw_tdls_set_aid(padapter, pframe, pattrib);
\r
2697 pframe = rtw_tdls_set_vht_cap(padapter, pframe, pattrib);
\r
2702 if (padapter->wdinfo.wfd_tdls_enable == 1)
\r
2703 wfd_ie_tdls(padapter, pframe, &(pattrib->pktlen));
\r
2708 void rtw_build_tdls_setup_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2710 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
2711 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2712 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2713 struct sta_info *ptdls_sta;
\r
2714 u8 k; /* for random ANonce */
\r
2715 u8 *pftie=NULL, *ptimeout_ie = NULL, *plinkid_ie = NULL, *prsnie = NULL, *pftie_mic = NULL;
\r
2719 ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);
\r
2721 if (ptdls_sta == NULL)
\r
2722 DBG_871X("[%s] %d ptdls_sta is NULL\n", __FUNCTION__, __LINE__);
\r
2724 if (pattrib->encrypt && ptdls_sta != NULL) {
\r
2725 for (k=0;k<8;k++) {
\r
2726 time = rtw_get_current_time();
\r
2727 _rtw_memcpy(&ptdls_sta->ANonce[4*k], (u8*)&time, 4);
\r
2731 pframe_head = pframe;
\r
2733 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2734 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2735 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2736 pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
\r
2738 if (ptxmgmt->status_code != 0) {
\r
2739 DBG_871X("[%s] status_code:%04x \n", __FUNCTION__, ptxmgmt->status_code);
\r
2743 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2744 pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);
\r
2745 pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);
\r
2746 pframe = rtw_tdls_set_sup_ch(&(padapter->mlmeextpriv), pframe, pattrib);
\r
2747 pframe = rtw_tdls_set_sup_reg_class(pframe, pattrib);
\r
2749 if (pattrib->encrypt) {
\r
2751 pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _FALSE, ptdls_sta);
\r
2754 pframe = rtw_tdls_set_ext_cap(pframe, pattrib);
\r
2756 if (pattrib->encrypt) {
\r
2757 if (rtw_tdls_is_driver_setup(padapter) == _TRUE)
\r
2758 wpa_tdls_generate_tpk(padapter, ptdls_sta);
\r
2761 pftie_mic = pframe+4;
\r
2762 pframe = rtw_tdls_set_ftie(ptxmgmt
\r
2765 , ptdls_sta->ANonce
\r
2766 , ptdls_sta->SNonce);
\r
2768 ptimeout_ie = pframe;
\r
2769 pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _FALSE, ptdls_sta);
\r
2772 #ifdef CONFIG_80211N_HT
\r
2773 /* Sup_reg_classes(optional) */
\r
2774 if (pregistrypriv->ht_enable == _TRUE)
\r
2775 pframe = rtw_tdls_set_ht_cap(padapter, pframe_head, pattrib);
\r
2778 pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);
\r
2780 plinkid_ie = pframe;
\r
2781 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2783 /* Fill FTIE mic */
\r
2784 if (pattrib->encrypt && rtw_tdls_is_driver_setup(padapter) == _TRUE)
\r
2785 wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);
\r
2787 if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))
\r
2788 pframe = rtw_tdls_set_qos_cap(pframe, pattrib);
\r
2790 #ifdef CONFIG_80211AC_VHT
\r
2791 if ((padapter->mlmepriv.htpriv.ht_option == _TRUE) && (pmlmeext->cur_channel > 14)
\r
2792 && REGSTY_IS_11AC_ENABLE(pregistrypriv)
\r
2793 && hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
\r
2794 && (!padapter->mlmepriv.country_ent || COUNTRY_CHPLAN_EN_11AC(padapter->mlmepriv.country_ent))
\r
2796 pframe = rtw_tdls_set_aid(padapter, pframe, pattrib);
\r
2797 pframe = rtw_tdls_set_vht_cap(padapter, pframe, pattrib);
\r
2798 pframe = rtw_tdls_set_vht_op_mode_notify(padapter, pframe, pattrib, pmlmeext->cur_bwmode);
\r
2803 if (padapter->wdinfo.wfd_tdls_enable)
\r
2804 wfd_ie_tdls(padapter, pframe, &(pattrib->pktlen));
\r
2809 void rtw_build_tdls_setup_cfm_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2811 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
2812 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2813 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
2814 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2815 struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);
\r
2817 unsigned int ie_len;
\r
2819 u8 wmm_param_ele[24] = {0};
\r
2820 u8 *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL;
\r
2822 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2823 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2824 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2825 pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
\r
2826 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2828 if (ptxmgmt->status_code!=0)
\r
2831 if (pattrib->encrypt) {
\r
2833 pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
\r
2836 if (pattrib->encrypt) {
\r
2838 pftie_mic = pframe+4;
\r
2839 pframe = rtw_tdls_set_ftie(ptxmgmt
\r
2842 , ptdls_sta->ANonce
\r
2843 , ptdls_sta->SNonce);
\r
2845 ptimeout_ie = pframe;
\r
2846 pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
\r
2848 if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
\r
2849 /* Start TPK timer */
\r
2850 ptdls_sta->TPK_count=0;
\r
2851 _set_timer(&ptdls_sta->TPK_timer, ONE_SEC);
\r
2855 /* HT operation; todo */
\r
2857 plinkid_ie = pframe;
\r
2858 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2860 if (pattrib->encrypt && (rtw_tdls_is_driver_setup(padapter) == _TRUE))
\r
2861 wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);
\r
2863 if (ptdls_sta->qos_option == _TRUE)
\r
2864 pframe = rtw_tdls_set_wmm_params(padapter, pframe, pattrib);
\r
2866 #ifdef CONFIG_80211AC_VHT
\r
2867 if ((padapter->mlmepriv.htpriv.ht_option == _TRUE)
\r
2868 && (ptdls_sta->vhtpriv.vht_option == _TRUE) && (pmlmeext->cur_channel > 14)
\r
2869 && REGSTY_IS_11AC_ENABLE(pregistrypriv)
\r
2870 && hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
\r
2871 && (!padapter->mlmepriv.country_ent || COUNTRY_CHPLAN_EN_11AC(padapter->mlmepriv.country_ent))
\r
2873 pframe = rtw_tdls_set_vht_operation(padapter, pframe, pattrib, pmlmeext->cur_channel);
\r
2874 pframe = rtw_tdls_set_vht_op_mode_notify(padapter, pframe, pattrib, pmlmeext->cur_bwmode);
\r
2879 void rtw_build_tdls_teardown_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2881 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2882 struct sta_info *ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);
\r
2883 u8 *pftie = NULL, *pftie_mic = NULL, *plinkid_ie = NULL;
\r
2885 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2886 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2887 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2888 pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
\r
2890 if (pattrib->encrypt) {
\r
2892 pftie_mic = pframe + 4;
\r
2893 pframe = rtw_tdls_set_ftie(ptxmgmt
\r
2896 , ptdls_sta->ANonce
\r
2897 , ptdls_sta->SNonce);
\r
2900 plinkid_ie = pframe;
\r
2901 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
\r
2902 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2903 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
\r
2904 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2906 if (pattrib->encrypt && (rtw_tdls_is_driver_setup(padapter) == _TRUE))
\r
2907 wpa_tdls_teardown_ftie_mic(ptdls_sta->tpk.kck, plinkid_ie, ptxmgmt->status_code, 1, 4, pftie, pftie_mic);
\r
2910 void rtw_build_tdls_dis_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2912 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2914 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2915 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2916 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2917 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2918 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2922 void rtw_build_tdls_dis_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, u8 privacy)
\r
2924 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
2925 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2926 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2927 u8 *pframe_head, pktlen_index;
\r
2929 pktlen_index = pattrib->pktlen;
\r
2930 pframe_head = pframe;
\r
2932 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_PUBLIC);
\r
2933 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2934 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2935 pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);
\r
2937 pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);
\r
2939 pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);
\r
2942 pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, NULL);
\r
2944 pframe = rtw_tdls_set_ext_cap(pframe, pattrib);
\r
2947 pframe = rtw_tdls_set_ftie(ptxmgmt, pframe, pattrib, NULL, NULL);
\r
2948 pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, NULL);
\r
2951 #ifdef CONFIG_80211N_HT
\r
2952 if (pregistrypriv->ht_enable == _TRUE)
\r
2953 pframe = rtw_tdls_set_ht_cap(padapter, pframe_head - pktlen_index, pattrib);
\r
2956 pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);
\r
2957 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2962 void rtw_build_tdls_peer_traffic_indication_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2965 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2967 struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);
\r
2969 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2970 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2971 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2972 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2974 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
\r
2975 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2976 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
\r
2977 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2980 /* PU buffer status */
\r
2981 if (ptdls_sta->uapsd_bk & BIT(1))
\r
2983 if (ptdls_sta->uapsd_be & BIT(1))
\r
2985 if (ptdls_sta->uapsd_vi & BIT(1))
\r
2987 if (ptdls_sta->uapsd_vo & BIT(1))
\r
2989 pframe = rtw_set_ie(pframe, _PTI_BUFFER_STATUS_, 1, &AC_queue, &(pattrib->pktlen));
\r
2993 void rtw_build_tdls_peer_traffic_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2996 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2997 struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);
\r
2999 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
3000 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
3001 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
3002 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
3004 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
\r
3005 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
3006 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
\r
3007 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
3010 #ifdef CONFIG_TDLS_CH_SW
\r
3011 void rtw_build_tdls_ch_switch_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
3013 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
3014 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
3015 struct sta_priv *pstapriv = &padapter->stapriv;
\r
3016 struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
\r
3017 u16 switch_time = TDLS_CH_SWITCH_TIME * 1000, switch_timeout = TDLS_CH_SWITCH_TIMEOUT * 1000;
\r
3019 ptdls_sta->ch_switch_time=switch_time;
\r
3020 ptdls_sta->ch_switch_timeout=switch_timeout;
\r
3022 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
3023 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
3024 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
3025 pframe = rtw_tdls_set_target_ch(padapter, pframe, pattrib);
\r
3026 pframe = rtw_tdls_set_reg_class(pframe, pattrib, ptdls_sta);
\r
3028 if (ptdlsinfo->chsw_info.ch_offset != HAL_PRIME_CHNL_OFFSET_DONT_CARE) {
\r
3029 switch (ptdlsinfo->chsw_info.ch_offset) {
\r
3030 case HAL_PRIME_CHNL_OFFSET_LOWER:
\r
3031 pframe = rtw_tdls_set_second_channel_offset(pframe, pattrib, SCA);
\r
3033 case HAL_PRIME_CHNL_OFFSET_UPPER:
\r
3034 pframe = rtw_tdls_set_second_channel_offset(pframe, pattrib, SCB);
\r
3039 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
\r
3040 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
3041 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
\r
3042 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
3044 pframe = rtw_tdls_set_ch_sw(pframe, pattrib, ptdls_sta);
\r
3048 void rtw_build_tdls_ch_switch_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
3051 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
3052 struct sta_priv *pstapriv = &padapter->stapriv;
\r
3053 struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
\r
3055 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
3056 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
3057 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
3058 pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
\r
3060 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
\r
3061 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
3062 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
\r
3063 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
3065 pframe = rtw_tdls_set_ch_sw(pframe, pattrib, ptdls_sta);
\r
3070 void rtw_build_tunneled_probe_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
3073 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
3074 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
\r
3075 struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;
\r
3076 u8 category = RTW_WLAN_CATEGORY_P2P;
\r
3077 u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};
\r
3081 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
3082 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
3083 pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));
\r
3084 pframe = rtw_set_fixed_ie(pframe, 1, &(probe_req), &(pattrib->pktlen));
\r
3086 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
\r
3087 wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
\r
3088 pframe += wfdielen;
\r
3089 pattrib->pktlen += wfdielen;
\r
3090 } else if (!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE)) {
\r
3091 wfdielen = build_probe_req_wfd_ie(pbuddy_wdinfo, pframe);
\r
3092 pframe += wfdielen;
\r
3093 pattrib->pktlen += wfdielen;
\r
3098 void rtw_build_tunneled_probe_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
3101 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
3102 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
\r
3103 struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;
\r
3104 u8 category = RTW_WLAN_CATEGORY_P2P;
\r
3105 u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};
\r
3109 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
3110 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
3111 pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));
\r
3112 pframe = rtw_set_fixed_ie(pframe, 1, &(probe_rsp), &(pattrib->pktlen));
\r
3114 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
\r
3115 wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 1);
\r
3116 pframe += wfdielen;
\r
3117 pattrib->pktlen += wfdielen;
\r
3118 } else if (!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE)) {
\r
3119 wfdielen = build_probe_resp_wfd_ie(pbuddy_wdinfo, pframe, 1);
\r
3120 pframe += wfdielen;
\r
3121 pattrib->pktlen += wfdielen;
\r
3125 #endif /* CONFIG_WFD */
\r
3127 void _tdls_tpk_timer_hdl(void *FunctionContext)
\r
3129 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
3130 struct tdls_txmgmt txmgmt;
\r
3132 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
3133 ptdls_sta->TPK_count++;
\r
3134 /* TPK_timer expired in a second */
\r
3135 /* Retry timer should set at least 301 sec. */
\r
3136 if (ptdls_sta->TPK_count >= (ptdls_sta->TDLS_PeerKey_Lifetime - 3)) {
\r
3137 DBG_871X("[TDLS] %s, Re-Setup TDLS link with "MAC_FMT" since TPK lifetime expires!\n", __FUNCTION__, MAC_ARG(ptdls_sta->hwaddr));
\r
3138 ptdls_sta->TPK_count=0;
\r
3139 _rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);
\r
3140 issue_tdls_setup_req(ptdls_sta->padapter, &txmgmt, _FALSE);
\r
3143 _set_timer(&ptdls_sta->TPK_timer, ONE_SEC);
\r
3146 #ifdef CONFIG_TDLS_CH_SW
\r
3147 void _tdls_ch_switch_timer_hdl(void *FunctionContext)
\r
3149 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
3150 _adapter *padapter = ptdls_sta->padapter;
\r
3151 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
3153 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_END_TO_BASE_CHNL);
\r
3154 DBG_871X("[TDLS] %s, can't get traffic from op_ch:%d\n", __func__, rtw_get_oper_ch(padapter));
\r
3157 void _tdls_delay_timer_hdl(void *FunctionContext)
\r
3159 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
3160 _adapter *padapter = ptdls_sta->padapter;
\r
3161 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
3163 DBG_871X("[TDLS] %s, op_ch:%d, tdls_state:0x%08x\n", __func__, rtw_get_oper_ch(padapter), ptdls_sta->tdls_sta_state);
\r
3164 pchsw_info->delay_switch_back = _TRUE;
\r
3167 void _tdls_stay_on_base_chnl_timer_hdl(void *FunctionContext)
\r
3169 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
3170 _adapter *padapter = ptdls_sta->padapter;
\r
3171 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
3173 if (ptdls_sta != NULL) {
\r
3174 issue_tdls_ch_switch_req(padapter, ptdls_sta);
\r
3175 pchsw_info->ch_sw_state |= TDLS_WAIT_CH_RSP_STATE;
\r
3179 void _tdls_ch_switch_monitor_timer_hdl(void *FunctionContext)
\r
3181 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
3182 _adapter *padapter = ptdls_sta->padapter;
\r
3183 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
3185 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_END);
\r
3186 DBG_871X("[TDLS] %s, does not receive ch sw req\n", __func__);
\r
3191 void _tdls_handshake_timer_hdl(void *FunctionContext)
\r
3193 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
3194 _adapter *padapter = ptdls_sta->padapter;
\r
3195 struct tdls_txmgmt txmgmt;
\r
3197 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
3198 _rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);
\r
3199 txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
\r
3201 if (ptdls_sta != NULL) {
\r
3202 DBG_871X("[TDLS] Handshake time out\n");
\r
3203 if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)
\r
3205 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_TEARDOWN_STA);
\r
3209 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_TEARDOWN_STA_LOCALLY);
\r
3214 void _tdls_pti_timer_hdl(void *FunctionContext)
\r
3216 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
3217 _adapter *padapter = ptdls_sta->padapter;
\r
3218 struct tdls_txmgmt txmgmt;
\r
3220 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
3221 _rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);
\r
3222 txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_;
\r
3224 if (ptdls_sta != NULL) {
\r
3225 if (ptdls_sta->tdls_sta_state & TDLS_WAIT_PTR_STATE) {
\r
3226 DBG_871X("[TDLS] Doesn't receive PTR from peer dev:"MAC_FMT"; "
\r
3227 "Send TDLS Tear Down\n", MAC_ARG(ptdls_sta->hwaddr));
\r
3228 issue_tdls_teardown(padapter, &txmgmt, _FALSE);
\r
3233 void rtw_init_tdls_timer(_adapter *padapter, struct sta_info *psta)
\r
3235 psta->padapter=padapter;
\r
3236 _init_timer(&psta->TPK_timer, padapter->pnetdev, _tdls_tpk_timer_hdl, psta);
\r
3237 #ifdef CONFIG_TDLS_CH_SW
\r
3238 _init_timer(&psta->ch_sw_timer, padapter->pnetdev, _tdls_ch_switch_timer_hdl, psta);
\r
3239 _init_timer(&psta->delay_timer, padapter->pnetdev, _tdls_delay_timer_hdl, psta);
\r
3240 _init_timer(&psta->stay_on_base_chnl_timer, padapter->pnetdev, _tdls_stay_on_base_chnl_timer_hdl, psta);
\r
3241 _init_timer(&psta->ch_sw_monitor_timer, padapter->pnetdev, _tdls_ch_switch_monitor_timer_hdl, psta);
\r
3243 _init_timer(&psta->handshake_timer, padapter->pnetdev, _tdls_handshake_timer_hdl, psta);
\r
3244 _init_timer(&psta->pti_timer, padapter->pnetdev, _tdls_pti_timer_hdl, psta);
\r
3247 void rtw_free_tdls_timer(struct sta_info *psta)
\r
3249 _cancel_timer_ex(&psta->TPK_timer);
\r
3250 #ifdef CONFIG_TDLS_CH_SW
\r
3251 _cancel_timer_ex(&psta->ch_sw_timer);
\r
3252 _cancel_timer_ex(&psta->delay_timer);
\r
3253 _cancel_timer_ex(&psta->stay_on_base_chnl_timer);
\r
3254 _cancel_timer_ex(&psta->ch_sw_monitor_timer);
\r
3256 _cancel_timer_ex(&psta->handshake_timer);
\r
3257 _cancel_timer_ex(&psta->pti_timer);
\r
3260 u8 update_sgi_tdls(_adapter *padapter, struct sta_info *psta)
\r
3262 return query_ra_short_GI(psta);
\r
3265 u32 update_mask_tdls(_adapter *padapter, struct sta_info *psta)
\r
3267 unsigned char sta_band = 0;
\r
3268 unsigned int tx_ra_bitmap=0;
\r
3269 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
3270 WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
\r
3272 rtw_hal_update_sta_rate_mask(padapter, psta);
\r
3273 tx_ra_bitmap = psta->ra_mask;
\r
3275 if (pcur_network->Configuration.DSConfig > 14) {
\r
3276 if (tx_ra_bitmap & 0xffff000)
\r
3277 sta_band |= WIRELESS_11_5N | WIRELESS_11A;
\r
3279 sta_band |= WIRELESS_11A;
\r
3281 if (tx_ra_bitmap & 0xffff000)
\r
3282 sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
\r
3283 else if (tx_ra_bitmap & 0xff0)
\r
3284 sta_band |= WIRELESS_11G |WIRELESS_11B;
\r
3286 sta_band |= WIRELESS_11B;
\r
3289 psta->wireless_mode = sta_band;
\r
3291 psta->raid = rtw_hal_networktype_to_raid(padapter,psta);
\r
3292 tx_ra_bitmap |= ((psta->raid<<28)&0xf0000000);
\r
3293 return tx_ra_bitmap;
\r
3296 int rtw_tdls_is_driver_setup(_adapter *padapter)
\r
3298 return padapter->tdlsinfo.driver_setup;
\r
3301 const char * rtw_tdls_action_txt(enum TDLS_ACTION_FIELD action)
\r
3304 case TDLS_SETUP_REQUEST:
\r
3305 return "TDLS_SETUP_REQUEST";
\r
3306 case TDLS_SETUP_RESPONSE:
\r
3307 return "TDLS_SETUP_RESPONSE";
\r
3308 case TDLS_SETUP_CONFIRM:
\r
3309 return "TDLS_SETUP_CONFIRM";
\r
3310 case TDLS_TEARDOWN:
\r
3311 return "TDLS_TEARDOWN";
\r
3312 case TDLS_PEER_TRAFFIC_INDICATION:
\r
3313 return "TDLS_PEER_TRAFFIC_INDICATION";
\r
3314 case TDLS_CHANNEL_SWITCH_REQUEST:
\r
3315 return "TDLS_CHANNEL_SWITCH_REQUEST";
\r
3316 case TDLS_CHANNEL_SWITCH_RESPONSE:
\r
3317 return "TDLS_CHANNEL_SWITCH_RESPONSE";
\r
3318 case TDLS_PEER_PSM_REQUEST:
\r
3319 return "TDLS_PEER_PSM_REQUEST";
\r
3320 case TDLS_PEER_PSM_RESPONSE:
\r
3321 return "TDLS_PEER_PSM_RESPONSE";
\r
3322 case TDLS_PEER_TRAFFIC_RESPONSE:
\r
3323 return "TDLS_PEER_TRAFFIC_RESPONSE";
\r
3324 case TDLS_DISCOVERY_REQUEST:
\r
3325 return "TDLS_DISCOVERY_REQUEST";
\r
3326 case TDLS_DISCOVERY_RESPONSE:
\r
3327 return "TDLS_DISCOVERY_RESPONSE";
\r
3333 #endif /* CONFIG_TDLS */
\r