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 = 0;
\r
56 ptdlsinfo->chsw_info.cur_time = 0;
\r
57 ptdlsinfo->chsw_info.delay_switch_back = _FALSE;
\r
58 ptdlsinfo->chsw_info.dump_stack = _FALSE;
\r
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
67 #endif /* ONFIG_WFD */
\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 int _issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
\r
133 struct xmit_frame *pmgntframe;
\r
134 struct pkt_attrib *pattrib;
\r
135 unsigned char *pframe;
\r
136 struct rtw_ieee80211_hdr *pwlanhdr;
\r
137 unsigned short *fctrl, *qc;
\r
138 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
139 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
140 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
142 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
145 pattrib = &pmgntframe->attrib;
\r
146 update_mgntframe_attrib(padapter, pattrib);
\r
148 pattrib->hdrlen +=2;
\r
149 pattrib->qos_en = _TRUE;
\r
151 pattrib->ack_policy = 0;
\r
152 pattrib->mdata = 0;
\r
153 pattrib->retry_ctrl = _FALSE;
\r
155 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
\r
157 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
\r
158 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
\r
160 fctrl = &(pwlanhdr->frame_ctl);
\r
166 qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
\r
168 SetPriority(qc, 7); /* Set priority to VO */
\r
170 SetEOSP(qc, pattrib->eosp);
\r
172 SetAckpolicy(qc, pattrib->ack_policy);
\r
174 _rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
\r
175 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
\r
176 _rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
\r
178 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
\r
179 pmlmeext->mgnt_seq++;
\r
180 SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
\r
182 pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
\r
183 pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
\r
185 pattrib->last_txcmdsz = pattrib->pktlen;
\r
188 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
\r
190 dump_mgntframe(padapter, pmgntframe);
\r
198 int issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
\r
202 u32 start = rtw_get_current_time();
\r
203 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
204 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
207 psta = rtw_get_stainfo(&padapter->stapriv, da);
\r
210 rtw_hal_macid_sleep(padapter, psta->mac_id);
\r
212 rtw_hal_macid_wakeup(padapter, psta->mac_id);
\r
214 DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",
\r
215 FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup");
\r
221 ret = _issue_nulldata_to_TDLS_peer_STA(padapter, da, power_mode, wait_ms>0 ? _TRUE : _FALSE);
\r
225 if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
\r
228 if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
\r
229 rtw_msleep_os(wait_ms);
\r
231 } while ((i < try_cnt) && (ret==_FAIL || wait_ms==0));
\r
233 if (ret != _FAIL) {
\r
235 #ifndef DBG_XMIT_ACK
\r
240 if (try_cnt && wait_ms) {
\r
242 DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
\r
243 FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
\r
244 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
\r
246 DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
\r
247 FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
\r
248 ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
\r
254 void free_tdls_sta(_adapter *padapter, struct sta_info *ptdls_sta)
\r
256 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
257 struct sta_priv *pstapriv = &padapter->stapriv;
\r
260 /* free peer sta_info */
\r
261 _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
262 if (ptdlsinfo->sta_cnt != 0)
\r
263 ptdlsinfo->sta_cnt--;
\r
264 _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
\r
265 /* -2: AP + BC/MC sta, -4: default key */
\r
266 if (ptdlsinfo->sta_cnt < MAX_ALLOWED_TDLS_STA_NUM) {
\r
267 ptdlsinfo->sta_maximum = _FALSE;
\r
268 _rtw_memset( &ptdlsinfo->ss_record, 0x00, sizeof(struct tdls_ss_record) );
\r
272 rtw_clearstakey_cmd(padapter, ptdls_sta, _TRUE);
\r
274 if (ptdlsinfo->sta_cnt == 0) {
\r
275 rtw_tdls_cmd(padapter, NULL, TDLS_RS_RCR);
\r
276 ptdlsinfo->link_established = _FALSE;
\r
279 DBG_871X("Remain tdls sta:%02x\n", ptdlsinfo->sta_cnt);
\r
281 rtw_free_stainfo(padapter, ptdls_sta);
\r
286 /* TDLS encryption(if needed) will always be CCMP */
\r
287 void rtw_tdls_set_key(_adapter *padapter, struct sta_info *ptdls_sta)
\r
289 ptdls_sta->dot118021XPrivacy=_AES_;
\r
290 rtw_setstakey_cmd(padapter, ptdls_sta, TDLS_KEY, _TRUE);
\r
293 void rtw_tdls_process_ht_cap(_adapter *padapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)
\r
295 /* Save HT capabilities in the sta object */
\r
296 _rtw_memset(&ptdls_sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
\r
297 if (data && Length >= sizeof(struct rtw_ieee80211_ht_cap)) {
\r
298 ptdls_sta->flags |= WLAN_STA_HT;
\r
299 ptdls_sta->flags |= WLAN_STA_WME;
\r
301 _rtw_memcpy(&ptdls_sta->htpriv.ht_cap, data, sizeof(struct rtw_ieee80211_ht_cap));
\r
303 ptdls_sta->flags &= ~WLAN_STA_HT;
\r
305 if (ptdls_sta->flags & WLAN_STA_HT) {
\r
306 if (padapter->registrypriv.ht_enable == _TRUE) {
\r
307 ptdls_sta->htpriv.ht_option = _TRUE;
\r
308 ptdls_sta->qos_option = _TRUE;
\r
310 ptdls_sta->htpriv.ht_option = _FALSE;
\r
311 ptdls_sta->qos_option = _FALSE;
\r
315 /* HT related cap */
\r
316 if (ptdls_sta->htpriv.ht_option) {
\r
317 /* Check if sta supports rx ampdu */
\r
318 if (padapter->registrypriv.ampdu_enable == 1)
\r
319 ptdls_sta->htpriv.ampdu_enable = _TRUE;
\r
321 /* Check if sta support s Short GI 20M */
\r
322 if (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
\r
323 ptdls_sta->htpriv.sgi_20m = _TRUE;
\r
325 /* Check if sta support s Short GI 40M */
\r
326 if (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))
\r
327 ptdls_sta->htpriv.sgi_40m = _TRUE;
\r
329 /* Bwmode would still followed AP's setting */
\r
330 if (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) {
\r
331 if (padapter->mlmeextpriv.cur_bwmode >= CHANNEL_WIDTH_40)
\r
332 ptdls_sta->bw_mode = CHANNEL_WIDTH_40;
\r
333 ptdls_sta->htpriv.ch_offset = padapter->mlmeextpriv.cur_ch_offset;
\r
339 u8 *rtw_tdls_set_ht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
341 rtw_ht_use_default_setting(padapter);
\r
343 rtw_restructure_ht_ie(padapter, NULL, pframe, 0, &(pattrib->pktlen), padapter->mlmeextpriv.cur_channel);
\r
345 return pframe + pattrib->pktlen;
\r
348 u8 *rtw_tdls_set_sup_ch(struct mlme_ext_priv *pmlmeext, u8 *pframe, struct pkt_attrib *pattrib)
\r
350 u8 sup_ch[ 30 * 2 ] = { 0x00 }, ch_set_idx = 0; //For supported channel
\r
351 u8 ch_24g = 0, b1 = 0, b4 = 0;
\r
352 u8 bit_table = 0, sup_ch_idx = 0;
\r
355 if (pmlmeext->channel_set[ch_set_idx].ChannelNum >= 1 &&
\r
356 pmlmeext->channel_set[ch_set_idx].ChannelNum <= 14)
\r
357 ch_24g = 1; /* 2.4 G channels */
\r
358 else if (pmlmeext->channel_set[ch_set_idx].ChannelNum >= 36 &&
\r
359 pmlmeext->channel_set[ch_set_idx].ChannelNum <= 48)
\r
360 b1 = 1; /* 5 G band1 */
\r
361 else if (pmlmeext->channel_set[ch_set_idx].ChannelNum >= 149 &&
\r
362 pmlmeext->channel_set[ch_set_idx].ChannelNum <= 165)
\r
363 b4 = 1; /* 5 G band4 */
\r
365 ch_set_idx++; /* We don't support DFS channels. */
\r
369 sup_ch_idx = (ch_24g + b1 + b4 - 1) * 2;
\r
370 if (sup_ch_idx >= 0) {
\r
371 if (sup_ch[sup_ch_idx] == 0)
\r
372 sup_ch[sup_ch_idx] = pmlmeext->channel_set[ch_set_idx].ChannelNum;
\r
373 sup_ch[sup_ch_idx+1]++; //Number of channel
\r
377 } while (pmlmeext->channel_set[ch_set_idx].ChannelNum != 0 && ch_set_idx < MAX_CHANNEL_NUM);
\r
379 return(rtw_set_ie(pframe, _SUPPORTED_CH_IE_, sup_ch_idx+2, sup_ch, &(pattrib->pktlen)));
\r
382 u8 *rtw_tdls_set_rsnie(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, int init, struct sta_info *ptdls_sta)
\r
387 if (ptxmgmt->len > 0)
\r
388 p = rtw_get_ie(ptxmgmt->buf, _RSN_IE_2_, &len, ptxmgmt->len);
\r
391 return rtw_set_ie(pframe, _RSN_IE_2_, len, p+2, &(pattrib->pktlen));
\r
394 return rtw_set_ie(pframe, _RSN_IE_2_, sizeof(TDLS_RSNIE), TDLS_RSNIE, &(pattrib->pktlen));
\r
396 return rtw_set_ie(pframe, _RSN_IE_2_, sizeof(ptdls_sta->TDLS_RSNIE), ptdls_sta->TDLS_RSNIE, &(pattrib->pktlen));
\r
399 u8 *rtw_tdls_set_ext_cap(u8 *pframe, struct pkt_attrib *pattrib)
\r
401 return rtw_set_ie(pframe, _EXT_CAP_IE_ , sizeof(TDLS_EXT_CAPIE), TDLS_EXT_CAPIE, &(pattrib->pktlen));
\r
404 u8 *rtw_tdls_set_qos_cap(u8 *pframe, struct pkt_attrib *pattrib)
\r
406 return rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(TDLS_WMMIE), TDLS_WMMIE, &(pattrib->pktlen));
\r
409 u8 *rtw_tdls_set_ftie(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, u8 *ANonce, u8 *SNonce)
\r
411 struct wpa_tdls_ftie FTIE = {0};
\r
415 if (ptxmgmt->len > 0)
\r
416 p = rtw_get_ie(ptxmgmt->buf, _FTIE_, &len, ptxmgmt->len);
\r
419 return rtw_set_ie(pframe, _FTIE_, len, p+2, &(pattrib->pktlen));
\r
421 if (ANonce != NULL)
\r
422 _rtw_memcpy(FTIE.Anonce, ANonce, WPA_NONCE_LEN);
\r
423 if (SNonce != NULL)
\r
424 _rtw_memcpy(FTIE.Snonce, SNonce, WPA_NONCE_LEN);
\r
425 return rtw_set_ie(pframe, _FTIE_ , 82, (u8 *)FTIE.mic_ctrl, &(pattrib->pktlen));
\r
429 u8 *rtw_tdls_set_timeout_interval(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, int init, struct sta_info *ptdls_sta)
\r
431 u8 timeout_itvl[5]; /* set timeout interval to maximum value */
\r
432 u32 timeout_interval= TPK_RESEND_COUNT;
\r
436 if (ptxmgmt->len > 0)
\r
437 p = rtw_get_ie(ptxmgmt->buf, _TIMEOUT_ITVL_IE_, &len, ptxmgmt->len);
\r
440 return rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, len, p+2, &(pattrib->pktlen));
\r
442 /* Timeout interval */
\r
443 timeout_itvl[0]=0x02;
\r
445 _rtw_memcpy(timeout_itvl+1, &timeout_interval, 4);
\r
447 _rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);
\r
449 return rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
\r
453 u8 *rtw_tdls_set_bss_coexist(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
457 if (padapter->mlmepriv.num_FortyMHzIntolerant > 0)
\r
458 iedata |= BIT(2); /* 20 MHz BSS Width Request */
\r
460 /* Information Bit should be set by TDLS test plan 5.9 */
\r
462 return rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
\r
465 u8 *rtw_tdls_set_payload_type(u8 *pframe, struct pkt_attrib *pattrib)
\r
467 u8 payload_type = 0x02;
\r
468 return rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
\r
471 u8 *rtw_tdls_set_category(u8 *pframe, struct pkt_attrib *pattrib, u8 category)
\r
473 return rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
476 u8 *rtw_tdls_set_action(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)
\r
478 return rtw_set_fixed_ie(pframe, 1, &(ptxmgmt->action_code), &(pattrib->pktlen));
\r
481 u8 *rtw_tdls_set_status_code(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)
\r
483 return rtw_set_fixed_ie(pframe, 2, (u8 *)&(ptxmgmt->status_code), &(pattrib->pktlen));
\r
486 u8 *rtw_tdls_set_dialog(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)
\r
488 u8 dialogtoken = 1;
\r
489 if (ptxmgmt->dialog_token)
\r
490 return rtw_set_fixed_ie(pframe, 1, &(ptxmgmt->dialog_token), &(pattrib->pktlen));
\r
492 return rtw_set_fixed_ie(pframe, 1, &(dialogtoken), &(pattrib->pktlen));
\r
495 u8 *rtw_tdls_set_reg_class(u8 *pframe, struct pkt_attrib *pattrib, struct sta_info *ptdls_sta)
\r
498 return rtw_set_fixed_ie(pframe, 1, &(reg_class), &(pattrib->pktlen));
\r
501 u8 *rtw_tdls_set_capability(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
503 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
504 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
\r
505 u8 cap_from_ie[2] = {0};
\r
507 _rtw_memcpy(cap_from_ie, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
\r
509 return rtw_set_fixed_ie(pframe, 2, cap_from_ie, &(pattrib->pktlen));
\r
512 u8 *rtw_tdls_set_supported_rate(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
514 u8 bssrate[NDIS_802_11_LENGTH_RATES_EX];
\r
515 int bssrate_len = 0;
\r
516 u8 more_supportedrates = 0;
\r
518 rtw_set_supported_rate(bssrate, padapter->registrypriv.wireless_mode);
\r
519 bssrate_len = rtw_get_rateset_len(bssrate);
\r
521 if (bssrate_len > 8) {
\r
522 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
\r
523 more_supportedrates = 1;
\r
525 pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
\r
528 /* extended supported rates */
\r
529 if (more_supportedrates == 1) {
\r
530 pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
\r
536 u8 *rtw_tdls_set_sup_reg_class(u8 *pframe, struct pkt_attrib *pattrib)
\r
538 return rtw_set_ie(pframe, _SRC_IE_ , sizeof(TDLS_SRC), TDLS_SRC, &(pattrib->pktlen));
\r
541 u8 *rtw_tdls_set_linkid(u8 *pframe, struct pkt_attrib *pattrib, u8 init)
\r
543 u8 link_id_addr[18] = {0};
\r
544 if (init == _TRUE) {
\r
545 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
546 _rtw_memcpy((link_id_addr+6), pattrib->src, 6);
\r
547 _rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
\r
549 _rtw_memcpy(link_id_addr, pattrib->ra, 6);
\r
550 _rtw_memcpy((link_id_addr+6), pattrib->dst, 6);
\r
551 _rtw_memcpy((link_id_addr+12), pattrib->src, 6);
\r
553 return rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
\r
556 #ifdef CONFIG_TDLS_CH_SW
\r
557 u8 *rtw_tdls_set_target_ch(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
560 if (padapter->tdlsinfo.chsw_info.off_ch_num)
\r
561 return rtw_set_fixed_ie(pframe, 1, &(padapter->tdlsinfo.chsw_info.off_ch_num), &(pattrib->pktlen));
\r
563 return rtw_set_fixed_ie(pframe, 1, &(target_ch), &(pattrib->pktlen));
\r
566 u8 *rtw_tdls_set_ch_sw(u8 *pframe, struct pkt_attrib *pattrib, struct sta_info *ptdls_sta)
\r
568 u8 ch_switch_timing[4] = {0};
\r
569 u16 switch_time = (ptdls_sta->ch_switch_time >= CH_SWITCH_TIME * 1000) ?
\r
570 ptdls_sta->ch_switch_time : CH_SWITCH_TIME;
\r
571 u16 switch_timeout = (ptdls_sta->ch_switch_timeout >= CH_SWITCH_TIMEOUT * 1000) ?
\r
572 ptdls_sta->ch_switch_timeout : CH_SWITCH_TIMEOUT;
\r
574 _rtw_memcpy(ch_switch_timing, &switch_time, 2);
\r
575 _rtw_memcpy(ch_switch_timing + 2, &switch_timeout, 2);
\r
577 return rtw_set_ie(pframe, _CH_SWITCH_TIMING_, 4, ch_switch_timing, &(pattrib->pktlen));
\r
581 u8 *rtw_tdls_set_wmm_params(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
\r
583 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
584 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
585 u8 wmm_param_ele[24] = {0};
\r
587 if (&pmlmeinfo->WMM_param) {
\r
588 _rtw_memcpy(wmm_param_ele, WMM_PARA_OUI, 6);
\r
589 if (_rtw_memcmp(&pmlmeinfo->WMM_param, &wmm_param_ele[6], 18) == _TRUE)
\r
590 /* Use default WMM Param */
\r
591 _rtw_memcpy(wmm_param_ele + 6, (u8 *)&TDLS_WMM_PARAM_IE, sizeof(TDLS_WMM_PARAM_IE));
\r
593 _rtw_memcpy(wmm_param_ele + 6, (u8 *)&pmlmeinfo->WMM_param, sizeof(pmlmeinfo->WMM_param));
\r
594 return rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 24, wmm_param_ele, &(pattrib->pktlen));
\r
601 void rtw_tdls_process_wfd_ie(struct tdls_info *ptdlsinfo, u8 *ptr, u8 length)
\r
603 u8 wfd_ie[ 128 ] = { 0x00 };
\r
605 u32 wfd_offset = 0;
\r
606 /* Try to get the TCP port information when receiving the negotiation response. */
\r
609 wfd_offset = rtw_get_wfd_ie( ptr + wfd_offset, length - wfd_offset, wfd_ie, &wfd_ielen );
\r
610 while (wfd_offset) {
\r
611 u8 attr_content[ 10 ] = { 0x00 };
\r
612 u32 attr_contentlen = 0;
\r
615 DBG_871X( "[%s] WFD IE Found!!\n", __FUNCTION__ );
\r
616 rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, attr_content, &attr_contentlen);
\r
617 if (attr_contentlen) {
\r
618 ptdlsinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );
\r
619 DBG_871X( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, ptdlsinfo->wfd_info->peer_rtsp_ctrlport );
\r
622 _rtw_memset( attr_content, 0x00, 10);
\r
623 attr_contentlen = 0;
\r
624 rtw_get_wfd_attr_content( wfd_ie, wfd_ielen, WFD_ATTR_LOCAL_IP_ADDR, attr_content, &attr_contentlen);
\r
625 if (attr_contentlen) {
\r
626 _rtw_memcpy(ptdlsinfo->wfd_info->peer_ip_address, ( attr_content + 1 ), 4);
\r
627 DBG_871X( "[%s] Peer IP = %02u.%02u.%02u.%02u \n", __FUNCTION__,
\r
628 ptdlsinfo->wfd_info->peer_ip_address[0], ptdlsinfo->wfd_info->peer_ip_address[1],
\r
629 ptdlsinfo->wfd_info->peer_ip_address[2], ptdlsinfo->wfd_info->peer_ip_address[3]);
\r
631 wfd_offset = rtw_get_wfd_ie( ptr + wfd_offset, length - wfd_offset, wfd_ie, &wfd_ielen );
\r
635 int issue_tunneled_probe_req(_adapter *padapter)
\r
637 struct xmit_frame *pmgntframe;
\r
638 struct pkt_attrib *pattrib;
\r
639 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
640 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
641 u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
\r
642 struct tdls_txmgmt txmgmt;
\r
645 DBG_871X("[%s]\n", __FUNCTION__);
\r
647 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
648 txmgmt.action_code = TUNNELED_PROBE_REQ;
\r
650 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
653 pattrib = &pmgntframe->attrib;
\r
655 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
656 pattrib->ether_type = 0x890d;
\r
658 _rtw_memcpy(pattrib->dst, baddr, ETH_ALEN);
\r
659 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
660 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
661 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
663 update_tdls_attrib(padapter, pattrib);
\r
664 pattrib->qsel = pattrib->priority;
\r
665 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {
\r
666 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
667 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
670 dump_mgntframe(padapter, pmgntframe);
\r
677 int issue_tunneled_probe_rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
679 struct xmit_frame *pmgntframe;
\r
680 struct pkt_attrib *pattrib;
\r
681 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
682 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
683 struct tdls_txmgmt txmgmt;
\r
686 DBG_871X("[%s]\n", __FUNCTION__);
\r
688 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
689 txmgmt.action_code = TUNNELED_PROBE_RSP;
\r
691 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
694 pattrib = &pmgntframe->attrib;
\r
696 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
697 pattrib->ether_type = 0x890d;
\r
699 _rtw_memcpy(pattrib->dst, precv_frame->u.hdr.attrib.src, ETH_ALEN);
\r
700 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
701 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
702 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
704 update_tdls_attrib(padapter, pattrib);
\r
705 pattrib->qsel = pattrib->priority;
\r
706 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {
\r
707 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
708 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
711 dump_mgntframe(padapter, pmgntframe);
\r
717 #endif /* CONFIG_WFD */
\r
719 int issue_tdls_setup_req(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, int wait_ack)
\r
721 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
722 struct xmit_frame *pmgntframe;
\r
723 struct pkt_attrib *pattrib;
\r
724 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
725 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
726 struct sta_priv *pstapriv = &padapter->stapriv;
\r
727 struct sta_info *ptdls_sta= NULL;
\r
730 /* Retry timer should be set at least 301 sec, using TPK_count counting 301 times. */
\r
731 u32 timeout_interval= TPK_RESEND_COUNT;
\r
733 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
735 ptxmgmt->action_code = TDLS_SETUP_REQUEST;
\r
736 if (ptdlsinfo->ap_prohibited == _TRUE)
\r
739 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
742 pattrib = &pmgntframe->attrib;
\r
743 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
744 pattrib->ether_type = 0x890d;
\r
746 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
747 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
748 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
749 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
751 update_tdls_attrib(padapter, pattrib);
\r
753 /* init peer sta_info */
\r
754 ptdls_sta = rtw_get_stainfo(pstapriv, ptxmgmt->peer);
\r
755 if (ptdls_sta == NULL) {
\r
756 ptdls_sta = rtw_alloc_stainfo(pstapriv, ptxmgmt->peer);
\r
757 if (ptdls_sta == NULL) {
\r
758 DBG_871X("[%s] rtw_alloc_stainfo fail\n", __FUNCTION__);
\r
759 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
760 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
765 if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
\r
766 ptdlsinfo->sta_cnt++;
\r
768 if (ptdlsinfo->sta_cnt == MAX_ALLOWED_TDLS_STA_NUM)
\r
769 ptdlsinfo->sta_maximum = _TRUE;
\r
771 ptdls_sta->tdls_sta_state |= TDLS_RESPONDER_STATE;
\r
773 if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
\r
774 ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
\r
775 _set_timer(&ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);
\r
778 pattrib->qsel = pattrib->priority;
\r
780 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) !=_SUCCESS) {
\r
781 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
782 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
787 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
\r
789 dump_mgntframe(padapter, pmgntframe);
\r
798 int _issue_tdls_teardown(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 wait_ack)
\r
800 struct xmit_frame *pmgntframe;
\r
801 struct pkt_attrib *pattrib;
\r
802 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
803 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
804 struct sta_priv *pstapriv = &padapter->stapriv;
\r
805 struct sta_info *ptdls_sta=NULL;
\r
809 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
811 ptxmgmt->action_code = TDLS_TEARDOWN;
\r
812 ptdls_sta = rtw_get_stainfo(pstapriv, ptxmgmt->peer);
\r
813 if (ptdls_sta == NULL) {
\r
814 DBG_871X("Np tdls_sta for tearing down\n");
\r
818 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
821 rtw_set_scan_deny(padapter, 550);
\r
823 rtw_scan_abort(padapter);
\r
824 #ifdef CONFIG_CONCURRENT_MODE
\r
825 if (rtw_buddy_adapter_up(padapter))
\r
826 rtw_scan_abort(padapter->pbuddy_adapter);
\r
827 #endif /* CONFIG_CONCURRENT_MODE */
\r
829 pattrib = &pmgntframe->attrib;
\r
831 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
832 pattrib->ether_type = 0x890d;
\r
834 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
835 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
836 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
837 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
839 update_tdls_attrib(padapter, pattrib);
\r
840 pattrib->qsel = pattrib->priority;
\r
841 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
\r
842 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
843 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
847 if (rtw_tdls_is_driver_setup(padapter) == _TRUE)
\r
848 if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)
\r
849 if (pattrib->encrypt)
\r
850 _cancel_timer_ex(&ptdls_sta->TPK_timer);
\r
853 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
\r
855 dump_mgntframe(padapter, pmgntframe);
\r
859 if (ret == _SUCCESS && rtw_tdls_is_driver_setup(padapter))
\r
860 rtw_tdls_cmd(padapter, ptxmgmt->peer, TDLS_TEAR_STA);
\r
867 int issue_tdls_teardown(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 wait_ack)
\r
871 ret = _issue_tdls_teardown(padapter, ptxmgmt, wait_ack);
\r
872 if ((ptxmgmt->status_code == _RSON_TDLS_TEAR_UN_RSN_) && (ret == _FAIL)) {
\r
873 /* Change status code and send teardown again via AP */
\r
874 ptxmgmt->status_code = _RSON_TDLS_TEAR_TOOFAR_;
\r
875 ret = _issue_tdls_teardown(padapter, ptxmgmt, wait_ack);
\r
881 int issue_tdls_dis_req(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)
\r
883 struct xmit_frame *pmgntframe;
\r
884 struct pkt_attrib *pattrib;
\r
885 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
886 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
889 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
891 ptxmgmt->action_code = TDLS_DISCOVERY_REQUEST;
\r
892 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
895 pattrib = &pmgntframe->attrib;
\r
896 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
897 pattrib->ether_type = 0x890d;
\r
899 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
900 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
901 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
902 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
904 update_tdls_attrib(padapter, pattrib);
\r
905 pattrib->qsel = pattrib->priority;
\r
906 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
\r
907 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
908 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
911 dump_mgntframe(padapter, pmgntframe);
\r
912 DBG_871X("issue tdls dis req\n");
\r
920 int issue_tdls_setup_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)
\r
922 struct xmit_frame *pmgntframe;
\r
923 struct pkt_attrib *pattrib;
\r
924 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
927 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
929 ptxmgmt->action_code = TDLS_SETUP_RESPONSE;
\r
930 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
933 pattrib = &pmgntframe->attrib;
\r
934 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
935 pattrib->ether_type = 0x890d;
\r
937 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
938 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
939 _rtw_memcpy(pattrib->ra, get_bssid(&(padapter->mlmepriv)), ETH_ALEN);
\r
940 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
942 update_tdls_attrib(padapter, pattrib);
\r
943 pattrib->qsel = pattrib->priority;
\r
944 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
\r
945 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
946 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
950 dump_mgntframe(padapter, pmgntframe);
\r
959 int issue_tdls_setup_cfm(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)
\r
961 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
962 struct xmit_frame *pmgntframe;
\r
963 struct pkt_attrib *pattrib;
\r
964 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
967 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
969 ptxmgmt->action_code = TDLS_SETUP_CONFIRM;
\r
970 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
973 pattrib = &pmgntframe->attrib;
\r
974 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
975 pattrib->ether_type = 0x890d;
\r
977 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
978 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
979 _rtw_memcpy(pattrib->ra, get_bssid(&padapter->mlmepriv), ETH_ALEN);
\r
980 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
982 update_tdls_attrib(padapter, pattrib);
\r
983 pattrib->qsel = pattrib->priority;
\r
984 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
\r
985 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
986 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
990 dump_mgntframe(padapter, pmgntframe);
\r
999 /* TDLS Discovery Response frame is a management action frame */
\r
1000 int issue_tdls_dis_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 privacy)
\r
1002 struct xmit_frame *pmgntframe;
\r
1003 struct pkt_attrib *pattrib;
\r
1004 unsigned char *pframe;
\r
1005 struct rtw_ieee80211_hdr *pwlanhdr;
\r
1006 unsigned short *fctrl;
\r
1007 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1008 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
1011 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1013 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1016 pattrib = &pmgntframe->attrib;
\r
1017 update_mgntframe_attrib(padapter, pattrib);
\r
1019 _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
\r
1021 pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
\r
1022 pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
\r
1024 fctrl = &(pwlanhdr->frame_ctl);
\r
1027 /* unicast probe request frame */
\r
1028 _rtw_memcpy(pwlanhdr->addr1, ptxmgmt->peer, ETH_ALEN);
\r
1029 _rtw_memcpy(pattrib->dst, pwlanhdr->addr1, ETH_ALEN);
\r
1030 _rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
\r
1031 _rtw_memcpy(pattrib->src, pwlanhdr->addr2, ETH_ALEN);
\r
1032 _rtw_memcpy(pwlanhdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN);
\r
1033 _rtw_memcpy(pattrib->ra, pwlanhdr->addr3, ETH_ALEN);
\r
1035 SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
\r
1036 pmlmeext->mgnt_seq++;
\r
1037 SetFrameSubType(pframe, WIFI_ACTION);
\r
1039 pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
\r
1040 pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
\r
1042 rtw_build_tdls_dis_rsp_ies(padapter, pmgntframe, pframe, ptxmgmt, privacy);
\r
1044 pattrib->nr_frags = 1;
\r
1045 pattrib->last_txcmdsz = pattrib->pktlen;
\r
1047 dump_mgntframe(padapter, pmgntframe);
\r
1054 int issue_tdls_peer_traffic_rsp(_adapter *padapter, struct sta_info *ptdls_sta, struct tdls_txmgmt *ptxmgmt)
\r
1056 struct xmit_frame *pmgntframe;
\r
1057 struct pkt_attrib *pattrib;
\r
1058 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1059 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1062 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1064 ptxmgmt->action_code = TDLS_PEER_TRAFFIC_RESPONSE;
\r
1066 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1069 pattrib = &pmgntframe->attrib;
\r
1071 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1072 pattrib->ether_type = 0x890d;
\r
1074 _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
\r
1075 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1076 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
1077 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1079 update_tdls_attrib(padapter, pattrib);
\r
1080 pattrib->qsel = pattrib->priority;
\r
1082 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) !=_SUCCESS) {
\r
1083 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
1084 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1088 dump_mgntframe(padapter, pmgntframe);
\r
1096 int issue_tdls_peer_traffic_indication(_adapter *padapter, struct sta_info *ptdls_sta)
\r
1098 struct xmit_frame *pmgntframe;
\r
1099 struct pkt_attrib *pattrib;
\r
1100 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1101 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1102 struct tdls_txmgmt txmgmt;
\r
1105 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1107 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1108 txmgmt.action_code = TDLS_PEER_TRAFFIC_INDICATION;
\r
1110 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1113 pattrib = &pmgntframe->attrib;
\r
1115 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1116 pattrib->ether_type = 0x890d;
\r
1118 _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
\r
1119 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1120 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
1121 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1123 /* PTI frame's priority should be AC_VO */
\r
1124 pattrib->priority = 7;
\r
1126 update_tdls_attrib(padapter, pattrib);
\r
1127 pattrib->qsel = pattrib->priority;
\r
1128 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {
\r
1129 rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
\r
1130 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1134 dump_mgntframe(padapter, pmgntframe);
\r
1142 int issue_tdls_ch_switch_req(_adapter *padapter, struct sta_info *ptdls_sta)
\r
1144 struct xmit_frame *pmgntframe;
\r
1145 struct pkt_attrib *pattrib;
\r
1146 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1147 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1148 struct tdls_txmgmt txmgmt;
\r
1151 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1153 if (padapter->tdlsinfo.ch_switch_prohibited == _TRUE)
\r
1154 { DBG_871X("[TDLS] Ignore %s since ch_switch_prohibited = _TRUE\n", __FUNCTION__);
\r
1158 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1159 txmgmt.action_code = TDLS_CHANNEL_SWITCH_REQUEST;
\r
1161 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1164 pattrib = &pmgntframe->attrib;
\r
1166 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1167 pattrib->ether_type = 0x890d;
\r
1169 _rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
\r
1170 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1171 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
1172 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1174 update_tdls_attrib(padapter, pattrib);
\r
1175 pattrib->qsel = pattrib->priority;
\r
1176 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) !=_SUCCESS) {
\r
1177 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
1178 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1182 dump_mgntframe(padapter, pmgntframe);
\r
1189 int issue_tdls_ch_switch_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, int wait_ack)
\r
1191 struct xmit_frame *pmgntframe;
\r
1192 struct pkt_attrib *pattrib;
\r
1193 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
1194 struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
\r
1197 DBG_871X("[TDLS] %s\n", __FUNCTION__);
\r
1199 if (padapter->tdlsinfo.ch_switch_prohibited == _TRUE)
\r
1200 { DBG_871X("[TDLS] Ignore %s since ch_switch_prohibited = _TRUE\n", __FUNCTION__);
\r
1204 ptxmgmt->action_code = TDLS_CHANNEL_SWITCH_RESPONSE;
\r
1206 if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
\r
1209 pattrib = &pmgntframe->attrib;
\r
1211 pmgntframe->frame_tag = DATA_FRAMETAG;
\r
1212 pattrib->ether_type = 0x890d;
\r
1214 _rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
\r
1215 _rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
\r
1216 _rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
\r
1217 _rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
\r
1219 update_tdls_attrib(padapter, pattrib);
\r
1220 pattrib->qsel = pattrib->priority;
\r
1222 _enter_critical_bh(&pxmitpriv->lock, &irqL);
\r
1223 if(xmitframe_enqueue_for_tdls_sleeping_sta(padapter, pmgntframe)==_TRUE){
\r
1224 _exit_critical_bh(&pxmitpriv->lock, &irqL);
\r
1228 if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) !=_SUCCESS) {
\r
1229 rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
\r
1230 rtw_free_xmitframe(pxmitpriv, pmgntframe);
\r
1235 ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
\r
1237 dump_mgntframe(padapter, pmgntframe);
\r
1246 int On_TDLS_Dis_Rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
1248 struct sta_info *ptdls_sta = NULL, *psta = rtw_get_stainfo(&(padapter->stapriv), get_bssid(&(padapter->mlmepriv)));
\r
1249 struct recv_priv *precvpriv = &(padapter->recvpriv);
\r
1250 u8 *ptr = precv_frame->u.hdr.rx_data, *psa;
\r
1251 struct rx_pkt_attrib *pattrib = &(precv_frame->u.hdr.attrib);
\r
1252 struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);
\r
1253 u8 empty_addr[ETH_ALEN] = { 0x00 };
\r
1254 int UndecoratedSmoothedPWDB;
\r
1255 struct tdls_txmgmt txmgmt;
\r
1256 int ret = _SUCCESS;
\r
1258 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1259 /* WFDTDLS: for sigma test, not to setup direct link automatically */
\r
1260 ptdlsinfo->dev_discovered = _TRUE;
\r
1262 #ifdef CONFIG_TDLS_AUTOSETUP
\r
1264 psa = get_sa(ptr);
\r
1265 ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), psa);
\r
1267 if (ptdls_sta != NULL) {
\r
1268 ptdls_sta->tdls_sta_state |= TDLS_ALIVE_STATE;
\r
1270 /* Record the tdls sta with lowest signal strength */
\r
1271 if (ptdlsinfo->sta_maximum == _TRUE && ptdls_sta->alive_count >= 1 ) {
\r
1272 if (_rtw_memcmp(ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN)) {
\r
1273 _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);
\r
1274 ptdlsinfo->ss_record.RxPWDBAll = pattrib->phy_info.RxPWDBAll;
\r
1276 if (ptdlsinfo->ss_record.RxPWDBAll < pattrib->phy_info.RxPWDBAll) {
\r
1277 _rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);
\r
1278 ptdlsinfo->ss_record.RxPWDBAll = pattrib->phy_info.RxPWDBAll;
\r
1283 if (ptdlsinfo->sta_maximum == _TRUE) {
\r
1284 if (_rtw_memcmp( ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN)) {
\r
1285 /* All traffics are busy, do not set up another direct link. */
\r
1289 if (pattrib->phy_info.RxPWDBAll > ptdlsinfo->ss_record.RxPWDBAll) {
\r
1290 _rtw_memcpy(txmgmt.peer, ptdlsinfo->ss_record.macaddr, ETH_ALEN);
\r
1291 /* issue_tdls_teardown(padapter, ptdlsinfo->ss_record.macaddr, _FALSE); */
\r
1299 rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
\r
1301 if (pattrib->phy_info.RxPWDBAll + TDLS_SIGNAL_THRESH >= UndecoratedSmoothedPWDB) {
\r
1302 DBG_871X("pattrib->RxPWDBAll=%d, pdmpriv->UndecoratedSmoothedPWDB=%d\n", pattrib->phy_info.RxPWDBAll, UndecoratedSmoothedPWDB);
\r
1303 _rtw_memcpy(txmgmt.peer, psa, ETH_ALEN);
\r
1304 issue_tdls_setup_req(padapter, &txmgmt, _FALSE);
\r
1307 #endif /* CONFIG_TDLS_AUTOSETUP */
\r
1314 sint On_TDLS_Setup_Req(_adapter *padapter, union recv_frame *precv_frame)
\r
1316 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
1318 struct sta_info *ptdls_sta= NULL;
\r
1319 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1320 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1321 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
1322 struct security_priv *psecuritypriv = &padapter->securitypriv;
\r
1324 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1325 u8 *prsnie, *ppairwise_cipher;
\r
1327 u8 ccmp_included=0, rsnie_included=0;
\r
1328 u16 j, pairwise_count;
\r
1330 u32 timeout_interval = TPK_RESEND_COUNT;
\r
1331 sint parsing_length; /* Frame body length, without icv_len */
\r
1332 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1334 unsigned char supportRate[16];
\r
1335 int supportRateNum = 0;
\r
1336 struct tdls_txmgmt txmgmt;
\r
1338 if (ptdlsinfo->ap_prohibited == _TRUE)
\r
1341 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1342 psa = get_sa(ptr);
\r
1343 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1345 pmyid = adapter_mac_addr(padapter);
\r
1346 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
1347 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1348 -prx_pkt_attrib->hdrlen
\r
1349 -prx_pkt_attrib->iv_len
\r
1350 -prx_pkt_attrib->icv_len
\r
1356 if (ptdls_sta == NULL) {
\r
1357 ptdls_sta = rtw_alloc_stainfo(pstapriv, psa);
\r
1359 if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {
\r
1360 /* If the direct link is already set up */
\r
1361 /* Process as re-setup after tear down */
\r
1362 DBG_871X("re-setup a direct link\n");
\r
1364 /* Already receiving TDLS setup request */
\r
1365 else if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE) {
\r
1366 DBG_871X("receive duplicated TDLS setup request frame in handshaking\n");
\r
1369 /* When receiving and sending setup_req to the same link at the same time */
\r
1370 /* STA with higher MAC_addr would be initiator */
\r
1371 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE) {
\r
1372 DBG_871X("receive setup_req after sending setup_req\n");
\r
1373 for (i=0;i<6;i++){
\r
1374 if(*(pmyid+i)==*(psa+i)){
\r
1376 else if(*(pmyid+i)>*(psa+i)){
\r
1377 ptdls_sta->tdls_sta_state = TDLS_INITIATOR_STATE;
\r
1379 }else if(*(pmyid+i)<*(psa+i)){
\r
1387 txmgmt.dialog_token = *(ptr+2); /* Copy dialog token */
\r
1388 txmgmt.status_code = _STATS_SUCCESSFUL_;
\r
1390 /* Parsing information element */
\r
1391 for (j=FIXED_IE; j<parsing_length;) {
\r
1393 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1395 switch (pIE->ElementID) {
\r
1396 case _SUPPORTEDRATES_IE_:
\r
1397 _rtw_memcpy(supportRate, pIE->data, pIE->Length);
\r
1398 supportRateNum = pIE->Length;
\r
1400 case _COUNTRY_IE_:
\r
1402 case _EXT_SUPPORTEDRATES_IE_:
\r
1403 if (supportRateNum<=sizeof(supportRate)) {
\r
1404 _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);
\r
1405 supportRateNum += pIE->Length;
\r
1408 case _SUPPORTED_CH_IE_:
\r
1412 if (prx_pkt_attrib->encrypt) {
\r
1414 /* Check CCMP pairwise_cipher presence. */
\r
1415 ppairwise_cipher=prsnie+10;
\r
1416 _rtw_memcpy(ptdls_sta->TDLS_RSNIE, pIE->data, pIE->Length);
\r
1417 pairwise_count = *(u16*)(ppairwise_cipher-2);
\r
1418 for (k=0; k<pairwise_count; k++) {
\r
1419 if (_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE)
\r
1423 if (ccmp_included == 0)
\r
1424 txmgmt.status_code=_STATS_INVALID_RSNIE_;
\r
1427 case _EXT_CAP_IE_:
\r
1429 case _VENDOR_SPECIFIC_IE_:
\r
1432 if (prx_pkt_attrib->encrypt)
\r
1433 _rtw_memcpy(SNonce, (ptr+j+52), 32);
\r
1435 case _TIMEOUT_ITVL_IE_:
\r
1436 if (prx_pkt_attrib->encrypt)
\r
1437 timeout_interval = cpu_to_le32(*(u32*)(ptr+j+3));
\r
1439 case _RIC_Descriptor_IE_:
\r
1441 case _HT_CAPABILITY_IE_:
\r
1442 rtw_tdls_process_ht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);
\r
1444 case EID_BSSCoexistence:
\r
1446 case _LINK_ID_IE_:
\r
1447 if (_rtw_memcmp(get_bssid(pmlmepriv), pIE->data, 6) == _FALSE)
\r
1448 txmgmt.status_code=_STATS_NOT_IN_SAME_BSS_;
\r
1454 j += (pIE->Length + 2);
\r
1458 /* Check status code */
\r
1459 /* If responder STA has/hasn't security on AP, but request hasn't/has RSNIE, it should reject */
\r
1460 if (txmgmt.status_code == _STATS_SUCCESSFUL_) {
\r
1461 if (rsnie_included && prx_pkt_attrib->encrypt == 0)
\r
1462 txmgmt.status_code = _STATS_SEC_DISABLED_;
\r
1463 else if (rsnie_included==0 && prx_pkt_attrib->encrypt)
\r
1464 txmgmt.status_code = _STATS_INVALID_PARAMETERS_;
\r
1467 /* WFD test plan version 0.18.2 test item 5.1.5 */
\r
1468 /* SoUT does not use TDLS if AP uses weak security */
\r
1469 if (padapter->wdinfo.wfd_tdls_enable && (rsnie_included && prx_pkt_attrib->encrypt != _AES_))
\r
1470 txmgmt.status_code = _STATS_SEC_DISABLED_;
\r
1471 #endif /* CONFIG_WFD */
\r
1474 ptdls_sta->tdls_sta_state|= TDLS_INITIATOR_STATE;
\r
1475 if (prx_pkt_attrib->encrypt) {
\r
1476 _rtw_memcpy(ptdls_sta->SNonce, SNonce, 32);
\r
1478 if (timeout_interval <= 300)
\r
1479 ptdls_sta->TDLS_PeerKey_Lifetime = TPK_RESEND_COUNT;
\r
1481 ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
\r
1484 /* Update station supportRate */
\r
1485 ptdls_sta->bssratelen = supportRateNum;
\r
1486 _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);
\r
1488 if (!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
\r
1489 ptdlsinfo->sta_cnt++;
\r
1490 /* -2: AP + BC/MC sta, -4: default key */
\r
1491 if (ptdlsinfo->sta_cnt == MAX_ALLOWED_TDLS_STA_NUM)
\r
1492 ptdlsinfo->sta_maximum = _TRUE;
\r
1495 rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length - FIXED_IE);
\r
1496 #endif /* CONFIG_WFD */
\r
1502 _rtw_memcpy(txmgmt.peer, prx_pkt_attrib->src, ETH_ALEN);
\r
1504 if (rtw_tdls_is_driver_setup(padapter)) {
\r
1505 issue_tdls_setup_rsp(padapter, &txmgmt);
\r
1507 if (txmgmt.status_code==_STATS_SUCCESSFUL_) {
\r
1508 _set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);
\r
1510 free_tdls_sta(padapter, ptdls_sta);
\r
1519 int On_TDLS_Setup_Rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
1521 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
1522 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
1523 struct sta_info *ptdls_sta= NULL;
\r
1524 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1525 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1527 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1529 u16 status_code=0;
\r
1530 sint parsing_length; /* Frame body length, without icv_len */
\r
1531 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1534 u8 *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL, *ppairwise_cipher=NULL;
\r
1535 u16 pairwise_count, j, k;
\r
1537 unsigned char supportRate[16];
\r
1538 int supportRateNum = 0;
\r
1539 struct tdls_txmgmt txmgmt;
\r
1540 int ret = _SUCCESS;
\r
1541 u32 timeout_interval = TPK_RESEND_COUNT;
\r
1543 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1544 psa = get_sa(ptr);
\r
1545 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1547 if (NULL == ptdls_sta) {
\r
1552 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
1553 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1554 -prx_pkt_attrib->hdrlen
\r
1555 -prx_pkt_attrib->iv_len
\r
1556 -prx_pkt_attrib->icv_len
\r
1562 _rtw_memcpy(&status_code, ptr+2, 2);
\r
1564 if (status_code != 0) {
\r
1565 DBG_871X( "[TDLS] %s status_code = %d, free_tdls_sta\n", __FUNCTION__, status_code );
\r
1566 free_tdls_sta(padapter, ptdls_sta);
\r
1573 /* parsing information element */
\r
1574 for (j = FIXED_IE; j<parsing_length;) {
\r
1575 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1577 switch (pIE->ElementID) {
\r
1578 case _SUPPORTEDRATES_IE_:
\r
1579 _rtw_memcpy(supportRate, pIE->data, pIE->Length);
\r
1580 supportRateNum = pIE->Length;
\r
1582 case _COUNTRY_IE_:
\r
1584 case _EXT_SUPPORTEDRATES_IE_:
\r
1585 if (supportRateNum<=sizeof(supportRate)) {
\r
1586 _rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);
\r
1587 supportRateNum += pIE->Length;
\r
1590 case _SUPPORTED_CH_IE_:
\r
1594 /* Check CCMP pairwise_cipher presence. */
\r
1595 ppairwise_cipher=prsnie+10;
\r
1596 _rtw_memcpy(&pairwise_count, (u16*)(ppairwise_cipher-2), 2);
\r
1597 for (k=0;k<pairwise_count;k++) {
\r
1598 if (_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4) == _TRUE)
\r
1601 case _EXT_CAP_IE_:
\r
1603 case _VENDOR_SPECIFIC_IE_:
\r
1604 if (_rtw_memcmp((u8 *)pIE + 2, WMM_INFO_OUI, 6) == _TRUE) {
\r
1605 /* WMM Info ID and OUI */
\r
1606 if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))
\r
1607 ptdls_sta->qos_option = _TRUE;
\r
1612 _rtw_memcpy(ANonce, (ptr+j+20), 32);
\r
1614 case _TIMEOUT_ITVL_IE_:
\r
1615 ptimeout_ie=(u8*)pIE;
\r
1616 timeout_interval = cpu_to_le32(*(u32*)(ptimeout_ie+3));
\r
1618 case _RIC_Descriptor_IE_:
\r
1620 case _HT_CAPABILITY_IE_:
\r
1621 rtw_tdls_process_ht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);
\r
1623 case EID_BSSCoexistence:
\r
1625 case _LINK_ID_IE_:
\r
1626 plinkid_ie=(u8*)pIE;
\r
1632 j += (pIE->Length + 2);
\r
1636 ptdls_sta->bssratelen = supportRateNum;
\r
1637 _rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);
\r
1638 _rtw_memcpy(ptdls_sta->ANonce, ANonce, 32);
\r
1641 rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length - FIXED_IE);
\r
1642 #endif /* CONFIG_WFD */
\r
1644 if (status_code != _STATS_SUCCESSFUL_) {
\r
1645 txmgmt.status_code = status_code;
\r
1647 if (prx_pkt_attrib->encrypt) {
\r
1648 if (verify_ccmp == 1) {
\r
1649 txmgmt.status_code = _STATS_SUCCESSFUL_;
\r
1650 if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
\r
1651 wpa_tdls_generate_tpk(padapter, ptdls_sta);
\r
1652 if (tdls_verify_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie) == _FAIL) {
\r
1653 DBG_871X( "[TDLS] %s tdls_verify_mic fail, free_tdls_sta\n", __FUNCTION__);
\r
1654 free_tdls_sta(padapter, ptdls_sta);
\r
1658 ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
\r
1663 txmgmt.status_code = _STATS_INVALID_RSNIE_;
\r
1667 txmgmt.status_code = _STATS_SUCCESSFUL_;
\r
1671 if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
\r
1672 _rtw_memcpy(txmgmt.peer, prx_pkt_attrib->src, ETH_ALEN);
\r
1673 issue_tdls_setup_cfm(padapter, &txmgmt);
\r
1675 if (txmgmt.status_code == _STATS_SUCCESSFUL_) {
\r
1676 ptdlsinfo->link_established = _TRUE;
\r
1678 if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE) {
\r
1679 ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;
\r
1680 ptdls_sta->state |= _FW_LINKED;
\r
1681 _cancel_timer_ex( &ptdls_sta->handshake_timer);
\r
1684 if (prx_pkt_attrib->encrypt)
\r
1685 rtw_tdls_set_key(padapter, ptdls_sta);
\r
1687 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_ESTABLISHED);
\r
1693 if (rtw_tdls_is_driver_setup(padapter) == _TRUE)
\r
1700 int On_TDLS_Setup_Cfm(_adapter *padapter, union recv_frame *precv_frame)
\r
1702 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
1703 struct sta_info *ptdls_sta= NULL;
\r
1704 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1705 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1707 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1709 u16 status_code=0;
\r
1710 sint parsing_length;
\r
1711 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1713 u8 *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL, *ppairwise_cipher=NULL;
\r
1714 u16 j, pairwise_count;
\r
1715 int ret = _SUCCESS;
\r
1717 psa = get_sa(ptr);
\r
1718 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1720 if (ptdls_sta == NULL) {
\r
1721 DBG_871X("[%s] Direct Link Peer = "MAC_FMT" not found\n", __FUNCTION__, MAC_ARG(psa));
\r
1726 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
1727 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1728 -prx_pkt_attrib->hdrlen
\r
1729 -prx_pkt_attrib->iv_len
\r
1730 -prx_pkt_attrib->icv_len
\r
1736 _rtw_memcpy(&status_code, ptr+2, 2);
\r
1738 if (status_code!= 0) {
\r
1739 DBG_871X("[%s] status_code = %d\n, free_tdls_sta", __FUNCTION__, status_code);
\r
1740 free_tdls_sta(padapter, ptdls_sta);
\r
1745 if (prx_pkt_attrib->encrypt) {
\r
1746 /* Parsing information element */
\r
1747 for(j=FIXED_IE; j<parsing_length;) {
\r
1749 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1751 switch (pIE->ElementID) {
\r
1755 case _VENDOR_SPECIFIC_IE_:
\r
1756 if (_rtw_memcmp((u8 *)pIE + 2, WMM_PARA_OUI, 6) == _TRUE) {
\r
1757 /* WMM Parameter ID and OUI */
\r
1758 ptdls_sta->qos_option = _TRUE;
\r
1764 case _TIMEOUT_ITVL_IE_:
\r
1765 ptimeout_ie=(u8*)pIE;
\r
1767 case _HT_EXTRA_INFO_IE_:
\r
1769 case _LINK_ID_IE_:
\r
1770 plinkid_ie=(u8*)pIE;
\r
1776 j += (pIE->Length + 2);
\r
1780 /* Verify mic in FTIE MIC field */
\r
1781 if (rtw_tdls_is_driver_setup(padapter) &&
\r
1782 (tdls_verify_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie) == _FAIL)) {
\r
1783 free_tdls_sta(padapter, ptdls_sta);
\r
1790 if (rtw_tdls_is_driver_setup(padapter)) {
\r
1791 ptdlsinfo->link_established = _TRUE;
\r
1793 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE) {
\r
1794 ptdls_sta->tdls_sta_state|=TDLS_LINKED_STATE;
\r
1795 ptdls_sta->state |= _FW_LINKED;
\r
1796 _cancel_timer_ex(&ptdls_sta->handshake_timer);
\r
1799 if (prx_pkt_attrib->encrypt) {
\r
1800 rtw_tdls_set_key(padapter, ptdls_sta);
\r
1802 /* Start TPK timer */
\r
1803 ptdls_sta->TPK_count = 0;
\r
1804 _set_timer(&ptdls_sta->TPK_timer, ONE_SEC);
\r
1807 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_ESTABLISHED);
\r
1815 int On_TDLS_Dis_Req(_adapter *padapter, union recv_frame *precv_frame)
\r
1817 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1818 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1819 struct sta_info *psta_ap;
\r
1820 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1821 sint parsing_length; /* Frame body length, without icv_len */
\r
1822 PNDIS_802_11_VARIABLE_IEs pIE;
\r
1823 u8 FIXED_IE = 3, *dst;
\r
1825 struct tdls_txmgmt txmgmt;
\r
1826 int ret = _SUCCESS;
\r
1828 if (rtw_tdls_is_driver_setup(padapter) == _FALSE)
\r
1831 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1832 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
1833 txmgmt.dialog_token = *(ptr+2);
\r
1834 _rtw_memcpy(&txmgmt.peer, precv_frame->u.hdr.attrib.src, ETH_ALEN);
\r
1835 txmgmt.action_code = TDLS_DISCOVERY_RESPONSE;
\r
1836 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
1837 -prx_pkt_attrib->hdrlen
\r
1838 -prx_pkt_attrib->iv_len
\r
1839 -prx_pkt_attrib->icv_len
\r
1845 /* Parsing information element */
\r
1846 for (j=FIXED_IE; j<parsing_length;) {
\r
1848 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
1850 switch (pIE->ElementID) {
\r
1851 case _LINK_ID_IE_:
\r
1852 psta_ap = rtw_get_stainfo(pstapriv, pIE->data);
\r
1853 if (psta_ap == NULL)
\r
1855 dst = pIE->data + 12;
\r
1856 if (MacAddr_isBcst(dst) == _FALSE && (_rtw_memcmp(adapter_mac_addr(padapter), dst, 6) == _FALSE))
\r
1863 j += (pIE->Length + 2);
\r
1867 issue_tdls_dis_rsp(padapter, &txmgmt, prx_pkt_attrib->privacy);
\r
1874 int On_TDLS_Teardown(_adapter *padapter, union recv_frame *precv_frame)
\r
1877 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1878 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
1879 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
1880 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
1881 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1882 struct sta_info *ptdls_sta= NULL;
\r
1886 reason = *(ptr + prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN + 2);
\r
1887 DBG_871X("[TDLS] %s Reason code(%d)\n", __FUNCTION__,reason);
\r
1889 psa = get_sa(ptr);
\r
1891 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
1892 if (ptdls_sta != NULL) {
\r
1893 if (rtw_tdls_is_driver_setup(padapter))
\r
1894 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_TEAR_STA);
\r
1902 u8 TDLS_check_ch_state(uint state){
\r
1903 if (state & TDLS_CH_SWITCH_ON_STATE &&
\r
1904 state & TDLS_PEER_AT_OFF_STATE) {
\r
1905 if (state & TDLS_PEER_SLEEP_STATE)
\r
1906 return 2; /* U-APSD + ch. switch */
\r
1908 return 1; /* ch. switch */
\r
1914 int On_TDLS_Peer_Traffic_Indication(_adapter *padapter, union recv_frame *precv_frame)
\r
1916 struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
\r
1917 struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->src);
\r
1918 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
1919 struct tdls_txmgmt txmgmt;
\r
1921 ptr +=pattrib->hdrlen + pattrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
1922 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
1924 if (ptdls_sta != NULL) {
\r
1925 txmgmt.dialog_token = *(ptr+2);
\r
1926 issue_tdls_peer_traffic_rsp(padapter, ptdls_sta, &txmgmt);
\r
1927 //issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 0, 0);
\r
1929 DBG_871X("from unknown sta:"MAC_FMT"\n", MAC_ARG(pattrib->src));
\r
1936 /* We process buffered data for 1. U-APSD, 2. ch. switch, 3. U-APSD + ch. switch here */
\r
1937 int On_TDLS_Peer_Traffic_Rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
1939 struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
\r
1940 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
1941 struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib;
\r
1942 struct sta_priv *pstapriv = &padapter->stapriv;
\r
1943 struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->src);
\r
1945 /* u8 state=TDLS_check_ch_state(ptdls_sta->tdls_sta_state); */
\r
1948 ptdls_sta->sta_stats.rx_data_pkts++;
\r
1950 ptdls_sta->tdls_sta_state &= ~(TDLS_WAIT_PTR_STATE);
\r
1952 /* Check 4-AC queue bit */
\r
1953 if (ptdls_sta->uapsd_vo || ptdls_sta->uapsd_vi || ptdls_sta->uapsd_be || ptdls_sta->uapsd_bk)
\r
1956 /* If it's a direct link and have buffered frame */
\r
1957 if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {
\r
1960 _list *xmitframe_plist, *xmitframe_phead;
\r
1961 struct xmit_frame *pxmitframe=NULL;
\r
1963 _enter_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);
\r
1965 xmitframe_phead = get_list_head(&ptdls_sta->sleep_q);
\r
1966 xmitframe_plist = get_next(xmitframe_phead);
\r
1968 /* transmit buffered frames */
\r
1969 while (rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == _FALSE) {
\r
1970 pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
\r
1971 xmitframe_plist = get_next(xmitframe_plist);
\r
1972 rtw_list_delete(&pxmitframe->list);
\r
1974 ptdls_sta->sleepq_len--;
\r
1975 ptdls_sta->sleepq_ac_len--;
\r
1976 if (ptdls_sta->sleepq_len>0) {
\r
1977 pxmitframe->attrib.mdata = 1;
\r
1978 pxmitframe->attrib.eosp = 0;
\r
1980 pxmitframe->attrib.mdata = 0;
\r
1981 pxmitframe->attrib.eosp = 1;
\r
1983 pxmitframe->attrib.triggered = 1;
\r
1985 rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
\r
1988 if (ptdls_sta->sleepq_len==0)
\r
1989 DBG_871X("no buffered packets for tdls to xmit\n");
\r
1991 DBG_871X("error!psta->sleepq_len=%d\n", ptdls_sta->sleepq_len);
\r
1992 ptdls_sta->sleepq_len=0;
\r
1995 _exit_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);
\r
2004 #ifdef CONFIG_TDLS_CH_SW
\r
2005 sint On_TDLS_Ch_Switch_Req(_adapter *padapter, union recv_frame *precv_frame)
\r
2007 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
2008 struct sta_info *ptdls_sta= NULL;
\r
2009 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2010 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
2011 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
2013 sint parsing_length;
\r
2014 PNDIS_802_11_VARIABLE_IEs pIE;
\r
2017 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2018 struct tdls_txmgmt txmgmt;
\r
2019 u16 switch_time= CH_SWITCH_TIME * 1000, switch_timeout=CH_SWITCH_TIMEOUT * 1000;
\r
2021 if (padapter->tdlsinfo.ch_switch_prohibited == _TRUE)
\r
2022 { DBG_871X("[TDLS] Ignore %s since ch_switch_prohibited = _TRUE\n", __FUNCTION__);
\r
2026 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
2027 psa = get_sa(ptr);
\r
2028 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
2030 ptdls_sta->ch_switch_time=switch_time;
\r
2031 ptdls_sta->ch_switch_timeout=switch_timeout;
\r
2033 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
2034 parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
\r
2035 -prx_pkt_attrib->hdrlen
\r
2036 -prx_pkt_attrib->iv_len
\r
2037 -prx_pkt_attrib->icv_len
\r
2043 pchsw_info->off_ch_num = *(ptr + 2);
\r
2045 if (*(ptr + 2) == 2) {
\r
2046 pchsw_info->off_ch_num = 11;
\r
2049 if (pchsw_info->off_ch_num != pmlmeext->cur_channel) {
\r
2050 pchsw_info->delay_switch_back = _FALSE;
\r
2053 /* Parsing information element */
\r
2054 for (j=FIXED_IE; j<parsing_length;) {
\r
2055 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
2057 switch (pIE->ElementID) {
\r
2058 case EID_SecondaryChnlOffset:
\r
2059 padapter->tdlsinfo.chsw_info.ch_offset = *(pIE->data);
\r
2061 case _LINK_ID_IE_:
\r
2063 case _CH_SWITCH_TIMING_:
\r
2064 ptdls_sta->ch_switch_time = (RTW_GET_LE16(pIE->data) >= CH_SWITCH_TIME * 1000) ?
\r
2065 RTW_GET_LE16(pIE->data) : CH_SWITCH_TIME * 1000;
\r
2066 ptdls_sta->ch_switch_timeout = (RTW_GET_LE16(pIE->data + 2) >= CH_SWITCH_TIMEOUT * 1000) ?
\r
2067 RTW_GET_LE16(pIE->data + 2) : CH_SWITCH_TIMEOUT * 1000;
\r
2068 DBG_871X("%s ch_switch_time:%d, ch_switch_timeout:%d\n"
\r
2069 , __FUNCTION__, RTW_GET_LE16(pIE->data), RTW_GET_LE16(pIE->data + 2));
\r
2074 j += (pIE->Length + 2);
\r
2077 /* Todo: check status */
\r
2078 txmgmt.status_code = 0;
\r
2079 _rtw_memcpy(txmgmt.peer, psa, ETH_ALEN);
\r
2081 ATOMIC_SET(&pchsw_info->chsw_on, _TRUE);
\r
2083 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_RESP);
\r
2088 sint On_TDLS_Ch_Switch_Rsp(_adapter *padapter, union recv_frame *precv_frame)
\r
2090 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
2091 struct sta_info *ptdls_sta= NULL;
\r
2092 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2093 u8 *ptr = precv_frame->u.hdr.rx_data;
\r
2094 struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;
\r
2096 sint parsing_length;
\r
2097 PNDIS_802_11_VARIABLE_IEs pIE;
\r
2099 u16 status_code, j, switch_time, switch_timeout;
\r
2100 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2101 int ret = _SUCCESS;
\r
2103 if (padapter->tdlsinfo.ch_switch_prohibited == _TRUE)
\r
2104 { DBG_871X("[TDLS] Ignore %s since ch_switch_prohibited = _TRUE\n", __FUNCTION__);
\r
2108 psa = get_sa(ptr);
\r
2109 ptdls_sta = rtw_get_stainfo(pstapriv, psa);
\r
2111 /* If we receive Unsolicited TDLS Channel Switch Response when channel switch is running, */
\r
2112 /* we will go back to base channel and terminate this channel switch procedure */
\r
2113 if (ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE) {
\r
2114 if (pmlmeext->cur_channel != rtw_get_oper_ch(padapter)) {
\r
2115 DBG_871X("receive unsolicited channel switch response \n");
\r
2116 rtw_tdls_cmd(padapter, NULL, TDLS_CH_SW_BACK);
\r
2121 ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
\r
2122 parsing_length = ((union recv_frame *)precv_frame)->u.hdr.len
\r
2123 -prx_pkt_attrib->hdrlen
\r
2124 -prx_pkt_attrib->iv_len
\r
2125 -prx_pkt_attrib->icv_len
\r
2131 _rtw_memcpy(&status_code, ptr+2, 2);
\r
2133 if (status_code != 0) {
\r
2134 DBG_871X("[%s] status_code:%d\n", __FUNCTION__, status_code);
\r
2135 pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE);
\r
2136 ATOMIC_SET(&pchsw_info->chsw_on, _FALSE);
\r
2141 /* Parsing information element */
\r
2142 for (j = FIXED_IE; j < parsing_length;) {
\r
2143 pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
\r
2145 switch (pIE->ElementID) {
\r
2146 case _LINK_ID_IE_:
\r
2148 case _CH_SWITCH_TIMING_:
\r
2149 _rtw_memcpy(&switch_time, pIE->data, 2);
\r
2150 if (switch_time > ptdls_sta->ch_switch_time)
\r
2151 _rtw_memcpy(&ptdls_sta->ch_switch_time, &switch_time, 2);
\r
2153 _rtw_memcpy(&switch_timeout, pIE->data + 2, 2);
\r
2154 if (switch_timeout > ptdls_sta->ch_switch_timeout)
\r
2155 _rtw_memcpy(&ptdls_sta->ch_switch_timeout, &switch_timeout, 2);
\r
2161 j += (pIE->Length + 2);
\r
2164 if ((pmlmeext->cur_channel == rtw_get_oper_ch(padapter)) &&
\r
2165 (pchsw_info->ch_sw_state & TDLS_WAIT_CH_RSP_STATE)) {
\r
2166 ATOMIC_SET(&pchsw_info->chsw_on, _TRUE);
\r
2167 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW);
\r
2173 #endif /* CONFIG_TDLS_CH_SW */
\r
2176 void wfd_ie_tdls(_adapter * padapter, u8 *pframe, u32 *pktlen )
\r
2178 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
\r
2179 struct wifi_display_info *pwfd_info = padapter->tdlsinfo.wfd_info;
\r
2180 u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
\r
2185 wfdie[ wfdielen++ ] = 0x50;
\r
2186 wfdie[ wfdielen++ ] = 0x6F;
\r
2187 wfdie[ wfdielen++ ] = 0x9A;
\r
2188 wfdie[ wfdielen++ ] = 0x0A; /* WFA WFD v1.0 */
\r
2191 * Commented by Albert 20110825
\r
2192 * According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
\r
2193 * 1. WFD Device Information
\r
2194 * 2. Associated BSSID ( Optional )
\r
2195 * 3. Local IP Adress ( Optional )
\r
2198 /* WFD Device Information ATTR */
\r
2200 wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
\r
2203 /* Note: In the WFD specification, the size of length field is 2. */
\r
2204 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
\r
2208 /* WFD device information */
\r
2209 /* available for WFD session + Preferred TDLS + WSD ( WFD Service Discovery ) */
\r
2210 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL
\r
2211 | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_WSD);
\r
2215 /* Session Management Control Port */
\r
2216 /* Default TCP port for RTSP messages is 554 */
\r
2217 RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
\r
2221 /* WFD Device Maximum Throughput */
\r
2222 /* 300Mbps is the maximum throughput */
\r
2223 RTW_PUT_BE16(wfdie + wfdielen, 300);
\r
2226 /* Associated BSSID ATTR */
\r
2228 wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
\r
2231 /* Note: In the WFD specification, the size of length field is 2. */
\r
2232 RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
\r
2236 /* Associated BSSID */
\r
2237 if (check_fwstate( pmlmepriv, _FW_LINKED) == _TRUE)
\r
2238 _rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
\r
2240 _rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
\r
2242 /* Local IP Address ATTR */
\r
2243 wfdie[ wfdielen++ ] = WFD_ATTR_LOCAL_IP_ADDR;
\r
2246 /* Note: In the WFD specification, the size of length field is 2. */
\r
2247 RTW_PUT_BE16(wfdie + wfdielen, 0x0005);
\r
2251 /* 0x01: Version1;IPv4 */
\r
2252 wfdie[ wfdielen++ ] = 0x01;
\r
2254 /* IPv4 Address */
\r
2255 _rtw_memcpy( wfdie + wfdielen, pwfd_info->ip_address, 4 );
\r
2258 pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, pktlen);
\r
2261 #endif /* CONFIG_WFD */
\r
2263 void rtw_build_tdls_setup_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2265 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
2266 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2267 struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);
\r
2274 if (pattrib->encrypt) {
\r
2275 for (i=0;i<8;i++) {
\r
2276 time=rtw_get_current_time();
\r
2277 _rtw_memcpy(&ptdls_sta->SNonce[4*i], (u8 *)&time, 4);
\r
2281 pframe_head = pframe; /* For rtw_tdls_set_ht_cap() */
\r
2283 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2284 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2285 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2286 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2288 pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);
\r
2289 pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);
\r
2290 pframe = rtw_tdls_set_sup_ch(&(padapter->mlmeextpriv), pframe, pattrib);
\r
2291 pframe = rtw_tdls_set_sup_reg_class(pframe, pattrib);
\r
2293 if (pattrib->encrypt)
\r
2294 pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
\r
2296 pframe = rtw_tdls_set_ext_cap(pframe, pattrib);
\r
2298 if (pattrib->encrypt) {
\r
2299 pframe = rtw_tdls_set_ftie(ptxmgmt
\r
2303 , ptdls_sta->SNonce);
\r
2305 pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
\r
2308 /* Sup_reg_classes(optional) */
\r
2309 if (pregistrypriv->ht_enable == _TRUE)
\r
2310 pframe = rtw_tdls_set_ht_cap(padapter, pframe_head, pattrib);
\r
2312 pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);
\r
2314 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2316 if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))
\r
2317 pframe = rtw_tdls_set_qos_cap(pframe, pattrib);
\r
2320 wfd_ie_tdls( padapter, pframe, &(pattrib->pktlen) );
\r
2321 #endif /* CONFIG_WFD */
\r
2325 void rtw_build_tdls_setup_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2327 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
2328 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2329 struct sta_info *ptdls_sta;
\r
2330 u8 k; /* for random ANonce */
\r
2331 u8 *pftie=NULL, *ptimeout_ie = NULL, *plinkid_ie = NULL, *prsnie = NULL, *pftie_mic = NULL;
\r
2335 ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);
\r
2337 if (ptdls_sta == NULL)
\r
2338 DBG_871X("[%s] %d ptdls_sta is NULL\n", __FUNCTION__, __LINE__);
\r
2340 if (pattrib->encrypt && ptdls_sta != NULL) {
\r
2341 for (k=0;k<8;k++) {
\r
2342 time = rtw_get_current_time();
\r
2343 _rtw_memcpy(&ptdls_sta->ANonce[4*k], (u8*)&time, 4);
\r
2347 pframe_head = pframe;
\r
2349 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2350 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2351 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2352 pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
\r
2354 if (ptxmgmt->status_code != 0) {
\r
2355 DBG_871X("[%s] status_code:%04x \n", __FUNCTION__, ptxmgmt->status_code);
\r
2359 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2360 pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);
\r
2361 pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);
\r
2362 pframe = rtw_tdls_set_sup_ch(&(padapter->mlmeextpriv), pframe, pattrib);
\r
2363 pframe = rtw_tdls_set_sup_reg_class(pframe, pattrib);
\r
2365 if (pattrib->encrypt) {
\r
2367 pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _FALSE, ptdls_sta);
\r
2370 pframe = rtw_tdls_set_ext_cap(pframe, pattrib);
\r
2372 if (pattrib->encrypt) {
\r
2373 if (rtw_tdls_is_driver_setup(padapter) == _TRUE)
\r
2374 wpa_tdls_generate_tpk(padapter, ptdls_sta);
\r
2377 pftie_mic = pframe+4;
\r
2378 pframe = rtw_tdls_set_ftie(ptxmgmt
\r
2381 , ptdls_sta->ANonce
\r
2382 , ptdls_sta->SNonce);
\r
2384 ptimeout_ie = pframe;
\r
2385 pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _FALSE, ptdls_sta);
\r
2388 /* Sup_reg_classes(optional) */
\r
2389 if (pregistrypriv->ht_enable == _TRUE)
\r
2390 pframe = rtw_tdls_set_ht_cap(padapter, pframe_head, pattrib);
\r
2392 pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);
\r
2394 plinkid_ie = pframe;
\r
2395 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2397 /* Fill FTIE mic */
\r
2398 if (pattrib->encrypt && rtw_tdls_is_driver_setup(padapter) == _TRUE)
\r
2399 wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);
\r
2401 if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))
\r
2402 pframe = rtw_tdls_set_qos_cap(pframe, pattrib);
\r
2405 wfd_ie_tdls( padapter, pframe, &(pattrib->pktlen) );
\r
2406 #endif /* CONFIG_WFD */
\r
2410 void rtw_build_tdls_setup_cfm_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2413 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
\r
2414 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
\r
2415 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2416 struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);
\r
2418 unsigned int ie_len;
\r
2420 u8 wmm_param_ele[24] = {0};
\r
2421 u8 *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL;
\r
2423 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2424 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2425 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2426 pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
\r
2427 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2429 if (ptxmgmt->status_code!=0)
\r
2432 if (pattrib->encrypt) {
\r
2434 pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
\r
2437 if (pattrib->encrypt) {
\r
2439 pftie_mic = pframe+4;
\r
2440 pframe = rtw_tdls_set_ftie(ptxmgmt
\r
2443 , ptdls_sta->ANonce
\r
2444 , ptdls_sta->SNonce);
\r
2446 ptimeout_ie = pframe;
\r
2447 pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
\r
2449 if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
\r
2450 /* Start TPK timer */
\r
2451 ptdls_sta->TPK_count=0;
\r
2452 _set_timer(&ptdls_sta->TPK_timer, ONE_SEC);
\r
2456 /* HT operation; todo */
\r
2457 plinkid_ie = pframe;
\r
2458 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2460 if (pattrib->encrypt && (rtw_tdls_is_driver_setup(padapter) == _TRUE))
\r
2461 wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);
\r
2463 if (ptdls_sta->qos_option == _TRUE)
\r
2464 pframe = rtw_tdls_set_wmm_params(padapter, pframe, pattrib);
\r
2467 void rtw_build_tdls_teardown_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2469 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2470 struct sta_info *ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);
\r
2471 u8 *pftie = NULL, *pftie_mic = NULL, *plinkid_ie = NULL;
\r
2473 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2474 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2475 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2476 pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
\r
2478 if (pattrib->encrypt) {
\r
2480 pftie_mic = pframe + 4;
\r
2481 pframe = rtw_tdls_set_ftie(ptxmgmt
\r
2484 , ptdls_sta->ANonce
\r
2485 , ptdls_sta->SNonce);
\r
2488 plinkid_ie = pframe;
\r
2489 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
\r
2490 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2491 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
\r
2492 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2494 if (pattrib->encrypt && (rtw_tdls_is_driver_setup(padapter) == _TRUE))
\r
2495 wpa_tdls_teardown_ftie_mic(ptdls_sta->tpk.kck, plinkid_ie, ptxmgmt->status_code, 1, 4, pftie, pftie_mic);
\r
2498 void rtw_build_tdls_dis_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2500 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2502 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2503 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2504 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2505 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2506 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2510 void rtw_build_tdls_dis_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, u8 privacy)
\r
2512 struct registry_priv *pregistrypriv = &padapter->registrypriv;
\r
2513 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
\r
2514 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2515 u8 *pframe_head, pktlen_index;
\r
2517 pktlen_index = pattrib->pktlen;
\r
2518 pframe_head = pframe;
\r
2520 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_PUBLIC);
\r
2521 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2522 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2523 pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);
\r
2525 pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);
\r
2527 pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);
\r
2530 pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, NULL);
\r
2532 pframe = rtw_tdls_set_ext_cap(pframe, pattrib);
\r
2535 pframe = rtw_tdls_set_ftie(ptxmgmt, pframe, pattrib, NULL, NULL);
\r
2536 pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, NULL);
\r
2539 if (pregistrypriv->ht_enable == _TRUE)
\r
2540 pframe = rtw_tdls_set_ht_cap(padapter, pframe_head - pktlen_index, pattrib);
\r
2542 pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);
\r
2543 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2548 void rtw_build_tdls_peer_traffic_indication_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2551 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2553 struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);
\r
2555 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2556 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2557 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2558 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2560 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
\r
2561 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2562 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
\r
2563 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2566 /* PU buffer status */
\r
2567 if (ptdls_sta->uapsd_bk & BIT(1))
\r
2569 if (ptdls_sta->uapsd_be & BIT(1))
\r
2571 if (ptdls_sta->uapsd_vi & BIT(1))
\r
2573 if (ptdls_sta->uapsd_vo & BIT(1))
\r
2575 pframe = rtw_set_ie(pframe, _PTI_BUFFER_STATUS_, 1, &AC_queue, &(pattrib->pktlen));
\r
2579 void rtw_build_tdls_peer_traffic_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2582 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2583 struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);
\r
2585 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2586 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2587 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2588 pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
\r
2590 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
\r
2591 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2592 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
\r
2593 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2596 #ifdef CONFIG_TDLS_CH_SW
\r
2597 void rtw_build_tdls_ch_switch_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2600 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2601 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2602 struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
\r
2603 u16 switch_time= CH_SWITCH_TIME * 1000, switch_timeout=CH_SWITCH_TIMEOUT * 1000;
\r
2605 ptdls_sta->ch_switch_time=switch_time;
\r
2606 ptdls_sta->ch_switch_timeout=switch_timeout;
\r
2608 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2609 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2610 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2611 pframe = rtw_tdls_set_target_ch(padapter, pframe, pattrib);
\r
2612 pframe = rtw_tdls_set_reg_class(pframe, pattrib, ptdls_sta);
\r
2614 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
\r
2615 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2616 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
\r
2617 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2619 pframe = rtw_tdls_set_ch_sw(pframe, pattrib, ptdls_sta);
\r
2623 void rtw_build_tdls_ch_switch_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
\r
2626 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2627 struct sta_priv *pstapriv = &padapter->stapriv;
\r
2628 struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
\r
2630 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2631 pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
\r
2632 pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
\r
2633 pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
\r
2635 if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
\r
2636 pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
\r
2637 else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
\r
2638 pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
\r
2640 pframe = rtw_tdls_set_ch_sw(pframe, pattrib, ptdls_sta);
\r
2645 void rtw_build_tunneled_probe_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2648 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2649 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
\r
2650 struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;
\r
2651 u8 category = RTW_WLAN_CATEGORY_P2P;
\r
2652 u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};
\r
2656 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2657 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2658 pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));
\r
2659 pframe = rtw_set_fixed_ie(pframe, 1, &(probe_req), &(pattrib->pktlen));
\r
2661 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
\r
2662 wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
\r
2663 pframe += wfdielen;
\r
2664 pattrib->pktlen += wfdielen;
\r
2665 } else if (!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE)) {
\r
2666 wfdielen = build_probe_req_wfd_ie(pbuddy_wdinfo, pframe);
\r
2667 pframe += wfdielen;
\r
2668 pattrib->pktlen += wfdielen;
\r
2673 void rtw_build_tunneled_probe_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
\r
2676 struct pkt_attrib *pattrib = &pxmitframe->attrib;
\r
2677 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
\r
2678 struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;
\r
2679 u8 category = RTW_WLAN_CATEGORY_P2P;
\r
2680 u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};
\r
2684 pframe = rtw_tdls_set_payload_type(pframe, pattrib);
\r
2685 pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
\r
2686 pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));
\r
2687 pframe = rtw_set_fixed_ie(pframe, 1, &(probe_rsp), &(pattrib->pktlen));
\r
2689 if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
\r
2690 wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 1);
\r
2691 pframe += wfdielen;
\r
2692 pattrib->pktlen += wfdielen;
\r
2693 } else if (!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE)) {
\r
2694 wfdielen = build_probe_resp_wfd_ie(pbuddy_wdinfo, pframe, 1);
\r
2695 pframe += wfdielen;
\r
2696 pattrib->pktlen += wfdielen;
\r
2700 #endif /* CONFIG_WFD */
\r
2702 void _tdls_tpk_timer_hdl(void *FunctionContext)
\r
2704 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2705 struct tdls_txmgmt txmgmt;
\r
2707 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
2708 ptdls_sta->TPK_count++;
\r
2709 /* TPK_timer expired in a second */
\r
2710 /* Retry timer should set at least 301 sec. */
\r
2711 if (ptdls_sta->TPK_count >= ptdls_sta->TDLS_PeerKey_Lifetime) {
\r
2712 DBG_871X("[TDLS] %s, Re-Setup TDLS link with "MAC_FMT" since TPK lifetime expires!\n", __FUNCTION__, MAC_ARG(ptdls_sta->hwaddr));
\r
2713 ptdls_sta->TPK_count=0;
\r
2714 _rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);
\r
2715 issue_tdls_setup_req(ptdls_sta->padapter, &txmgmt, _FALSE);
\r
2718 _set_timer(&ptdls_sta->TPK_timer, ONE_SEC);
\r
2721 #ifdef CONFIG_TDLS_CH_SW
\r
2722 void _tdls_ch_switch_timer_hdl(void *FunctionContext)
\r
2724 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2725 _adapter *padapter = ptdls_sta->padapter;
\r
2726 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
2728 //DBG_871X("%s %d, tdls_sta_state:0x%08x\n", __FUNCTION__, __LINE__, ptdls_sta->tdls_sta_state);
\r
2730 if (padapter->mlmeextpriv.cur_channel != rtw_get_oper_ch(padapter)) {
\r
2731 if (!(pchsw_info->ch_sw_state & TDLS_PEER_AT_OFF_STATE)) {
\r
2732 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_BACK);
\r
2733 ATOMIC_SET(&pchsw_info->chsw_on, _FALSE);
\r
2734 DBG_871X("[TDLS] %s, can't get traffic from op_ch:%d\n", __FUNCTION__, rtw_get_oper_ch(padapter));
\r
2736 //DBG_871X("%s %d\n", __FUNCTION__, __LINE__);
\r
2737 //_set_timer(&ptdls_sta->delay_timer, padapter->mlmeextpriv.mlmext_info.bcn_interval - 5 - ptdls_sta->ch_switch_timeout/1000);
\r
2740 //DBG_871X("%s %d, op_ch:%d, tdls_state:0x%08x\n", __FUNCTION__, __LINE__, rtw_get_oper_ch(padapter), ptdls_sta->tdls_sta_state);
\r
2744 if (!(pchsw_info->ch_sw_state & TDLS_PEER_AT_OFF_STATE)) {
\r
2745 //SelectChannel(padapter, padapter->mlmeextpriv.cur_channel);
\r
2746 ATOMIC_SET(&pchsw_info->chsw_on, _FALSE);
\r
2747 DBG_871X("%s %d, op_ch:%d, tdls_state:0x%08x\n", __FUNCTION__, __LINE__, rtw_get_oper_ch(padapter), ptdls_sta->tdls_sta_state);
\r
2750 if (pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE) {
\r
2751 if (padapter->mlmeextpriv.cur_channel != rtw_get_oper_ch(padapter)) {
\r
2752 DBG_871X("%s %d\n", __FUNCTION__, __LINE__);
\r
2753 _set_timer(&ptdls_sta->delay_timer, padapter->mlmeextpriv.mlmext_info.bcn_interval - 5 - ptdls_sta->ch_switch_timeout/1000);
\r
2754 //_set_timer(&ptdls_sta->delay_timer, 1000);
\r
2756 DBG_871X("%s %d\n", __FUNCTION__, __LINE__);
\r
2757 issue_tdls_ch_switch_req(padapter, ptdls_sta);
\r
2758 //_set_timer(&ptdls_sta->delay_timer, 500);
\r
2764 void _tdls_delay_timer_hdl(void *FunctionContext)
\r
2766 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2767 _adapter *padapter = ptdls_sta->padapter;
\r
2768 struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
\r
2770 DBG_871X("[TDLS] %s, op_ch:%d, tdls_state:0x%08x\n", __FUNCTION__, rtw_get_oper_ch(padapter), ptdls_sta->tdls_sta_state);
\r
2771 pchsw_info->delay_switch_back = _TRUE;
\r
2775 void _tdls_handshake_timer_hdl(void *FunctionContext)
\r
2777 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2778 _adapter *padapter = ptdls_sta->padapter;
\r
2779 struct tdls_txmgmt txmgmt;
\r
2781 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
2782 _rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);
\r
2783 txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
\r
2785 if (ptdls_sta != NULL) {
\r
2786 DBG_871X("[TDLS] Handshake time out\n");
\r
2787 if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)
\r
2789 issue_tdls_teardown(padapter, &txmgmt, _TRUE);
\r
2793 rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_TEAR_STA);
\r
2798 void _tdls_pti_timer_hdl(void *FunctionContext)
\r
2800 struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
\r
2801 _adapter *padapter = ptdls_sta->padapter;
\r
2802 struct tdls_txmgmt txmgmt;
\r
2804 _rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
\r
2805 _rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);
\r
2806 txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_;
\r
2808 if (ptdls_sta != NULL) {
\r
2809 if (ptdls_sta->tdls_sta_state & TDLS_WAIT_PTR_STATE) {
\r
2810 DBG_871X("[TDLS] Doesn't receive PTR from peer dev:"MAC_FMT"; "
\r
2811 "Send TDLS Tear Down\n", MAC_ARG(ptdls_sta->hwaddr));
\r
2812 issue_tdls_teardown(padapter, &txmgmt, _FALSE);
\r
2817 void rtw_init_tdls_timer(_adapter *padapter, struct sta_info *psta)
\r
2819 psta->padapter=padapter;
\r
2820 _init_timer(&psta->TPK_timer, padapter->pnetdev, _tdls_tpk_timer_hdl, psta);
\r
2821 #ifdef CONFIG_TDLS_CH_SW
\r
2822 _init_timer(&psta->ch_sw_timer, padapter->pnetdev, _tdls_ch_switch_timer_hdl, psta);
\r
2823 _init_timer(&psta->delay_timer, padapter->pnetdev, _tdls_delay_timer_hdl, psta);
\r
2825 _init_timer(&psta->handshake_timer, padapter->pnetdev, _tdls_handshake_timer_hdl, psta);
\r
2826 _init_timer(&psta->pti_timer, padapter->pnetdev, _tdls_pti_timer_hdl, psta);
\r
2829 void rtw_free_tdls_timer(struct sta_info *psta)
\r
2831 _cancel_timer_ex(&psta->TPK_timer);
\r
2832 #ifdef CONFIG_TDLS_CH_SW
\r
2833 _cancel_timer_ex(&psta->ch_sw_timer);
\r
2834 _cancel_timer_ex(&psta->delay_timer);
\r
2836 _cancel_timer_ex(&psta->handshake_timer);
\r
2837 _cancel_timer_ex(&psta->pti_timer);
\r
2840 u8 update_sgi_tdls(_adapter *padapter, struct sta_info *psta)
\r
2842 return query_ra_short_GI(psta);
\r
2845 u32 update_mask_tdls(_adapter *padapter, struct sta_info *psta)
\r
2847 unsigned char sta_band = 0;
\r
2848 unsigned int tx_ra_bitmap=0;
\r
2849 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
\r
2850 WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
\r
2852 rtw_hal_update_sta_rate_mask(padapter, psta);
\r
2853 tx_ra_bitmap = psta->ra_mask;
\r
2855 if (pcur_network->Configuration.DSConfig > 14) {
\r
2856 if (tx_ra_bitmap & 0xffff000)
\r
2857 sta_band |= WIRELESS_11_5N | WIRELESS_11A;
\r
2859 sta_band |= WIRELESS_11A;
\r
2861 if (tx_ra_bitmap & 0xffff000)
\r
2862 sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
\r
2863 else if (tx_ra_bitmap & 0xff0)
\r
2864 sta_band |= WIRELESS_11G |WIRELESS_11B;
\r
2866 sta_band |= WIRELESS_11B;
\r
2869 psta->wireless_mode = sta_band;
\r
2871 psta->raid = rtw_hal_networktype_to_raid(padapter,psta);
\r
2872 tx_ra_bitmap |= ((psta->raid<<28)&0xf0000000);
\r
2873 return tx_ra_bitmap;
\r
2876 int rtw_tdls_is_driver_setup(_adapter *padapter)
\r
2878 return padapter->tdlsinfo.driver_setup;
\r
2881 const char * rtw_tdls_action_txt(enum TDLS_ACTION_FIELD action)
\r
2884 case TDLS_SETUP_REQUEST:
\r
2885 return "TDLS_SETUP_REQUEST";
\r
2886 case TDLS_SETUP_RESPONSE:
\r
2887 return "TDLS_SETUP_RESPONSE";
\r
2888 case TDLS_SETUP_CONFIRM:
\r
2889 return "TDLS_SETUP_CONFIRM";
\r
2890 case TDLS_TEARDOWN:
\r
2891 return "TDLS_TEARDOWN";
\r
2892 case TDLS_PEER_TRAFFIC_INDICATION:
\r
2893 return "TDLS_PEER_TRAFFIC_INDICATION";
\r
2894 case TDLS_CHANNEL_SWITCH_REQUEST:
\r
2895 return "TDLS_CHANNEL_SWITCH_REQUEST";
\r
2896 case TDLS_CHANNEL_SWITCH_RESPONSE:
\r
2897 return "TDLS_CHANNEL_SWITCH_RESPONSE";
\r
2898 case TDLS_PEER_PSM_REQUEST:
\r
2899 return "TDLS_PEER_PSM_REQUEST";
\r
2900 case TDLS_PEER_PSM_RESPONSE:
\r
2901 return "TDLS_PEER_PSM_RESPONSE";
\r
2902 case TDLS_PEER_TRAFFIC_RESPONSE:
\r
2903 return "TDLS_PEER_TRAFFIC_RESPONSE";
\r
2904 case TDLS_DISCOVERY_REQUEST:
\r
2905 return "TDLS_DISCOVERY_REQUEST";
\r
2906 case TDLS_DISCOVERY_RESPONSE:
\r
2907 return "TDLS_DISCOVERY_RESPONSE";
\r
2913 #endif /* CONFIG_TDLS */
\r