Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_tdls.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2017 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/14#define _RTW_TDLS_C_1516#include <drv_types.h>17#include <hal_data.h>1819#ifdef CONFIG_TDLS20#define ONE_SEC 1000 /* 1000 ms */2122extern unsigned char MCS_rate_2R[16];23extern unsigned char MCS_rate_1R[16];2425inline void rtw_tdls_set_link_established(_adapter *adapter, bool en)26{27adapter->tdlsinfo.link_established = en;28rtw_mi_update_iface_status(&(adapter->mlmepriv), 0);29}3031void rtw_reset_tdls_info(_adapter *padapter)32{33struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;3435ptdlsinfo->ap_prohibited = _FALSE;3637/* For TDLS channel switch, currently we only allow it to work in wifi logo test mode */38if (padapter->registrypriv.wifi_spec == 1)39ptdlsinfo->ch_switch_prohibited = _FALSE;40else41ptdlsinfo->ch_switch_prohibited = _TRUE;4243rtw_tdls_set_link_established(padapter, _FALSE);44ptdlsinfo->sta_cnt = 0;45ptdlsinfo->sta_maximum = _FALSE;4647#ifdef CONFIG_TDLS_CH_SW48ptdlsinfo->chsw_info.ch_sw_state = TDLS_STATE_NONE;49ATOMIC_SET(&ptdlsinfo->chsw_info.chsw_on, _FALSE);50ptdlsinfo->chsw_info.off_ch_num = 0;51ptdlsinfo->chsw_info.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;52ptdlsinfo->chsw_info.cur_time = 0;53ptdlsinfo->chsw_info.delay_switch_back = _FALSE;54ptdlsinfo->chsw_info.dump_stack = _FALSE;55#endif5657ptdlsinfo->ch_sensing = 0;58ptdlsinfo->watchdog_count = 0;59ptdlsinfo->dev_discovered = _FALSE;6061#ifdef CONFIG_WFD62ptdlsinfo->wfd_info = &padapter->wfd_info;63#endif6465ptdlsinfo->tdls_sctx = NULL;66}6768int rtw_init_tdls_info(_adapter *padapter)69{70int res = _SUCCESS;71struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;7273rtw_reset_tdls_info(padapter);7475#ifdef CONFIG_TDLS_DRIVER_SETUP76ptdlsinfo->driver_setup = _TRUE;77#else78ptdlsinfo->driver_setup = _FALSE;79#endif /* CONFIG_TDLS_DRIVER_SETUP */8081_rtw_spinlock_init(&ptdlsinfo->cmd_lock);82_rtw_spinlock_init(&ptdlsinfo->hdl_lock);8384return res;8586}8788void rtw_free_tdls_info(struct tdls_info *ptdlsinfo)89{90_rtw_spinlock_free(&ptdlsinfo->cmd_lock);91_rtw_spinlock_free(&ptdlsinfo->hdl_lock);9293_rtw_memset(ptdlsinfo, 0, sizeof(struct tdls_info));9495}9697void rtw_free_all_tdls_sta(_adapter *padapter, u8 enqueue_cmd)98{99struct sta_priv *pstapriv = &padapter->stapriv;100struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;101_irqL irqL;102_list *plist, *phead;103s32 index;104struct sta_info *psta = NULL;105struct sta_info *ptdls_sta[NUM_STA];106u8 empty_hwaddr[ETH_ALEN] = { 0x00 };107108_rtw_memset(ptdls_sta, 0x00, sizeof(ptdls_sta));109110_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);111for (index = 0; index < NUM_STA; index++) {112phead = &(pstapriv->sta_hash[index]);113plist = get_next(phead);114115while (rtw_end_of_queue_search(phead, plist) == _FALSE) {116psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);117118plist = get_next(plist);119120if (psta->tdls_sta_state != TDLS_STATE_NONE)121ptdls_sta[index] = psta;122}123}124_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);125126for (index = 0; index < NUM_STA; index++) {127if (ptdls_sta[index]) {128struct TDLSoption_param tdls_param;129130psta = ptdls_sta[index];131132RTW_INFO("Do tear down to "MAC_FMT" by enqueue_cmd = %d\n", MAC_ARG(psta->cmn.mac_addr), enqueue_cmd);133134_rtw_memcpy(&(tdls_param.addr), psta->cmn.mac_addr, ETH_ALEN);135tdls_param.option = TDLS_TEARDOWN_STA_NO_WAIT;136tdls_hdl(padapter, (unsigned char *)&(tdls_param));137138rtw_tdls_teardown_pre_hdl(padapter, psta);139140if (enqueue_cmd == _TRUE)141rtw_tdls_cmd(padapter, psta->cmn.mac_addr, TDLS_TEARDOWN_STA_LOCALLY_POST);142else143{144tdls_param.option = TDLS_TEARDOWN_STA_LOCALLY_POST;145tdls_hdl(padapter, (unsigned char *)&(tdls_param));146}147}148}149}150151int check_ap_tdls_prohibited(u8 *pframe, u8 pkt_len)152{153u8 tdls_prohibited_bit = 0x40; /* bit(38); TDLS_prohibited */154155if (pkt_len < 5)156return _FALSE;157158pframe += 4;159if ((*pframe) & tdls_prohibited_bit)160return _TRUE;161162return _FALSE;163}164165int check_ap_tdls_ch_switching_prohibited(u8 *pframe, u8 pkt_len)166{167u8 tdls_ch_swithcing_prohibited_bit = 0x80; /* bit(39); TDLS_channel_switching prohibited */168169if (pkt_len < 5)170return _FALSE;171172pframe += 4;173if ((*pframe) & tdls_ch_swithcing_prohibited_bit)174return _TRUE;175176return _FALSE;177}178179u8 rtw_is_tdls_enabled(_adapter *padapter)180{181return padapter->registrypriv.en_tdls;182}183184void rtw_set_tdls_enable(_adapter *padapter, u8 enable)185{186padapter->registrypriv.en_tdls = enable;187RTW_INFO("%s: en_tdls = %d\n", __func__, rtw_is_tdls_enabled(padapter));188}189190void rtw_enable_tdls_func(_adapter *padapter)191{192if (rtw_is_tdls_enabled(padapter) == _TRUE)193return;194195#if 0196#ifdef CONFIG_MCC_MODE197if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC) == _TRUE) {198RTW_INFO("[TDLS] MCC is running, can't enable TDLS !\n");199return;200}201#endif202#endif203rtw_set_tdls_enable(padapter, _TRUE);204}205206void rtw_disable_tdls_func(_adapter *padapter, u8 enqueue_cmd)207{208if (rtw_is_tdls_enabled(padapter) == _FALSE)209return;210211rtw_free_all_tdls_sta(padapter, enqueue_cmd);212rtw_tdls_cmd(padapter, NULL, TDLS_RS_RCR);213rtw_reset_tdls_info(padapter);214215rtw_set_tdls_enable(padapter, _FALSE);216}217218u8 rtw_is_tdls_sta_existed(_adapter *padapter)219{220struct sta_priv *pstapriv = &padapter->stapriv;221struct sta_info *psta;222int i = 0;223_irqL irqL;224_list *plist, *phead;225u8 ret = _FALSE;226227if (rtw_is_tdls_enabled(padapter) == _FALSE)228return _FALSE;229230_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);231232for (i = 0; i < NUM_STA; i++) {233phead = &(pstapriv->sta_hash[i]);234plist = get_next(phead);235while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {236psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);237plist = get_next(plist);238if (psta->tdls_sta_state != TDLS_STATE_NONE) {239ret = _TRUE;240goto Exit;241}242}243}244245Exit:246247_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);248249return ret;250}251252u8 rtw_tdls_is_setup_allowed(_adapter *padapter)253{254struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;255256if (is_client_associated_to_ap(padapter) == _FALSE)257return _FALSE;258259if (ptdlsinfo->ap_prohibited == _TRUE)260return _FALSE;261262return _TRUE;263}264265#ifdef CONFIG_TDLS_CH_SW266u8 rtw_tdls_is_chsw_allowed(_adapter *padapter)267{268struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;269270if (ptdlsinfo->ch_switch_prohibited == _TRUE)271return _FALSE;272273if (padapter->registrypriv.wifi_spec == 0)274return _FALSE;275276return _TRUE;277}278#endif279280int _issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ms)281{282int ret = _FAIL;283struct xmit_frame *pmgntframe;284struct pkt_attrib *pattrib;285unsigned char *pframe;286struct rtw_ieee80211_hdr *pwlanhdr;287unsigned short *fctrl, *qc;288struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);289struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);290struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);291292pmgntframe = alloc_mgtxmitframe(pxmitpriv);293if (pmgntframe == NULL)294goto exit;295296pattrib = &pmgntframe->attrib;297update_mgntframe_attrib(padapter, pattrib);298299pattrib->hdrlen += 2;300pattrib->qos_en = _TRUE;301pattrib->eosp = 1;302pattrib->ack_policy = 0;303pattrib->mdata = 0;304pattrib->retry_ctrl = _FALSE;305306_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);307308pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;309pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;310311fctrl = &(pwlanhdr->frame_ctl);312*(fctrl) = 0;313314if (power_mode)315SetPwrMgt(fctrl);316317qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);318319SetPriority(qc, 7); /* Set priority to VO */320321SetEOSP(qc, pattrib->eosp);322323SetAckpolicy(qc, pattrib->ack_policy);324325_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);326_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);327_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);328329SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);330pmlmeext->mgnt_seq++;331set_frame_sub_type(pframe, WIFI_QOS_DATA_NULL);332333pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);334pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);335336pattrib->last_txcmdsz = pattrib->pktlen;337338if (wait_ms)339ret = dump_mgntframe_and_wait_ack_timeout(padapter, pmgntframe, wait_ms);340else {341dump_mgntframe(padapter, pmgntframe);342ret = _SUCCESS;343}344345exit:346return ret;347348}349350/*351*wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT352*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 TX353*try_cnt means the maximal TX count to try354*/355int issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)356{357int ret;358int i = 0;359systime start = rtw_get_current_time();360struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);361struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);362363#if 0364psta = rtw_get_stainfo(&padapter->stapriv, da);365if (psta) {366if (power_mode)367rtw_hal_macid_sleep(padapter, psta->cmn.mac_id);368else369rtw_hal_macid_wakeup(padapter, psta->cmn.mac_id);370} else {371RTW_INFO(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",372FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode ? "sleep" : "wakeup");373rtw_warn_on(1);374}375#endif376377do {378ret = _issue_nulldata_to_TDLS_peer_STA(padapter, da, power_mode, wait_ms);379380i++;381382if (RTW_CANNOT_RUN(padapter))383break;384385if (i < try_cnt && wait_ms > 0 && ret == _FAIL)386rtw_msleep_os(wait_ms);387388} while ((i < try_cnt) && (ret == _FAIL || wait_ms == 0));389390if (ret != _FAIL) {391ret = _SUCCESS;392#ifndef DBG_XMIT_ACK393goto exit;394#endif395}396397if (try_cnt && wait_ms) {398if (da)399RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",400FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),401ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));402else403RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",404FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),405ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));406}407exit:408return ret;409}410411/* TDLS encryption(if needed) will always be CCMP */412void rtw_tdls_set_key(_adapter *padapter, struct sta_info *ptdls_sta)413{414ptdls_sta->dot118021XPrivacy = _AES_;415rtw_setstakey_cmd(padapter, ptdls_sta, TDLS_KEY, _TRUE);416}417418#ifdef CONFIG_80211N_HT419void rtw_tdls_process_ht_cap(_adapter *padapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)420{421struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;422struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);423struct mlme_priv *pmlmepriv = &padapter->mlmepriv;424struct ht_priv *phtpriv = &pmlmepriv->htpriv;425u8 max_AMPDU_len, min_MPDU_spacing;426u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, cur_beamform_cap = 0;427428/* Save HT capabilities in the sta object */429_rtw_memset(&ptdls_sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));430if (data && Length >= sizeof(struct rtw_ieee80211_ht_cap)) {431ptdls_sta->flags |= WLAN_STA_HT;432ptdls_sta->flags |= WLAN_STA_WME;433434_rtw_memcpy(&ptdls_sta->htpriv.ht_cap, data, sizeof(struct rtw_ieee80211_ht_cap));435} else {436ptdls_sta->flags &= ~WLAN_STA_HT;437return;438}439440if (ptdls_sta->flags & WLAN_STA_HT) {441if (padapter->registrypriv.ht_enable == _TRUE && is_supported_ht(padapter->registrypriv.wireless_mode) ) {442ptdls_sta->htpriv.ht_option = _TRUE;443ptdls_sta->qos_option = _TRUE;444} else {445ptdls_sta->htpriv.ht_option = _FALSE;446ptdls_sta->qos_option = _FALSE;447}448}449450/* HT related cap */451if (ptdls_sta->htpriv.ht_option) {452/* Check if sta supports rx ampdu */453if (padapter->registrypriv.ampdu_enable == 1)454ptdls_sta->htpriv.ampdu_enable = _TRUE;455456/* AMPDU Parameters field */457/* Get MIN of MAX AMPDU Length Exp */458if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (data[2] & 0x3))459max_AMPDU_len = (data[2] & 0x3);460else461max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);462/* Get MAX of MIN MPDU Start Spacing */463if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (data[2] & 0x1c))464min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);465else466min_MPDU_spacing = (data[2] & 0x1c);467ptdls_sta->htpriv.rx_ampdu_min_spacing = max_AMPDU_len | min_MPDU_spacing;468469/* Check if sta support s Short GI 20M */470if ((phtpriv->sgi_20m == _TRUE) && (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_20)))471ptdls_sta->htpriv.sgi_20m = _TRUE;472473/* Check if sta support s Short GI 40M */474if ((phtpriv->sgi_40m == _TRUE) && (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)))475ptdls_sta->htpriv.sgi_40m = _TRUE;476477/* Bwmode would still followed AP's setting */478if (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) {479if (padapter->mlmeextpriv.cur_bwmode >= CHANNEL_WIDTH_40)480ptdls_sta->cmn.bw_mode = CHANNEL_WIDTH_40;481ptdls_sta->htpriv.ch_offset = padapter->mlmeextpriv.cur_ch_offset;482}483484/* Config LDPC Coding Capability */485if (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX) && GET_HT_CAP_ELE_LDPC_CAP(data)) {486SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));487RTW_INFO("Enable HT Tx LDPC!\n");488}489ptdls_sta->htpriv.ldpc_cap = cur_ldpc_cap;490491/* Config STBC setting */492if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX) && GET_HT_CAP_ELE_RX_STBC(data)) {493SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX));494RTW_INFO("Enable HT Tx STBC!\n");495}496ptdls_sta->htpriv.stbc_cap = cur_stbc_cap;497498#ifdef CONFIG_BEAMFORMING499/* Config Tx beamforming setting */500if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) &&501GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(data))502SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);503504if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&505GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(data))506SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);507ptdls_sta->htpriv.beamform_cap = cur_beamform_cap;508if (cur_beamform_cap)509RTW_INFO("Client HT Beamforming Cap = 0x%02X\n", cur_beamform_cap);510#endif /* CONFIG_BEAMFORMING */511}512513}514515u8 *rtw_tdls_set_ht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)516{517rtw_ht_use_default_setting(padapter);518519if (padapter->registrypriv.wifi_spec == 1) {520padapter->mlmepriv.htpriv.sgi_20m = _FALSE;521padapter->mlmepriv.htpriv.sgi_40m = _FALSE;522}523524rtw_restructure_ht_ie(padapter, NULL, pframe, 0, &(pattrib->pktlen), padapter->mlmeextpriv.cur_channel);525526return pframe + pattrib->pktlen;527}528#endif529530#ifdef CONFIG_80211AC_VHT531void rtw_tdls_process_vht_cap(_adapter *padapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)532{533struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);534struct mlme_priv *pmlmepriv = &padapter->mlmepriv;535struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;536u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, tx_nss = 0;537u16 cur_beamform_cap = 0;538u8 *pcap_mcs;539540_rtw_memset(&ptdls_sta->vhtpriv, 0, sizeof(struct vht_priv));541if (data && Length == 12) {542ptdls_sta->flags |= WLAN_STA_VHT;543544_rtw_memcpy(ptdls_sta->vhtpriv.vht_cap, data, 12);545546#if 0547if (elems.vht_op_mode_notify && elems.vht_op_mode_notify_len == 1)548_rtw_memcpy(&pstat->vhtpriv.vht_op_mode_notify, elems.vht_op_mode_notify, 1);549else /* for Frame without Operating Mode notify ie; default: 80M */550pstat->vhtpriv.vht_op_mode_notify = CHANNEL_WIDTH_80;551#else552ptdls_sta->vhtpriv.vht_op_mode_notify = CHANNEL_WIDTH_80;553#endif554} else {555ptdls_sta->flags &= ~WLAN_STA_VHT;556return;557}558559if (ptdls_sta->flags & WLAN_STA_VHT) {560if (REGSTY_IS_11AC_ENABLE(&padapter->registrypriv)561&& is_supported_vht(padapter->registrypriv.wireless_mode)562&& (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent))) {563ptdls_sta->vhtpriv.vht_option = _TRUE;564ptdls_sta->cmn.ra_info.is_vht_enable = _TRUE;565}566else567ptdls_sta->vhtpriv.vht_option = _FALSE;568}569570/* B4 Rx LDPC */571if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX) &&572GET_VHT_CAPABILITY_ELE_RX_LDPC(data)) {573SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));574RTW_INFO("Current VHT LDPC Setting = %02X\n", cur_ldpc_cap);575}576ptdls_sta->vhtpriv.ldpc_cap = cur_ldpc_cap;577578/* B5 Short GI for 80 MHz */579ptdls_sta->vhtpriv.sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(data) & pvhtpriv->sgi_80m) ? _TRUE : _FALSE;580581/* B8 B9 B10 Rx STBC */582if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX) &&583GET_VHT_CAPABILITY_ELE_RX_STBC(data)) {584SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));585RTW_INFO("Current VHT STBC Setting = %02X\n", cur_stbc_cap);586}587ptdls_sta->vhtpriv.stbc_cap = cur_stbc_cap;588589#ifdef CONFIG_BEAMFORMING590/* B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee */591if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&592GET_VHT_CAPABILITY_ELE_SU_BFEE(data))593SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);594595/* B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer */596if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&597GET_VHT_CAPABILITY_ELE_SU_BFER(data))598SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);599ptdls_sta->vhtpriv.beamform_cap = cur_beamform_cap;600ptdls_sta->cmn.bf_info.vht_beamform_cap = cur_beamform_cap;601if (cur_beamform_cap)602RTW_INFO("Current VHT Beamforming Setting = %02X\n", cur_beamform_cap);603#endif /*CONFIG_BEAMFORMING*/604605/* B23 B24 B25 Maximum A-MPDU Length Exponent */606ptdls_sta->vhtpriv.ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(data);607608pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(data);609tx_nss = GET_HAL_TX_NSS(padapter);610rtw_vht_nss_to_mcsmap(tx_nss, ptdls_sta->vhtpriv.vht_mcs_map, pcap_mcs);611ptdls_sta->vhtpriv.vht_highest_rate = rtw_get_vht_highest_rate(ptdls_sta->vhtpriv.vht_mcs_map);612}613614void rtw_tdls_process_vht_operation(_adapter *padapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)615{616struct mlme_priv *pmlmepriv = &padapter->mlmepriv;617struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;618struct registry_priv *regsty = adapter_to_regsty(padapter);619u8 operation_bw = 0;620621if (GET_VHT_OPERATION_ELE_CHL_WIDTH(data) >= 1) {622623operation_bw = CHANNEL_WIDTH_80;624625if (hal_is_bw_support(padapter, operation_bw) && REGSTY_IS_BW_5G_SUPPORT(regsty, operation_bw)626&& (operation_bw <= pmlmeext->cur_bwmode))627ptdls_sta->cmn.bw_mode = operation_bw;628else629ptdls_sta->cmn.bw_mode = pmlmeext->cur_bwmode;630} else631ptdls_sta->cmn.bw_mode = pmlmeext->cur_bwmode;632}633634void rtw_tdls_process_vht_op_mode_notify(_adapter *padapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)635{636struct mlme_priv *pmlmepriv = &padapter->mlmepriv;637struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;638struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;639struct registry_priv *regsty = adapter_to_regsty(padapter);640u8 target_bw;641u8 target_rxss, current_rxss;642643if (pvhtpriv->vht_option == _FALSE)644return;645646target_bw = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(data);647target_rxss = (GET_VHT_OPERATING_MODE_FIELD_RX_NSS(data) + 1);648649if (hal_is_bw_support(padapter, target_bw) && REGSTY_IS_BW_5G_SUPPORT(regsty, target_bw)650&& (target_bw <= pmlmeext->cur_bwmode))651ptdls_sta->cmn.bw_mode = target_bw;652else653ptdls_sta->cmn.bw_mode = pmlmeext->cur_bwmode;654655current_rxss = rtw_vht_mcsmap_to_nss(ptdls_sta->vhtpriv.vht_mcs_map);656if (target_rxss != current_rxss) {657u8 vht_mcs_map[2] = {};658659rtw_vht_nss_to_mcsmap(target_rxss, vht_mcs_map, ptdls_sta->vhtpriv.vht_mcs_map);660_rtw_memcpy(ptdls_sta->vhtpriv.vht_mcs_map, vht_mcs_map, 2);661}662}663664u8 *rtw_tdls_set_aid(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)665{666return rtw_set_ie(pframe, EID_AID, 2, (u8 *)&(padapter->mlmepriv.cur_network.aid), &(pattrib->pktlen));667}668669u8 *rtw_tdls_set_vht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)670{671u32 ie_len = 0;672673rtw_vht_use_default_setting(padapter);674675ie_len = rtw_build_vht_cap_ie(padapter, pframe);676pattrib->pktlen += ie_len;677678return pframe + ie_len;679}680681u8 *rtw_tdls_set_vht_operation(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib, u8 channel)682{683u32 ie_len = 0;684685ie_len = rtw_build_vht_operation_ie(padapter, pframe, channel);686pattrib->pktlen += ie_len;687688return pframe + ie_len;689}690691u8 *rtw_tdls_set_vht_op_mode_notify(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib, u8 bw)692{693u32 ie_len = 0;694695ie_len = rtw_build_vht_op_mode_notify_ie(padapter, pframe, bw);696pattrib->pktlen += ie_len;697698return pframe + ie_len;699}700#endif701702703u8 *rtw_tdls_set_sup_ch(_adapter *adapter, u8 *pframe, struct pkt_attrib *pattrib)704{705struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);706u8 sup_ch[30 * 2] = {0x00}, ch_set_idx = 0, sup_ch_idx = 2;707708while (ch_set_idx < rfctl->max_chan_nums && rfctl->channel_set[ch_set_idx].ChannelNum != 0) {709if (rfctl->channel_set[ch_set_idx].ChannelNum <= 14) {710/* TODO: fix 2.4G supported channel when channel doesn't start from 1 and continuous */711sup_ch[0] = 1; /* First channel number */712sup_ch[1] = rfctl->channel_set[ch_set_idx].ChannelNum; /* Number of channel */713} else {714sup_ch[sup_ch_idx++] = rfctl->channel_set[ch_set_idx].ChannelNum;715sup_ch[sup_ch_idx++] = 1;716}717ch_set_idx++;718}719720return rtw_set_ie(pframe, _SUPPORTED_CH_IE_, sup_ch_idx, sup_ch, &(pattrib->pktlen));721}722723u8 *rtw_tdls_set_rsnie(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, int init, struct sta_info *ptdls_sta)724{725u8 *p = NULL;726int len = 0;727728if (ptxmgmt->len > 0)729p = rtw_get_ie(ptxmgmt->buf, _RSN_IE_2_, &len, ptxmgmt->len);730731if (p != NULL)732return rtw_set_ie(pframe, _RSN_IE_2_, len, p + 2, &(pattrib->pktlen));733else if (init == _TRUE)734return rtw_set_ie(pframe, _RSN_IE_2_, sizeof(TDLS_RSNIE), TDLS_RSNIE, &(pattrib->pktlen));735else736return rtw_set_ie(pframe, _RSN_IE_2_, sizeof(ptdls_sta->TDLS_RSNIE), ptdls_sta->TDLS_RSNIE, &(pattrib->pktlen));737}738739u8 *rtw_tdls_set_ext_cap(u8 *pframe, struct pkt_attrib *pattrib)740{741return rtw_set_ie(pframe, _EXT_CAP_IE_ , sizeof(TDLS_EXT_CAPIE), TDLS_EXT_CAPIE, &(pattrib->pktlen));742}743744u8 *rtw_tdls_set_qos_cap(u8 *pframe, struct pkt_attrib *pattrib)745{746return rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(TDLS_WMMIE), TDLS_WMMIE, &(pattrib->pktlen));747}748749u8 *rtw_tdls_set_ftie(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, u8 *ANonce, u8 *SNonce)750{751struct wpa_tdls_ftie FTIE = {0};752u8 *p = NULL;753int len = 0;754755if (ptxmgmt->len > 0)756p = rtw_get_ie(ptxmgmt->buf, _FTIE_, &len, ptxmgmt->len);757758if (p != NULL)759return rtw_set_ie(pframe, _FTIE_, len, p + 2, &(pattrib->pktlen));760else {761if (ANonce != NULL)762_rtw_memcpy(FTIE.Anonce, ANonce, WPA_NONCE_LEN);763if (SNonce != NULL)764_rtw_memcpy(FTIE.Snonce, SNonce, WPA_NONCE_LEN);765766return rtw_set_ie(pframe, _FTIE_, TDLS_FTIE_DATA_LEN,767(u8 *)FTIE.data, &(pattrib->pktlen));768}769}770771u8 *rtw_tdls_set_timeout_interval(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, int init, struct sta_info *ptdls_sta)772{773u8 timeout_itvl[5]; /* set timeout interval to maximum value */774u32 timeout_interval = TDLS_TPK_RESEND_COUNT;775u8 *p = NULL;776int len = 0;777778if (ptxmgmt->len > 0)779p = rtw_get_ie(ptxmgmt->buf, _TIMEOUT_ITVL_IE_, &len, ptxmgmt->len);780781if (p != NULL)782return rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, len, p + 2, &(pattrib->pktlen));783else {784/* Timeout interval */785timeout_itvl[0] = 0x02;786if (init == _TRUE)787_rtw_memcpy(timeout_itvl + 1, &timeout_interval, 4);788else789_rtw_memcpy(timeout_itvl + 1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);790791return rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));792}793}794795u8 *rtw_tdls_set_bss_coexist(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)796{797u8 iedata = 0;798799if (padapter->mlmepriv.num_FortyMHzIntolerant > 0)800iedata |= BIT(2); /* 20 MHz BSS Width Request */801802/* Information Bit should be set by TDLS test plan 5.9 */803iedata |= BIT(0);804return rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));805}806807u8 *rtw_tdls_set_payload_type(u8 *pframe, struct pkt_attrib *pattrib)808{809u8 payload_type = 0x02;810return rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));811}812813u8 *rtw_tdls_set_category(u8 *pframe, struct pkt_attrib *pattrib, u8 category)814{815return rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));816}817818u8 *rtw_tdls_set_action(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)819{820return rtw_set_fixed_ie(pframe, 1, &(ptxmgmt->action_code), &(pattrib->pktlen));821}822823u8 *rtw_tdls_set_status_code(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)824{825return rtw_set_fixed_ie(pframe, 2, (u8 *)&(ptxmgmt->status_code), &(pattrib->pktlen));826}827828u8 *rtw_tdls_set_dialog(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)829{830u8 dialogtoken = 1;831if (ptxmgmt->dialog_token)832return rtw_set_fixed_ie(pframe, 1, &(ptxmgmt->dialog_token), &(pattrib->pktlen));833else834return rtw_set_fixed_ie(pframe, 1, &(dialogtoken), &(pattrib->pktlen));835}836837u8 *rtw_tdls_set_reg_class(u8 *pframe, struct pkt_attrib *pattrib, struct sta_info *ptdls_sta)838{839u8 reg_class = 22;840return rtw_set_fixed_ie(pframe, 1, &(reg_class), &(pattrib->pktlen));841}842843u8 *rtw_tdls_set_second_channel_offset(u8 *pframe, struct pkt_attrib *pattrib, u8 ch_offset)844{845return rtw_set_ie(pframe, EID_SecondaryChnlOffset , 1, &ch_offset, &(pattrib->pktlen));846}847848u8 *rtw_tdls_set_capability(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)849{850struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;851struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;852u8 cap_from_ie[2] = {0};853854_rtw_memcpy(cap_from_ie, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);855856return rtw_set_fixed_ie(pframe, 2, cap_from_ie, &(pattrib->pktlen));857}858859u8 *rtw_tdls_set_supported_rate(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)860{861u8 bssrate[NDIS_802_11_LENGTH_RATES_EX];862int bssrate_len = 0;863u8 more_supportedrates = 0;864865rtw_set_supported_rate(bssrate, (padapter->registrypriv.wireless_mode == WIRELESS_MODE_MAX) ? padapter->mlmeextpriv.cur_wireless_mode : padapter->registrypriv.wireless_mode);866bssrate_len = rtw_get_rateset_len(bssrate);867868if (bssrate_len > 8) {869pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));870more_supportedrates = 1;871} else872pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));873874/* extended supported rates */875if (more_supportedrates == 1)876pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));877878return pframe;879}880881u8 *rtw_tdls_set_sup_reg_class(u8 *pframe, struct pkt_attrib *pattrib)882{883return rtw_set_ie(pframe, _SRC_IE_ , sizeof(TDLS_SRC), TDLS_SRC, &(pattrib->pktlen));884}885886u8 *rtw_tdls_set_linkid(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib, u8 init)887{888struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);889struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);890891u8 link_id_addr[18] = {0};892893_rtw_memcpy(link_id_addr, get_my_bssid(&(pmlmeinfo->network)), 6);894895if (init == _TRUE) {896_rtw_memcpy((link_id_addr + 6), pattrib->src, 6);897_rtw_memcpy((link_id_addr + 12), pattrib->dst, 6);898} else {899_rtw_memcpy((link_id_addr + 6), pattrib->dst, 6);900_rtw_memcpy((link_id_addr + 12), pattrib->src, 6);901}902return rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));903}904905#ifdef CONFIG_TDLS_CH_SW906u8 *rtw_tdls_set_target_ch(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)907{908u8 target_ch = 1;909if (padapter->tdlsinfo.chsw_info.off_ch_num)910return rtw_set_fixed_ie(pframe, 1, &(padapter->tdlsinfo.chsw_info.off_ch_num), &(pattrib->pktlen));911else912return rtw_set_fixed_ie(pframe, 1, &(target_ch), &(pattrib->pktlen));913}914915u8 *rtw_tdls_set_ch_sw(u8 *pframe, struct pkt_attrib *pattrib, struct sta_info *ptdls_sta)916{917u8 ch_switch_timing[4] = {0};918u16 switch_time = (ptdls_sta->ch_switch_time >= TDLS_CH_SWITCH_TIME * 1000) ?919ptdls_sta->ch_switch_time : TDLS_CH_SWITCH_TIME;920u16 switch_timeout = (ptdls_sta->ch_switch_timeout >= TDLS_CH_SWITCH_TIMEOUT * 1000) ?921ptdls_sta->ch_switch_timeout : TDLS_CH_SWITCH_TIMEOUT;922923_rtw_memcpy(ch_switch_timing, &switch_time, 2);924_rtw_memcpy(ch_switch_timing + 2, &switch_timeout, 2);925926return rtw_set_ie(pframe, _CH_SWITCH_TIMING_, 4, ch_switch_timing, &(pattrib->pktlen));927}928929void rtw_tdls_set_ch_sw_oper_control(_adapter *padapter, u8 enable)930{931HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);932933if (enable == _TRUE) {934#ifdef CONFIG_TDLS_CH_SW_V2935pHalData->ch_switch_offload = _TRUE;936#endif937938#ifdef CONFIG_TDLS_CH_SW_BY_DRV939pHalData->ch_switch_offload = _FALSE;940#endif941}942else943pHalData->ch_switch_offload = _FALSE;944945if (ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on) != enable)946ATOMIC_SET(&padapter->tdlsinfo.chsw_info.chsw_on, enable);947948rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_BCN_EARLY_C2H_RPT, &enable);949RTW_INFO("[TDLS] %s Bcn Early C2H Report\n", (enable == _TRUE) ? "Start" : "Stop");950}951952void rtw_tdls_ch_sw_back_to_base_chnl(_adapter *padapter)953{954struct mlme_priv *pmlmepriv;955struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;956957pmlmepriv = &padapter->mlmepriv;958959if ((ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE) &&960(padapter->mlmeextpriv.cur_channel != rtw_get_oper_ch(padapter)))961rtw_tdls_cmd(padapter, pchsw_info->addr, TDLS_CH_SW_TO_BASE_CHNL_UNSOLICITED);962}963964static void rtw_tdls_chsw_oper_init(_adapter *padapter, u32 timeout_ms)965{966struct submit_ctx *chsw_sctx = &padapter->tdlsinfo.chsw_info.chsw_sctx;967968rtw_sctx_init(chsw_sctx, timeout_ms);969}970971static int rtw_tdls_chsw_oper_wait(_adapter *padapter)972{973struct submit_ctx *chsw_sctx = &padapter->tdlsinfo.chsw_info.chsw_sctx;974975return rtw_sctx_wait(chsw_sctx, __func__);976}977978void rtw_tdls_chsw_oper_done(_adapter *padapter)979{980struct submit_ctx *chsw_sctx = &padapter->tdlsinfo.chsw_info.chsw_sctx;981982rtw_sctx_done(&chsw_sctx);983}984985s32 rtw_tdls_do_ch_sw(_adapter *padapter, struct sta_info *ptdls_sta, u8 chnl_type, u8 channel, u8 channel_offset, u16 bwmode, u16 ch_switch_time)986{987HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);988u8 center_ch, chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;989u32 ch_sw_time_start, ch_sw_time_spent, wait_time;990u8 take_care_iqk;991s32 ret = _FAIL;992993ch_sw_time_start = rtw_systime_to_ms(rtw_get_current_time());994995/* set mac_id sleep before channel switch */996rtw_hal_macid_sleep(padapter, ptdls_sta->cmn.mac_id);997998#if defined(CONFIG_TDLS_CH_SW_BY_DRV) || defined(CONFIG_TDLS_CH_SW_V2)999set_channel_bwmode(padapter, channel, channel_offset, bwmode);1000ret = _SUCCESS;1001#else1002rtw_tdls_chsw_oper_init(padapter, TDLS_CH_SWITCH_OPER_OFFLOAD_TIMEOUT);10031004/* channel switch IOs offload to FW */1005if (rtw_hal_ch_sw_oper_offload(padapter, channel, channel_offset, bwmode) == _SUCCESS) {1006if (rtw_tdls_chsw_oper_wait(padapter) == _SUCCESS) {1007/* set channel and bw related variables in driver */1008_enter_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);10091010rtw_set_oper_ch(padapter, channel);1011rtw_set_oper_choffset(padapter, channel_offset);1012rtw_set_oper_bw(padapter, bwmode);10131014center_ch = rtw_get_center_ch(channel, bwmode, channel_offset);1015pHalData->current_channel = center_ch;1016pHalData->CurrentCenterFrequencyIndex1 = center_ch;1017pHalData->current_channel_bw = bwmode;1018pHalData->nCur40MhzPrimeSC = channel_offset;10191020if (bwmode == CHANNEL_WIDTH_80) {1021if (center_ch > channel)1022chnl_offset80 = HAL_PRIME_CHNL_OFFSET_LOWER;1023else if (center_ch < channel)1024chnl_offset80 = HAL_PRIME_CHNL_OFFSET_UPPER;1025else1026chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;1027}1028pHalData->nCur80MhzPrimeSC = chnl_offset80;10291030pHalData->CurrentCenterFrequencyIndex1 = center_ch;10311032_exit_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);10331034rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk);1035if (take_care_iqk == _TRUE)1036rtw_hal_ch_sw_iqk_info_restore(padapter, CH_SW_USE_CASE_TDLS);10371038ret = _SUCCESS;1039} else1040RTW_INFO("[TDLS] chsw oper wait fail !!\n");1041}1042#endif10431044if (ret == _SUCCESS) {1045ch_sw_time_spent = rtw_systime_to_ms(rtw_get_current_time()) - ch_sw_time_start;1046if (chnl_type == TDLS_CH_SW_OFF_CHNL) {1047if ((u32)ch_switch_time / 1000 > ch_sw_time_spent)1048wait_time = (u32)ch_switch_time / 1000 - ch_sw_time_spent;1049else1050wait_time = 0;10511052if (wait_time > 0)1053rtw_msleep_os(wait_time);1054}1055}10561057/* set mac_id wakeup after channel switch */1058rtw_hal_macid_wakeup(padapter, ptdls_sta->cmn.mac_id);10591060return ret;1061}1062#endif10631064u8 *rtw_tdls_set_wmm_params(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)1065{1066struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);1067struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1068u8 wmm_param_ele[24] = {0};10691070if (&pmlmeinfo->WMM_param) {1071_rtw_memcpy(wmm_param_ele, WMM_PARA_OUI, 6);1072if (_rtw_memcmp(&pmlmeinfo->WMM_param, &wmm_param_ele[6], 18) == _TRUE)1073/* Use default WMM Param */1074_rtw_memcpy(wmm_param_ele + 6, (u8 *)&TDLS_WMM_PARAM_IE, sizeof(TDLS_WMM_PARAM_IE));1075else1076_rtw_memcpy(wmm_param_ele + 6, (u8 *)&pmlmeinfo->WMM_param, sizeof(pmlmeinfo->WMM_param));1077return rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 24, wmm_param_ele, &(pattrib->pktlen));1078} else1079return pframe;1080}10811082#ifdef CONFIG_WFD1083void rtw_tdls_process_wfd_ie(struct tdls_info *ptdlsinfo, u8 *ptr, u8 length)1084{1085u8 *wfd_ie;1086u32 wfd_ielen = 0;10871088if (!hal_chk_wl_func(tdls_info_to_adapter(ptdlsinfo), WL_FUNC_MIRACAST))1089return;10901091/* Try to get the TCP port information when receiving the negotiation response. */10921093wfd_ie = rtw_get_wfd_ie(ptr, length, NULL, &wfd_ielen);1094while (wfd_ie) {1095u8 *attr_content;1096u32 attr_contentlen = 0;1097int i;10981099RTW_INFO("[%s] WFD IE Found!!\n", __FUNCTION__);1100attr_content = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &attr_contentlen);1101if (attr_content && attr_contentlen) {1102ptdlsinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16(attr_content + 2);1103RTW_INFO("[%s] Peer PORT NUM = %d\n", __FUNCTION__, ptdlsinfo->wfd_info->peer_rtsp_ctrlport);1104}11051106attr_content = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_LOCAL_IP_ADDR, NULL, &attr_contentlen);1107if (attr_content && attr_contentlen) {1108_rtw_memcpy(ptdlsinfo->wfd_info->peer_ip_address, (attr_content + 1), 4);1109RTW_INFO("[%s] Peer IP = %02u.%02u.%02u.%02u\n", __FUNCTION__,1110ptdlsinfo->wfd_info->peer_ip_address[0], ptdlsinfo->wfd_info->peer_ip_address[1],1111ptdlsinfo->wfd_info->peer_ip_address[2], ptdlsinfo->wfd_info->peer_ip_address[3]);1112}11131114wfd_ie = rtw_get_wfd_ie(wfd_ie + wfd_ielen, (ptr + length) - (wfd_ie + wfd_ielen), NULL, &wfd_ielen);1115}1116}11171118int issue_tunneled_probe_req(_adapter *padapter)1119{1120struct xmit_frame *pmgntframe;1121struct pkt_attrib *pattrib;1122struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1123struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1124u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};1125struct tdls_txmgmt txmgmt;1126int ret = _FAIL;11271128RTW_INFO("[%s]\n", __FUNCTION__);11291130_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));1131txmgmt.action_code = TUNNELED_PROBE_REQ;11321133pmgntframe = alloc_mgtxmitframe(pxmitpriv);1134if (pmgntframe == NULL)1135goto exit;11361137pattrib = &pmgntframe->attrib;11381139pmgntframe->frame_tag = DATA_FRAMETAG;1140pattrib->ether_type = 0x890d;11411142_rtw_memcpy(pattrib->dst, baddr, ETH_ALEN);1143_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);1144_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);1145_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);11461147update_tdls_attrib(padapter, pattrib);1148pattrib->qsel = pattrib->priority;1149if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {1150rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1151rtw_free_xmitframe(pxmitpriv, pmgntframe);1152goto exit;1153}1154dump_mgntframe(padapter, pmgntframe);1155ret = _SUCCESS;1156exit:11571158return ret;1159}11601161int issue_tunneled_probe_rsp(_adapter *padapter, union recv_frame *precv_frame)1162{1163struct xmit_frame *pmgntframe;1164struct pkt_attrib *pattrib;1165struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1166struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1167struct tdls_txmgmt txmgmt;1168int ret = _FAIL;11691170RTW_INFO("[%s]\n", __FUNCTION__);11711172_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));1173txmgmt.action_code = TUNNELED_PROBE_RSP;11741175pmgntframe = alloc_mgtxmitframe(pxmitpriv);1176if (pmgntframe == NULL)1177goto exit;11781179pattrib = &pmgntframe->attrib;11801181pmgntframe->frame_tag = DATA_FRAMETAG;1182pattrib->ether_type = 0x890d;11831184_rtw_memcpy(pattrib->dst, precv_frame->u.hdr.attrib.src, ETH_ALEN);1185_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);1186_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);1187_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);11881189update_tdls_attrib(padapter, pattrib);1190pattrib->qsel = pattrib->priority;1191if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {1192rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1193rtw_free_xmitframe(pxmitpriv, pmgntframe);1194goto exit;1195}1196dump_mgntframe(padapter, pmgntframe);1197ret = _SUCCESS;1198exit:11991200return ret;1201}1202#endif /* CONFIG_WFD */12031204int issue_tdls_setup_req(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, int wait_ack)1205{1206struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;1207struct xmit_frame *pmgntframe;1208struct pkt_attrib *pattrib;1209struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1210struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1211struct sta_priv *pstapriv = &padapter->stapriv;1212struct sta_info *ptdls_sta = NULL;1213_irqL irqL;1214int ret = _FAIL;1215/* Retry timer should be set at least 301 sec, using TPK_count counting 301 times. */1216u32 timeout_interval = TDLS_TPK_RESEND_COUNT;12171218RTW_INFO("[TDLS] %s\n", __FUNCTION__);12191220if (rtw_tdls_is_setup_allowed(padapter) == _FALSE)1221goto exit;12221223if (IS_MCAST(ptxmgmt->peer))1224goto exit;12251226ptdls_sta = rtw_get_stainfo(pstapriv, ptxmgmt->peer);1227if (ptdlsinfo->sta_maximum == _TRUE) {1228if (ptdls_sta == NULL)1229goto exit;1230else if (!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))1231goto exit;1232}12331234pmgntframe = alloc_mgtxmitframe(pxmitpriv);1235if (pmgntframe == NULL)1236goto exit;12371238if (ptdls_sta == NULL) {1239ptdls_sta = rtw_alloc_stainfo(pstapriv, ptxmgmt->peer);1240if (ptdls_sta == NULL) {1241RTW_INFO("[%s] rtw_alloc_stainfo fail\n", __FUNCTION__);1242rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1243rtw_free_xmitframe(pxmitpriv, pmgntframe);1244goto exit;1245}1246ptdlsinfo->sta_cnt++;1247}12481249ptxmgmt->action_code = TDLS_SETUP_REQUEST;12501251pattrib = &pmgntframe->attrib;1252pmgntframe->frame_tag = DATA_FRAMETAG;1253pattrib->ether_type = 0x890d;12541255_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);1256_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);1257_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);1258_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);12591260update_tdls_attrib(padapter, pattrib);12611262if (ptdlsinfo->sta_cnt == MAX_ALLOWED_TDLS_STA_NUM)1263ptdlsinfo->sta_maximum = _TRUE;12641265ptdls_sta->tdls_sta_state |= TDLS_RESPONDER_STATE;12661267if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {1268ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;1269_set_timer(&ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);1270}12711272pattrib->qsel = pattrib->priority;12731274if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {1275rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1276rtw_free_xmitframe(pxmitpriv, pmgntframe);1277goto exit;1278}12791280if (wait_ack)1281ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);1282else {1283dump_mgntframe(padapter, pmgntframe);1284ret = _SUCCESS;1285}12861287exit:12881289return ret;1290}12911292int _issue_tdls_teardown(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, struct sta_info *ptdls_sta, u8 wait_ack)1293{1294struct xmit_frame *pmgntframe;1295struct pkt_attrib *pattrib;1296struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1297struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1298struct sta_priv *pstapriv = &padapter->stapriv;1299_irqL irqL;1300int ret = _FAIL;13011302RTW_INFO("[TDLS] %s\n", __FUNCTION__);13031304ptxmgmt->action_code = TDLS_TEARDOWN;13051306pmgntframe = alloc_mgtxmitframe(pxmitpriv);1307if (pmgntframe == NULL)1308goto exit;13091310rtw_mi_set_scan_deny(padapter, 550);1311rtw_mi_scan_abort(padapter, _TRUE);13121313pattrib = &pmgntframe->attrib;13141315pmgntframe->frame_tag = DATA_FRAMETAG;1316pattrib->ether_type = 0x890d;13171318_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);1319_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);13201321if (ptxmgmt->status_code == _RSON_TDLS_TEAR_UN_RSN_)1322_rtw_memcpy(pattrib->ra, ptxmgmt->peer, ETH_ALEN);1323else1324_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);13251326_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);13271328update_tdls_attrib(padapter, pattrib);1329pattrib->qsel = pattrib->priority;1330if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {1331rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1332rtw_free_xmitframe(pxmitpriv, pmgntframe);1333goto exit;1334}13351336if (rtw_tdls_is_driver_setup(padapter) == _TRUE)1337if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)1338if (pattrib->encrypt)1339_cancel_timer_ex(&ptdls_sta->TPK_timer);13401341if (wait_ack)1342ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);1343else {1344dump_mgntframe(padapter, pmgntframe);1345ret = _SUCCESS;1346}13471348exit:13491350return ret;1351}13521353int issue_tdls_teardown(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 wait_ack)1354{1355struct sta_info *ptdls_sta = NULL;1356int ret = _FAIL;13571358ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), ptxmgmt->peer);1359if (ptdls_sta == NULL) {1360RTW_INFO("No tdls_sta for tearing down\n");1361goto exit;1362}13631364ret = _issue_tdls_teardown(padapter, ptxmgmt, ptdls_sta, wait_ack);1365if ((ptxmgmt->status_code == _RSON_TDLS_TEAR_UN_RSN_) && (ret == _FAIL)) {1366/* Change status code and send teardown again via AP */1367ptxmgmt->status_code = _RSON_TDLS_TEAR_TOOFAR_;1368ret = _issue_tdls_teardown(padapter, ptxmgmt, ptdls_sta, wait_ack);1369}13701371if (rtw_tdls_is_driver_setup(padapter)) {1372rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);1373rtw_tdls_cmd(padapter, ptxmgmt->peer, TDLS_TEARDOWN_STA_LOCALLY_POST);1374}13751376exit:1377return ret;1378}13791380int issue_tdls_dis_req(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)1381{1382struct xmit_frame *pmgntframe;1383struct pkt_attrib *pattrib;1384struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1385struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1386int ret = _FAIL;13871388RTW_INFO("[TDLS] %s\n", __FUNCTION__);13891390ptxmgmt->action_code = TDLS_DISCOVERY_REQUEST;1391pmgntframe = alloc_mgtxmitframe(pxmitpriv);1392if (pmgntframe == NULL)1393goto exit;13941395pattrib = &pmgntframe->attrib;1396pmgntframe->frame_tag = DATA_FRAMETAG;1397pattrib->ether_type = 0x890d;13981399_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);1400_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);1401_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);1402_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);14031404update_tdls_attrib(padapter, pattrib);1405pattrib->qsel = pattrib->priority;1406if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {1407rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1408rtw_free_xmitframe(pxmitpriv, pmgntframe);1409goto exit;1410}1411dump_mgntframe(padapter, pmgntframe);1412RTW_INFO("issue tdls dis req\n");14131414ret = _SUCCESS;1415exit:14161417return ret;1418}14191420int issue_tdls_setup_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)1421{1422struct xmit_frame *pmgntframe;1423struct pkt_attrib *pattrib;1424struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1425int ret = _FAIL;14261427RTW_INFO("[TDLS] %s\n", __FUNCTION__);14281429ptxmgmt->action_code = TDLS_SETUP_RESPONSE;1430pmgntframe = alloc_mgtxmitframe(pxmitpriv);1431if (pmgntframe == NULL)1432goto exit;14331434pattrib = &pmgntframe->attrib;1435pmgntframe->frame_tag = DATA_FRAMETAG;1436pattrib->ether_type = 0x890d;14371438_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);1439_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);1440_rtw_memcpy(pattrib->ra, get_bssid(&(padapter->mlmepriv)), ETH_ALEN);1441_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);14421443update_tdls_attrib(padapter, pattrib);1444pattrib->qsel = pattrib->priority;1445if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {1446rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1447rtw_free_xmitframe(pxmitpriv, pmgntframe);1448goto exit;1449}14501451dump_mgntframe(padapter, pmgntframe);14521453ret = _SUCCESS;1454exit:14551456return ret;14571458}14591460int issue_tdls_setup_cfm(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)1461{1462struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;1463struct xmit_frame *pmgntframe;1464struct pkt_attrib *pattrib;1465struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1466int ret = _FAIL;14671468RTW_INFO("[TDLS] %s\n", __FUNCTION__);14691470ptxmgmt->action_code = TDLS_SETUP_CONFIRM;1471pmgntframe = alloc_mgtxmitframe(pxmitpriv);1472if (pmgntframe == NULL)1473goto exit;14741475pattrib = &pmgntframe->attrib;1476pmgntframe->frame_tag = DATA_FRAMETAG;1477pattrib->ether_type = 0x890d;14781479_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);1480_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);1481_rtw_memcpy(pattrib->ra, get_bssid(&padapter->mlmepriv), ETH_ALEN);1482_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);14831484update_tdls_attrib(padapter, pattrib);1485pattrib->qsel = pattrib->priority;1486if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {1487rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1488rtw_free_xmitframe(pxmitpriv, pmgntframe);1489goto exit;1490}14911492dump_mgntframe(padapter, pmgntframe);14931494ret = _SUCCESS;1495exit:14961497return ret;14981499}15001501/* TDLS Discovery Response frame is a management action frame */1502int issue_tdls_dis_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 privacy)1503{1504struct xmit_frame *pmgntframe;1505struct pkt_attrib *pattrib;1506unsigned char *pframe;1507struct rtw_ieee80211_hdr *pwlanhdr;1508unsigned short *fctrl;1509struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1510struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);1511int ret = _FAIL;15121513RTW_INFO("[TDLS] %s\n", __FUNCTION__);15141515pmgntframe = alloc_mgtxmitframe(pxmitpriv);1516if (pmgntframe == NULL)1517goto exit;15181519pattrib = &pmgntframe->attrib;1520update_mgntframe_attrib(padapter, pattrib);15211522_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);15231524pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;1525pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;15261527fctrl = &(pwlanhdr->frame_ctl);1528*(fctrl) = 0;15291530/* unicast probe request frame */1531_rtw_memcpy(pwlanhdr->addr1, ptxmgmt->peer, ETH_ALEN);1532_rtw_memcpy(pattrib->dst, pwlanhdr->addr1, ETH_ALEN);1533_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);1534_rtw_memcpy(pattrib->src, pwlanhdr->addr2, ETH_ALEN);1535_rtw_memcpy(pwlanhdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN);1536_rtw_memcpy(pattrib->ra, pwlanhdr->addr3, ETH_ALEN);15371538SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);1539pmlmeext->mgnt_seq++;1540set_frame_sub_type(pframe, WIFI_ACTION);15411542pframe += sizeof(struct rtw_ieee80211_hdr_3addr);1543pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);15441545rtw_build_tdls_dis_rsp_ies(padapter, pmgntframe, pframe, ptxmgmt, privacy);15461547pattrib->nr_frags = 1;1548pattrib->last_txcmdsz = pattrib->pktlen;15491550dump_mgntframe(padapter, pmgntframe);1551ret = _SUCCESS;15521553exit:1554return ret;1555}15561557int issue_tdls_peer_traffic_rsp(_adapter *padapter, struct sta_info *ptdls_sta, struct tdls_txmgmt *ptxmgmt)1558{1559struct xmit_frame *pmgntframe;1560struct pkt_attrib *pattrib;1561struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1562struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1563int ret = _FAIL;15641565RTW_INFO("[TDLS] %s\n", __FUNCTION__);15661567ptxmgmt->action_code = TDLS_PEER_TRAFFIC_RESPONSE;15681569pmgntframe = alloc_mgtxmitframe(pxmitpriv);1570if (pmgntframe == NULL)1571goto exit;15721573pattrib = &pmgntframe->attrib;15741575pmgntframe->frame_tag = DATA_FRAMETAG;1576pattrib->ether_type = 0x890d;15771578_rtw_memcpy(pattrib->dst, ptdls_sta->cmn.mac_addr, ETH_ALEN);1579_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);1580_rtw_memcpy(pattrib->ra, ptdls_sta->cmn.mac_addr, ETH_ALEN);1581_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);15821583update_tdls_attrib(padapter, pattrib);1584pattrib->qsel = pattrib->priority;15851586if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {1587rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1588rtw_free_xmitframe(pxmitpriv, pmgntframe);1589goto exit;1590}15911592dump_mgntframe(padapter, pmgntframe);1593ret = _SUCCESS;15941595exit:15961597return ret;1598}15991600int issue_tdls_peer_traffic_indication(_adapter *padapter, struct sta_info *ptdls_sta)1601{1602struct xmit_frame *pmgntframe;1603struct pkt_attrib *pattrib;1604struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1605struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1606struct tdls_txmgmt txmgmt;1607int ret = _FAIL;16081609RTW_INFO("[TDLS] %s\n", __FUNCTION__);16101611_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));1612txmgmt.action_code = TDLS_PEER_TRAFFIC_INDICATION;16131614pmgntframe = alloc_mgtxmitframe(pxmitpriv);1615if (pmgntframe == NULL)1616goto exit;16171618pattrib = &pmgntframe->attrib;16191620pmgntframe->frame_tag = DATA_FRAMETAG;1621pattrib->ether_type = 0x890d;16221623_rtw_memcpy(pattrib->dst, ptdls_sta->cmn.mac_addr, ETH_ALEN);1624_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);1625_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);1626_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);16271628/* PTI frame's priority should be AC_VO */1629pattrib->priority = 7;16301631update_tdls_attrib(padapter, pattrib);1632pattrib->qsel = pattrib->priority;1633if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {1634rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1635rtw_free_xmitframe(pxmitpriv, pmgntframe);1636goto exit;1637}16381639dump_mgntframe(padapter, pmgntframe);1640ret = _SUCCESS;16411642exit:16431644return ret;1645}16461647#ifdef CONFIG_TDLS_CH_SW1648int issue_tdls_ch_switch_req(_adapter *padapter, struct sta_info *ptdls_sta)1649{1650struct xmit_frame *pmgntframe;1651struct pkt_attrib *pattrib;1652struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1653struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1654struct tdls_txmgmt txmgmt;1655int ret = _FAIL;16561657RTW_INFO("[TDLS] %s\n", __FUNCTION__);16581659if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {1660RTW_INFO("[TDLS] Ignore %s since channel switch is not allowed\n", __func__);1661goto exit;1662}16631664_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));1665txmgmt.action_code = TDLS_CHANNEL_SWITCH_REQUEST;16661667pmgntframe = alloc_mgtxmitframe(pxmitpriv);1668if (pmgntframe == NULL)1669goto exit;16701671pattrib = &pmgntframe->attrib;16721673pmgntframe->frame_tag = DATA_FRAMETAG;1674pattrib->ether_type = 0x890d;16751676_rtw_memcpy(pattrib->dst, ptdls_sta->cmn.mac_addr, ETH_ALEN);1677_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);1678_rtw_memcpy(pattrib->ra, ptdls_sta->cmn.mac_addr, ETH_ALEN);1679_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);16801681update_tdls_attrib(padapter, pattrib);1682pattrib->qsel = pattrib->priority;1683if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {1684rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1685rtw_free_xmitframe(pxmitpriv, pmgntframe);1686goto exit;1687}16881689dump_mgntframe(padapter, pmgntframe);1690ret = _SUCCESS;1691exit:16921693return ret;1694}16951696int issue_tdls_ch_switch_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, int wait_ack)1697{1698struct xmit_frame *pmgntframe;1699struct pkt_attrib *pattrib;1700struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1701struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);1702int ret = _FAIL;17031704RTW_INFO("[TDLS] %s\n", __FUNCTION__);17051706if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {1707RTW_INFO("[TDLS] Ignore %s since channel switch is not allowed\n", __func__);1708goto exit;1709}17101711ptxmgmt->action_code = TDLS_CHANNEL_SWITCH_RESPONSE;17121713pmgntframe = alloc_mgtxmitframe(pxmitpriv);1714if (pmgntframe == NULL)1715goto exit;17161717pattrib = &pmgntframe->attrib;17181719pmgntframe->frame_tag = DATA_FRAMETAG;1720pattrib->ether_type = 0x890d;17211722_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);1723_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);1724_rtw_memcpy(pattrib->ra, ptxmgmt->peer, ETH_ALEN);1725_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);17261727update_tdls_attrib(padapter, pattrib);1728pattrib->qsel = pattrib->priority;1729/*1730_enter_critical_bh(&pxmitpriv->lock, &irqL);1731if(xmitframe_enqueue_for_tdls_sleeping_sta(padapter, pmgntframe)==_TRUE){1732_exit_critical_bh(&pxmitpriv->lock, &irqL);1733return _FALSE;1734}1735*/1736if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {1737rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);1738rtw_free_xmitframe(pxmitpriv, pmgntframe);1739goto exit;1740}17411742if (wait_ack)1743ret = dump_mgntframe_and_wait_ack_timeout(padapter, pmgntframe, 10);1744else {1745dump_mgntframe(padapter, pmgntframe);1746ret = _SUCCESS;1747}1748exit:17491750return ret;1751}1752#endif17531754int On_TDLS_Dis_Rsp(_adapter *padapter, union recv_frame *precv_frame)1755{1756struct sta_info *ptdls_sta = NULL, *psta = rtw_get_stainfo(&(padapter->stapriv), get_bssid(&(padapter->mlmepriv)));1757struct recv_priv *precvpriv = &(padapter->recvpriv);1758u8 *ptr = precv_frame->u.hdr.rx_data, *psa;1759struct rx_pkt_attrib *pattrib = &(precv_frame->u.hdr.attrib);1760struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);1761u8 empty_addr[ETH_ALEN] = { 0x00 };1762int rssi = 0;1763struct tdls_txmgmt txmgmt;1764int ret = _SUCCESS;17651766if (psta)1767rssi = psta->cmn.rssi_stat.rssi;17681769_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));1770/* WFDTDLS: for sigma test, not to setup direct link automatically */1771ptdlsinfo->dev_discovered = _TRUE;17721773psa = get_sa(ptr);1774ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), psa);1775if (ptdls_sta != NULL)1776ptdls_sta->sta_stats.rx_tdls_disc_rsp_pkts++;17771778#ifdef CONFIG_TDLS_AUTOSETUP1779if (ptdls_sta != NULL) {1780/* Record the tdls sta with lowest signal strength */1781if (ptdlsinfo->sta_maximum == _TRUE && ptdls_sta->alive_count >= 1) {1782if (_rtw_memcmp(ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN)) {1783_rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);1784ptdlsinfo->ss_record.RxPWDBAll = pattrib->phy_info.rx_pwdb_all;1785} else {1786if (ptdlsinfo->ss_record.RxPWDBAll < pattrib->phy_info.rx_pwdb_all) {1787_rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);1788ptdlsinfo->ss_record.RxPWDBAll = pattrib->phy_info.rx_pwdb_all;1789}1790}1791}1792} else {1793if (ptdlsinfo->sta_maximum == _TRUE) {1794if (_rtw_memcmp(ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN)) {1795/* All traffics are busy, do not set up another direct link. */1796ret = _FAIL;1797goto exit;1798} else {1799if (pattrib->phy_info.rx_pwdb_all > ptdlsinfo->ss_record.RxPWDBAll) {1800_rtw_memcpy(txmgmt.peer, ptdlsinfo->ss_record.macaddr, ETH_ALEN);1801/* issue_tdls_teardown(padapter, ptdlsinfo->ss_record.macaddr, _FALSE); */1802} else {1803ret = _FAIL;1804goto exit;1805}1806}1807}180818091810if (pattrib->phy_info.rx_pwdb_all + TDLS_SIGNAL_THRESH >= rssi) {1811RTW_INFO("pattrib->RxPWDBAll=%d, pdmpriv->undecorated_smoothed_pwdb=%d\n", pattrib->phy_info.rx_pwdb_all, rssi);1812_rtw_memcpy(txmgmt.peer, psa, ETH_ALEN);1813issue_tdls_setup_req(padapter, &txmgmt, _FALSE);1814}1815}1816#endif /* CONFIG_TDLS_AUTOSETUP */18171818exit:1819return ret;18201821}18221823sint On_TDLS_Setup_Req(_adapter *padapter, union recv_frame *precv_frame, struct sta_info *ptdls_sta)1824{1825struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;1826u8 *psa, *pmyid;1827struct sta_priv *pstapriv = &padapter->stapriv;1828u8 *ptr = precv_frame->u.hdr.rx_data;1829struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);1830struct security_priv *psecuritypriv = &padapter->securitypriv;1831_irqL irqL;1832struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;1833u8 *prsnie, *ppairwise_cipher;1834u8 i, k;1835u8 ccmp_included = 0, rsnie_included = 0;1836u16 j, pairwise_count;1837u8 SNonce[32];1838u32 timeout_interval = TDLS_TPK_RESEND_COUNT;1839sint parsing_length; /* Frame body length, without icv_len */1840PNDIS_802_11_VARIABLE_IEs pIE;1841u8 FIXED_IE = 5;1842unsigned char supportRate[16];1843int supportRateNum = 0;1844struct tdls_txmgmt txmgmt;18451846if (rtw_tdls_is_setup_allowed(padapter) == _FALSE)1847goto exit;18481849_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));1850psa = get_sa(ptr);18511852if (ptdlsinfo->sta_maximum == _TRUE) {1853if (ptdls_sta == NULL)1854goto exit;1855else if (!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))1856goto exit;1857}18581859pmyid = adapter_mac_addr(padapter);1860ptr += prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN;1861parsing_length = ((union recv_frame *)precv_frame)->u.hdr.len1862- prx_pkt_attrib->hdrlen1863- prx_pkt_attrib->iv_len1864- prx_pkt_attrib->icv_len1865- LLC_HEADER_SIZE1866- ETH_TYPE_LEN1867- PAYLOAD_TYPE_LEN;18681869if (ptdls_sta == NULL) {1870ptdls_sta = rtw_alloc_stainfo(pstapriv, psa);1871if (ptdls_sta == NULL)1872goto exit;18731874ptdlsinfo->sta_cnt++;1875}1876else {1877if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {1878/* If the direct link is already set up */1879/* Process as re-setup after tear down */1880RTW_INFO("re-setup a direct link\n");1881}1882/* Already receiving TDLS setup request */1883else if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE) {1884RTW_INFO("receive duplicated TDLS setup request frame in handshaking\n");1885goto exit;1886}1887/* When receiving and sending setup_req to the same link at the same time */1888/* STA with higher MAC_addr would be initiator */1889else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE) {1890RTW_INFO("receive setup_req after sending setup_req\n");1891for (i = 0; i < 6; i++) {1892if (*(pmyid + i) == *(psa + i)) {1893} else if (*(pmyid + i) > *(psa + i)) {1894ptdls_sta->tdls_sta_state = TDLS_INITIATOR_STATE;1895break;1896} else if (*(pmyid + i) < *(psa + i))1897goto exit;1898}1899}1900}19011902if (ptdls_sta) {1903txmgmt.dialog_token = *(ptr + 2); /* Copy dialog token */1904txmgmt.status_code = _STATS_SUCCESSFUL_;19051906/* Parsing information element */1907for (j = FIXED_IE; j < parsing_length;) {19081909pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr + j);19101911switch (pIE->ElementID) {1912case _SUPPORTEDRATES_IE_:1913_rtw_memcpy(supportRate, pIE->data, pIE->Length);1914supportRateNum = pIE->Length;1915break;1916case _COUNTRY_IE_:1917break;1918case _EXT_SUPPORTEDRATES_IE_:1919if (supportRateNum < sizeof(supportRate)) {1920_rtw_memcpy(supportRate + supportRateNum, pIE->data, pIE->Length);1921supportRateNum += pIE->Length;1922}1923break;1924case _SUPPORTED_CH_IE_:1925break;1926case _RSN_IE_2_:1927rsnie_included = 1;1928if (prx_pkt_attrib->encrypt) {1929prsnie = (u8 *)pIE;1930/* Check CCMP pairwise_cipher presence. */1931ppairwise_cipher = prsnie + 10;1932_rtw_memcpy(ptdls_sta->TDLS_RSNIE, pIE->data, pIE->Length);1933pairwise_count = *(u16 *)(ppairwise_cipher - 2);1934for (k = 0; k < pairwise_count; k++) {1935if (_rtw_memcmp(ppairwise_cipher + 4 * k, RSN_CIPHER_SUITE_CCMP, 4) == _TRUE)1936ccmp_included = 1;1937}19381939if (ccmp_included == 0)1940txmgmt.status_code = _STATS_INVALID_RSNIE_;1941}1942break;1943case _EXT_CAP_IE_:1944break;1945case _VENDOR_SPECIFIC_IE_:1946break;1947case _FTIE_:1948if (prx_pkt_attrib->encrypt)1949_rtw_memcpy(SNonce, (ptr + j + 52), 32);1950break;1951case _TIMEOUT_ITVL_IE_:1952if (prx_pkt_attrib->encrypt)1953timeout_interval = cpu_to_le32(*(u32 *)(ptr + j + 3));1954break;1955case _RIC_Descriptor_IE_:1956break;1957#ifdef CONFIG_80211N_HT1958case _HT_CAPABILITY_IE_:1959rtw_tdls_process_ht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);1960break;1961#endif1962#ifdef CONFIG_80211AC_VHT1963case EID_AID:1964break;1965case EID_VHTCapability:1966rtw_tdls_process_vht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);1967break;1968#endif1969case EID_BSSCoexistence:1970break;1971case _LINK_ID_IE_:1972if (_rtw_memcmp(get_bssid(pmlmepriv), pIE->data, 6) == _FALSE)1973txmgmt.status_code = _STATS_NOT_IN_SAME_BSS_;1974break;1975default:1976break;1977}19781979j += (pIE->Length + 2);19801981}19821983/* Check status code */1984/* If responder STA has/hasn't security on AP, but request hasn't/has RSNIE, it should reject */1985if (txmgmt.status_code == _STATS_SUCCESSFUL_) {1986if (rsnie_included && prx_pkt_attrib->encrypt == 0)1987txmgmt.status_code = _STATS_SEC_DISABLED_;1988else if (rsnie_included == 0 && prx_pkt_attrib->encrypt)1989txmgmt.status_code = _STATS_INVALID_PARAMETERS_;19901991#ifdef CONFIG_WFD1992/* WFD test plan version 0.18.2 test item 5.1.5 */1993/* SoUT does not use TDLS if AP uses weak security */1994if (padapter->wdinfo.wfd_tdls_enable && (rsnie_included && prx_pkt_attrib->encrypt != _AES_))1995txmgmt.status_code = _STATS_SEC_DISABLED_;1996#endif /* CONFIG_WFD */1997}19981999ptdls_sta->tdls_sta_state |= TDLS_INITIATOR_STATE;2000if (prx_pkt_attrib->encrypt) {2001_rtw_memcpy(ptdls_sta->SNonce, SNonce, 32);20022003if (timeout_interval <= 300)2004ptdls_sta->TDLS_PeerKey_Lifetime = TDLS_TPK_RESEND_COUNT;2005else2006ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;2007}20082009/* Update station supportRate */2010ptdls_sta->bssratelen = supportRateNum;2011_rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);20122013/* -2: AP + BC/MC sta, -4: default key */2014if (ptdlsinfo->sta_cnt == MAX_ALLOWED_TDLS_STA_NUM)2015ptdlsinfo->sta_maximum = _TRUE;20162017#ifdef CONFIG_WFD2018rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length);2019#endif20202021} else2022goto exit;20232024_rtw_memcpy(txmgmt.peer, prx_pkt_attrib->src, ETH_ALEN);20252026if (rtw_tdls_is_driver_setup(padapter)) {2027issue_tdls_setup_rsp(padapter, &txmgmt);20282029if (txmgmt.status_code == _STATS_SUCCESSFUL_)2030_set_timer(&ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);2031else {2032rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);2033rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_TEARDOWN_STA_LOCALLY_POST);2034}2035}20362037exit:20382039return _SUCCESS;2040}20412042int On_TDLS_Setup_Rsp(_adapter *padapter, union recv_frame *precv_frame, struct sta_info *ptdls_sta)2043{2044struct registry_priv *pregistrypriv = &padapter->registrypriv;2045struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;2046struct sta_priv *pstapriv = &padapter->stapriv;2047u8 *ptr = precv_frame->u.hdr.rx_data;2048_irqL irqL;2049struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;2050u8 *psa;2051u16 status_code = 0;2052sint parsing_length; /* Frame body length, without icv_len */2053PNDIS_802_11_VARIABLE_IEs pIE;2054u8 FIXED_IE = 7;2055u8 ANonce[32];2056u8 *pftie = NULL, *ptimeout_ie = NULL, *plinkid_ie = NULL, *prsnie = NULL, *pftie_mic = NULL, *ppairwise_cipher = NULL;2057u16 pairwise_count, j, k;2058u8 verify_ccmp = 0;2059unsigned char supportRate[16];2060int supportRateNum = 0;2061struct tdls_txmgmt txmgmt;2062int ret = _SUCCESS;2063u32 timeout_interval = TDLS_TPK_RESEND_COUNT;20642065_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));2066psa = get_sa(ptr);20672068ptr += prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN;2069parsing_length = ((union recv_frame *)precv_frame)->u.hdr.len2070- prx_pkt_attrib->hdrlen2071- prx_pkt_attrib->iv_len2072- prx_pkt_attrib->icv_len2073- LLC_HEADER_SIZE2074- ETH_TYPE_LEN2075- PAYLOAD_TYPE_LEN;20762077_rtw_memcpy(&status_code, ptr + 2, 2);20782079if (status_code != 0) {2080RTW_INFO("[TDLS] %s status_code = %d, free_tdls_sta\n", __FUNCTION__, status_code);2081rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);2082rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_TEARDOWN_STA_LOCALLY_POST);2083ret = _FAIL;2084goto exit;2085}20862087status_code = 0;20882089/* parsing information element */2090for (j = FIXED_IE; j < parsing_length;) {2091pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr + j);20922093switch (pIE->ElementID) {2094case _SUPPORTEDRATES_IE_:2095_rtw_memcpy(supportRate, pIE->data, pIE->Length);2096supportRateNum = pIE->Length;2097break;2098case _COUNTRY_IE_:2099break;2100case _EXT_SUPPORTEDRATES_IE_:2101if (supportRateNum < sizeof(supportRate)) {2102_rtw_memcpy(supportRate + supportRateNum, pIE->data, pIE->Length);2103supportRateNum += pIE->Length;2104}2105break;2106case _SUPPORTED_CH_IE_:2107break;2108case _RSN_IE_2_:2109prsnie = (u8 *)pIE;2110/* Check CCMP pairwise_cipher presence. */2111ppairwise_cipher = prsnie + 10;2112_rtw_memcpy(&pairwise_count, (u16 *)(ppairwise_cipher - 2), 2);2113for (k = 0; k < pairwise_count; k++) {2114if (_rtw_memcmp(ppairwise_cipher + 4 * k, RSN_CIPHER_SUITE_CCMP, 4) == _TRUE)2115verify_ccmp = 1;2116}2117case _EXT_CAP_IE_:2118break;2119case _VENDOR_SPECIFIC_IE_:2120if (_rtw_memcmp((u8 *)pIE + 2, WMM_INFO_OUI, 6) == _TRUE) {2121/* WMM Info ID and OUI */2122if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))2123ptdls_sta->qos_option = _TRUE;2124}2125break;2126case _FTIE_:2127pftie = (u8 *)pIE;2128_rtw_memcpy(ANonce, (ptr + j + 20), 32);2129break;2130case _TIMEOUT_ITVL_IE_:2131ptimeout_ie = (u8 *)pIE;2132timeout_interval = cpu_to_le32(*(u32 *)(ptimeout_ie + 3));2133break;2134case _RIC_Descriptor_IE_:2135break;2136#ifdef CONFIG_80211N_HT2137case _HT_CAPABILITY_IE_:2138rtw_tdls_process_ht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);2139break;2140#endif2141#ifdef CONFIG_80211AC_VHT2142case EID_AID:2143/* todo in the future if necessary */2144break;2145case EID_VHTCapability:2146rtw_tdls_process_vht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);2147break;2148case EID_OpModeNotification:2149rtw_tdls_process_vht_op_mode_notify(padapter, ptdls_sta, pIE->data, pIE->Length);2150break;2151#endif2152case EID_BSSCoexistence:2153break;2154case _LINK_ID_IE_:2155plinkid_ie = (u8 *)pIE;2156break;2157default:2158break;2159}21602161j += (pIE->Length + 2);21622163}21642165ptdls_sta->bssratelen = supportRateNum;2166_rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);2167_rtw_memcpy(ptdls_sta->ANonce, ANonce, 32);21682169#ifdef CONFIG_WFD2170rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length);2171#endif21722173if (prx_pkt_attrib->encrypt) {2174if (verify_ccmp == 1) {2175txmgmt.status_code = _STATS_SUCCESSFUL_;2176if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {2177wpa_tdls_generate_tpk(padapter, ptdls_sta);2178if (tdls_verify_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie) == _FAIL) {2179RTW_INFO("[TDLS] %s tdls_verify_mic fail, free_tdls_sta\n", __FUNCTION__);2180rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);2181rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_TEARDOWN_STA_LOCALLY_POST);2182ret = _FAIL;2183goto exit;2184}2185ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;2186}2187} else2188txmgmt.status_code = _STATS_INVALID_RSNIE_;2189} else2190txmgmt.status_code = _STATS_SUCCESSFUL_;21912192if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {2193_rtw_memcpy(txmgmt.peer, prx_pkt_attrib->src, ETH_ALEN);2194issue_tdls_setup_cfm(padapter, &txmgmt);21952196if (txmgmt.status_code == _STATS_SUCCESSFUL_) {2197rtw_tdls_set_link_established(padapter, _TRUE);21982199if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE) {2200ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;2201ptdls_sta->state |= _FW_LINKED;2202_cancel_timer_ex(&ptdls_sta->handshake_timer);2203}22042205if (prx_pkt_attrib->encrypt)2206rtw_tdls_set_key(padapter, ptdls_sta);22072208rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_ESTABLISHED);22092210}2211}22122213exit:2214if (rtw_tdls_is_driver_setup(padapter) == _TRUE)2215return ret;2216else2217return _SUCCESS;22182219}22202221int On_TDLS_Setup_Cfm(_adapter *padapter, union recv_frame *precv_frame, struct sta_info *ptdls_sta)2222{2223struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;2224struct sta_priv *pstapriv = &padapter->stapriv;2225u8 *ptr = precv_frame->u.hdr.rx_data;2226_irqL irqL;2227struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;2228u8 *psa;2229u16 status_code = 0;2230sint parsing_length;2231PNDIS_802_11_VARIABLE_IEs pIE;2232u8 FIXED_IE = 5;2233u8 *pftie = NULL, *ptimeout_ie = NULL, *plinkid_ie = NULL, *prsnie = NULL, *pftie_mic = NULL, *ppairwise_cipher = NULL;2234u16 j, pairwise_count;2235int ret = _SUCCESS;22362237psa = get_sa(ptr);22382239ptr += prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN;2240parsing_length = ((union recv_frame *)precv_frame)->u.hdr.len2241- prx_pkt_attrib->hdrlen2242- prx_pkt_attrib->iv_len2243- prx_pkt_attrib->icv_len2244- LLC_HEADER_SIZE2245- ETH_TYPE_LEN2246- PAYLOAD_TYPE_LEN;22472248_rtw_memcpy(&status_code, ptr + 2, 2);22492250if (status_code != 0) {2251RTW_INFO("[%s] status_code = %d\n, free_tdls_sta", __FUNCTION__, status_code);2252rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);2253rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_TEARDOWN_STA_LOCALLY_POST);2254ret = _FAIL;2255goto exit;2256}22572258/* Parsing information element */2259for (j = FIXED_IE; j < parsing_length;) {22602261pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr + j);22622263switch (pIE->ElementID) {2264case _RSN_IE_2_:2265prsnie = (u8 *)pIE;2266break;2267case _VENDOR_SPECIFIC_IE_:2268if (_rtw_memcmp((u8 *)pIE + 2, WMM_PARA_OUI, 6) == _TRUE) {2269/* WMM Parameter ID and OUI */2270ptdls_sta->qos_option = _TRUE;2271}2272break;2273case _FTIE_:2274pftie = (u8 *)pIE;2275break;2276case _TIMEOUT_ITVL_IE_:2277ptimeout_ie = (u8 *)pIE;2278break;2279#ifdef CONFIG_80211N_HT2280case _HT_EXTRA_INFO_IE_:2281break;2282#endif2283#ifdef CONFIG_80211AC_VHT2284case EID_VHTOperation:2285rtw_tdls_process_vht_operation(padapter, ptdls_sta, pIE->data, pIE->Length);2286break;2287case EID_OpModeNotification:2288rtw_tdls_process_vht_op_mode_notify(padapter, ptdls_sta, pIE->data, pIE->Length);2289break;2290#endif2291case _LINK_ID_IE_:2292plinkid_ie = (u8 *)pIE;2293break;2294default:2295break;2296}22972298j += (pIE->Length + 2);22992300}23012302if (prx_pkt_attrib->encrypt) {2303/* Verify mic in FTIE MIC field */2304if (rtw_tdls_is_driver_setup(padapter) &&2305(tdls_verify_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie) == _FAIL)) {2306rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);2307rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_TEARDOWN_STA_LOCALLY_POST);2308ret = _FAIL;2309goto exit;2310}2311}23122313if (rtw_tdls_is_driver_setup(padapter)) {2314rtw_tdls_set_link_established(padapter, _TRUE);23152316if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE) {2317ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;2318ptdls_sta->state |= _FW_LINKED;2319_cancel_timer_ex(&ptdls_sta->handshake_timer);2320}23212322if (prx_pkt_attrib->encrypt) {2323rtw_tdls_set_key(padapter, ptdls_sta);23242325/* Start TPK timer */2326ptdls_sta->TPK_count = 0;2327_set_timer(&ptdls_sta->TPK_timer, ONE_SEC);2328}23292330rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_ESTABLISHED);2331}23322333exit:2334return ret;23352336}23372338int On_TDLS_Dis_Req(_adapter *padapter, union recv_frame *precv_frame)2339{2340struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;2341struct sta_priv *pstapriv = &padapter->stapriv;2342struct sta_info *psta_ap;2343u8 *ptr = precv_frame->u.hdr.rx_data;2344sint parsing_length; /* Frame body length, without icv_len */2345PNDIS_802_11_VARIABLE_IEs pIE;2346u8 FIXED_IE = 3, *dst;2347u16 j;2348struct tdls_txmgmt txmgmt;2349int ret = _SUCCESS;23502351if (rtw_tdls_is_driver_setup(padapter) == _FALSE)2352goto exit;23532354_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));2355ptr += prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN;2356txmgmt.dialog_token = *(ptr + 2);2357_rtw_memcpy(&txmgmt.peer, precv_frame->u.hdr.attrib.src, ETH_ALEN);2358txmgmt.action_code = TDLS_DISCOVERY_RESPONSE;2359parsing_length = ((union recv_frame *)precv_frame)->u.hdr.len2360- prx_pkt_attrib->hdrlen2361- prx_pkt_attrib->iv_len2362- prx_pkt_attrib->icv_len2363- LLC_HEADER_SIZE2364- ETH_TYPE_LEN2365- PAYLOAD_TYPE_LEN;23662367/* Parsing information element */2368for (j = FIXED_IE; j < parsing_length;) {23692370pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr + j);23712372switch (pIE->ElementID) {2373case _LINK_ID_IE_:2374psta_ap = rtw_get_stainfo(pstapriv, pIE->data);2375if (psta_ap == NULL)2376goto exit;2377dst = pIE->data + 12;2378if (MacAddr_isBcst(dst) == _FALSE && (_rtw_memcmp(adapter_mac_addr(padapter), dst, ETH_ALEN) == _FALSE))2379goto exit;2380break;2381default:2382break;2383}23842385j += (pIE->Length + 2);23862387}23882389issue_tdls_dis_rsp(padapter, &txmgmt, prx_pkt_attrib->privacy);23902391exit:2392return ret;23932394}23952396int On_TDLS_Teardown(_adapter *padapter, union recv_frame *precv_frame, struct sta_info *ptdls_sta)2397{2398u8 *ptr = precv_frame->u.hdr.rx_data;2399struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;2400struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);2401struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2402struct sta_priv *pstapriv = &padapter->stapriv;2403_irqL irqL;2404u8 reason;24052406reason = *(ptr + prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN + 2);2407RTW_INFO("[TDLS] %s Reason code(%d)\n", __FUNCTION__, reason);24082409if (rtw_tdls_is_driver_setup(padapter)) {2410rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);2411rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_TEARDOWN_STA_LOCALLY_POST);2412}24132414return _SUCCESS;24152416}24172418#if 02419u8 TDLS_check_ch_state(uint state)2420{2421if (state & TDLS_CH_SWITCH_ON_STATE &&2422state & TDLS_PEER_AT_OFF_STATE) {2423if (state & TDLS_PEER_SLEEP_STATE)2424return 2; /* U-APSD + ch. switch */2425else2426return 1; /* ch. switch */2427} else2428return 0;2429}2430#endif24312432int On_TDLS_Peer_Traffic_Indication(_adapter *padapter, union recv_frame *precv_frame, struct sta_info *ptdls_sta)2433{2434struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;2435u8 *ptr = precv_frame->u.hdr.rx_data;2436struct tdls_txmgmt txmgmt;24372438ptr += pattrib->hdrlen + pattrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN;2439_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));24402441txmgmt.dialog_token = *(ptr + 2);2442issue_tdls_peer_traffic_rsp(padapter, ptdls_sta, &txmgmt);2443/* issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->cmn.mac_addr, 0, 0, 0); */24442445return _SUCCESS;2446}24472448/* We process buffered data for 1. U-APSD, 2. ch. switch, 3. U-APSD + ch. switch here */2449int On_TDLS_Peer_Traffic_Rsp(_adapter *padapter, union recv_frame *precv_frame, struct sta_info *ptdls_sta)2450{2451struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;2452struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;2453struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;2454struct sta_priv *pstapriv = &padapter->stapriv;2455u8 wmmps_ac = 0;2456/* u8 state=TDLS_check_ch_state(ptdls_sta->tdls_sta_state); */2457int i;24582459ptdls_sta->sta_stats.rx_data_pkts++;24602461ptdls_sta->tdls_sta_state &= ~(TDLS_WAIT_PTR_STATE);24622463/* Check 4-AC queue bit */2464if (ptdls_sta->uapsd_vo || ptdls_sta->uapsd_vi || ptdls_sta->uapsd_be || ptdls_sta->uapsd_bk)2465wmmps_ac = 1;24662467/* If it's a direct link and have buffered frame */2468if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {2469if (wmmps_ac) {2470_irqL irqL;2471_list *xmitframe_plist, *xmitframe_phead;2472struct xmit_frame *pxmitframe = NULL;24732474_enter_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);24752476xmitframe_phead = get_list_head(&ptdls_sta->sleep_q);2477xmitframe_plist = get_next(xmitframe_phead);24782479/* transmit buffered frames */2480while (rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == _FALSE) {2481pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);2482xmitframe_plist = get_next(xmitframe_plist);2483rtw_list_delete(&pxmitframe->list);24842485ptdls_sta->sleepq_len--;2486ptdls_sta->sleepq_ac_len--;2487if (ptdls_sta->sleepq_len > 0) {2488pxmitframe->attrib.mdata = 1;2489pxmitframe->attrib.eosp = 0;2490} else {2491pxmitframe->attrib.mdata = 0;2492pxmitframe->attrib.eosp = 1;2493}2494pxmitframe->attrib.triggered = 1;24952496rtw_hal_xmitframe_enqueue(padapter, pxmitframe);2497}24982499if (ptdls_sta->sleepq_len == 0)2500RTW_INFO("no buffered packets for tdls to xmit\n");2501else {2502RTW_INFO("error!psta->sleepq_len=%d\n", ptdls_sta->sleepq_len);2503ptdls_sta->sleepq_len = 0;2504}25052506_exit_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);25072508}25092510}25112512return _SUCCESS;2513}25142515#ifdef CONFIG_TDLS_CH_SW2516sint On_TDLS_Ch_Switch_Req(_adapter *padapter, union recv_frame *precv_frame, struct sta_info *ptdls_sta)2517{2518struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;2519struct sta_priv *pstapriv = &padapter->stapriv;2520u8 *ptr = precv_frame->u.hdr.rx_data;2521struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;2522sint parsing_length;2523PNDIS_802_11_VARIABLE_IEs pIE;2524u8 FIXED_IE = 4;2525u16 j;2526struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;2527u8 zaddr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};2528u16 switch_time = TDLS_CH_SWITCH_TIME * 1000, switch_timeout = TDLS_CH_SWITCH_TIMEOUT * 1000;2529u8 take_care_iqk;25302531if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {2532RTW_INFO("[TDLS] Ignore %s since channel switch is not allowed\n", __func__);2533return _FAIL;2534}25352536ptdls_sta->ch_switch_time = switch_time;2537ptdls_sta->ch_switch_timeout = switch_timeout;25382539ptr += prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN;2540parsing_length = ((union recv_frame *)precv_frame)->u.hdr.len2541- prx_pkt_attrib->hdrlen2542- prx_pkt_attrib->iv_len2543- prx_pkt_attrib->icv_len2544- LLC_HEADER_SIZE2545- ETH_TYPE_LEN2546- PAYLOAD_TYPE_LEN;25472548pchsw_info->off_ch_num = *(ptr + 2);25492550if ((*(ptr + 2) == 2) && (hal_is_band_support(padapter, BAND_ON_5G)))2551pchsw_info->off_ch_num = 44;25522553if (pchsw_info->off_ch_num != pmlmeext->cur_channel)2554pchsw_info->delay_switch_back = _FALSE;25552556/* Parsing information element */2557for (j = FIXED_IE; j < parsing_length;) {2558pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr + j);25592560switch (pIE->ElementID) {2561case EID_SecondaryChnlOffset:2562switch (*(pIE->data)) {2563case EXTCHNL_OFFSET_UPPER:2564pchsw_info->ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;2565break;25662567case EXTCHNL_OFFSET_LOWER:2568pchsw_info->ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;2569break;25702571default:2572pchsw_info->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;2573break;2574}2575break;2576case _LINK_ID_IE_:2577break;2578case _CH_SWITCH_TIMING_:2579ptdls_sta->ch_switch_time = (RTW_GET_LE16(pIE->data) >= TDLS_CH_SWITCH_TIME * 1000) ?2580RTW_GET_LE16(pIE->data) : TDLS_CH_SWITCH_TIME * 1000;2581ptdls_sta->ch_switch_timeout = (RTW_GET_LE16(pIE->data + 2) >= TDLS_CH_SWITCH_TIMEOUT * 1000) ?2582RTW_GET_LE16(pIE->data + 2) : TDLS_CH_SWITCH_TIMEOUT * 1000;2583RTW_INFO("[TDLS] %s ch_switch_time:%d, ch_switch_timeout:%d\n"2584, __FUNCTION__, RTW_GET_LE16(pIE->data), RTW_GET_LE16(pIE->data + 2));2585default:2586break;2587}25882589j += (pIE->Length + 2);2590}25912592rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk);2593if (take_care_iqk == _TRUE) {2594u8 central_chnl;2595u8 bw_mode;25962597bw_mode = (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20;2598central_chnl = rtw_get_center_ch(pchsw_info->off_ch_num, bw_mode, pchsw_info->ch_offset);2599if (rtw_hal_ch_sw_iqk_info_search(padapter, central_chnl, bw_mode) < 0) {2600if (!(pchsw_info->ch_sw_state & TDLS_CH_SWITCH_PREPARE_STATE))2601rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_PREPARE);26022603return _FAIL;2604}2605}26062607/* cancel ch sw monitor timer for responder */2608if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE))2609_cancel_timer_ex(&ptdls_sta->ch_sw_monitor_timer);26102611if (_rtw_memcmp(pchsw_info->addr, zaddr, ETH_ALEN) == _TRUE)2612_rtw_memcpy(pchsw_info->addr, ptdls_sta->cmn.mac_addr, ETH_ALEN);26132614if (ATOMIC_READ(&pchsw_info->chsw_on) == _FALSE)2615rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_START);26162617rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_RESP);26182619return _SUCCESS;2620}26212622sint On_TDLS_Ch_Switch_Rsp(_adapter *padapter, union recv_frame *precv_frame, struct sta_info *ptdls_sta)2623{2624struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;2625struct sta_priv *pstapriv = &padapter->stapriv;2626u8 *ptr = precv_frame->u.hdr.rx_data;2627struct rx_pkt_attrib *prx_pkt_attrib = &precv_frame->u.hdr.attrib;2628sint parsing_length;2629PNDIS_802_11_VARIABLE_IEs pIE;2630u8 FIXED_IE = 4;2631u16 status_code, j, switch_time, switch_timeout;2632struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;2633int ret = _SUCCESS;26342635if (rtw_tdls_is_chsw_allowed(padapter) == _FALSE) {2636RTW_INFO("[TDLS] Ignore %s since channel switch is not allowed\n", __func__);2637return _SUCCESS;2638}26392640/* If we receive Unsolicited TDLS Channel Switch Response when channel switch is running, */2641/* we will go back to base channel and terminate this channel switch procedure */2642if (ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE) {2643if (pmlmeext->cur_channel != rtw_get_oper_ch(padapter)) {2644RTW_INFO("[TDLS] Rx unsolicited channel switch response\n");2645rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_BASE_CHNL);2646goto exit;2647}2648}26492650ptr += prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN;2651parsing_length = ((union recv_frame *)precv_frame)->u.hdr.len2652- prx_pkt_attrib->hdrlen2653- prx_pkt_attrib->iv_len2654- prx_pkt_attrib->icv_len2655- LLC_HEADER_SIZE2656- ETH_TYPE_LEN2657- PAYLOAD_TYPE_LEN;26582659_rtw_memcpy(&status_code, ptr + 2, 2);26602661if (status_code != 0) {2662RTW_INFO("[TDLS] %s status_code:%d\n", __func__, status_code);2663pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE);2664rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_END);2665ret = _FAIL;2666goto exit;2667}26682669/* Parsing information element */2670for (j = FIXED_IE; j < parsing_length;) {2671pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr + j);26722673switch (pIE->ElementID) {2674case _LINK_ID_IE_:2675break;2676case _CH_SWITCH_TIMING_:2677_rtw_memcpy(&switch_time, pIE->data, 2);2678if (switch_time > ptdls_sta->ch_switch_time)2679_rtw_memcpy(&ptdls_sta->ch_switch_time, &switch_time, 2);26802681_rtw_memcpy(&switch_timeout, pIE->data + 2, 2);2682if (switch_timeout > ptdls_sta->ch_switch_timeout)2683_rtw_memcpy(&ptdls_sta->ch_switch_timeout, &switch_timeout, 2);2684break;2685default:2686break;2687}26882689j += (pIE->Length + 2);2690}26912692if ((pmlmeext->cur_channel == rtw_get_oper_ch(padapter)) &&2693(pchsw_info->ch_sw_state & TDLS_WAIT_CH_RSP_STATE)) {2694if (ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE)2695rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_OFF_CHNL);2696}26972698exit:2699return ret;2700}2701#endif /* CONFIG_TDLS_CH_SW */27022703#ifdef CONFIG_WFD2704void wfd_ie_tdls(_adapter *padapter, u8 *pframe, u32 *pktlen)2705{2706struct mlme_priv *pmlmepriv = &padapter->mlmepriv;2707struct wifi_display_info *pwfd_info = padapter->tdlsinfo.wfd_info;2708u8 wfdie[MAX_WFD_IE_LEN] = { 0x00 };2709u32 wfdielen = 0;2710u16 v16 = 0;27112712if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))2713return;27142715/* WFD OUI */2716wfdielen = 0;2717wfdie[wfdielen++] = 0x50;2718wfdie[wfdielen++] = 0x6F;2719wfdie[wfdielen++] = 0x9A;2720wfdie[wfdielen++] = 0x0A; /* WFA WFD v1.0 */27212722/*2723* Commented by Albert 201108252724* According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes2725* 1. WFD Device Information2726* 2. Associated BSSID ( Optional )2727* 3. Local IP Adress ( Optional )2728*/27292730/* WFD Device Information ATTR */2731/* Type: */2732wfdie[wfdielen++] = WFD_ATTR_DEVICE_INFO;27332734/* Length: */2735/* Note: In the WFD specification, the size of length field is 2. */2736RTW_PUT_BE16(wfdie + wfdielen, 0x0006);2737wfdielen += 2;27382739/* Value1: */2740/* WFD device information */2741/* available for WFD session + Preferred TDLS + WSD ( WFD Service Discovery ) */2742v16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL2743| WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_WSD;2744RTW_PUT_BE16(wfdie + wfdielen, v16);2745wfdielen += 2;27462747/* Value2: */2748/* Session Management Control Port */2749/* Default TCP port for RTSP messages is 554 */2750RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->tdls_rtsp_ctrlport);2751wfdielen += 2;27522753/* Value3: */2754/* WFD Device Maximum Throughput */2755/* 300Mbps is the maximum throughput */2756RTW_PUT_BE16(wfdie + wfdielen, 300);2757wfdielen += 2;27582759/* Associated BSSID ATTR */2760/* Type: */2761wfdie[wfdielen++] = WFD_ATTR_ASSOC_BSSID;27622763/* Length: */2764/* Note: In the WFD specification, the size of length field is 2. */2765RTW_PUT_BE16(wfdie + wfdielen, 0x0006);2766wfdielen += 2;27672768/* Value: */2769/* Associated BSSID */2770if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)2771_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[0], ETH_ALEN);2772else2773_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);27742775/* Local IP Address ATTR */2776wfdie[wfdielen++] = WFD_ATTR_LOCAL_IP_ADDR;27772778/* Length: */2779/* Note: In the WFD specification, the size of length field is 2. */2780RTW_PUT_BE16(wfdie + wfdielen, 0x0005);2781wfdielen += 2;27822783/* Version: */2784/* 0x01: Version1;IPv4 */2785wfdie[wfdielen++] = 0x01;27862787/* IPv4 Address */2788_rtw_memcpy(wfdie + wfdielen, pwfd_info->ip_address, 4);2789wfdielen += 4;27902791pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, pktlen);27922793}2794#endif /* CONFIG_WFD */27952796void rtw_build_tdls_setup_req_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, struct sta_info *ptdls_sta)2797{2798struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);2799struct registry_priv *pregistrypriv = &padapter->registrypriv;2800struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);2801struct pkt_attrib *pattrib = &pxmitframe->attrib;2802int i = 0 ;2803u32 time;2804u8 *pframe_head;28052806/* SNonce */2807if (pattrib->encrypt) {2808for (i = 0; i < 8; i++) {2809time = rtw_get_current_time();2810_rtw_memcpy(&ptdls_sta->SNonce[4 * i], (u8 *)&time, 4);2811}2812}28132814pframe_head = pframe; /* For rtw_tdls_set_ht_cap() */28152816pframe = rtw_tdls_set_payload_type(pframe, pattrib);2817pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);2818pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);2819pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);28202821pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);2822pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);2823pframe = rtw_tdls_set_sup_ch(padapter, pframe, pattrib);2824pframe = rtw_tdls_set_sup_reg_class(pframe, pattrib);28252826if (pattrib->encrypt)2827pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);28282829pframe = rtw_tdls_set_ext_cap(pframe, pattrib);28302831if (pattrib->encrypt) {2832pframe = rtw_tdls_set_ftie(ptxmgmt2833, pframe2834, pattrib2835, NULL2836, ptdls_sta->SNonce);28372838pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);2839}28402841#ifdef CONFIG_80211N_HT2842/* Sup_reg_classes(optional) */2843if (pregistrypriv->ht_enable == _TRUE)2844pframe = rtw_tdls_set_ht_cap(padapter, pframe_head, pattrib);2845#endif28462847pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);28482849pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _TRUE);28502851if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))2852pframe = rtw_tdls_set_qos_cap(pframe, pattrib);28532854#ifdef CONFIG_80211AC_VHT2855if ((padapter->mlmepriv.htpriv.ht_option == _TRUE) && (pmlmeext->cur_channel > 14)2856&& REGSTY_IS_11AC_ENABLE(pregistrypriv)2857&& is_supported_vht(pregistrypriv->wireless_mode)2858&& (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent))2859) {2860pframe = rtw_tdls_set_aid(padapter, pframe, pattrib);2861pframe = rtw_tdls_set_vht_cap(padapter, pframe, pattrib);2862}2863#endif28642865#ifdef CONFIG_WFD2866if (padapter->wdinfo.wfd_tdls_enable == 1)2867wfd_ie_tdls(padapter, pframe, &(pattrib->pktlen));2868#endif28692870}28712872void rtw_build_tdls_setup_rsp_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, struct sta_info *ptdls_sta)2873{2874struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);2875struct registry_priv *pregistrypriv = &padapter->registrypriv;2876struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);2877struct pkt_attrib *pattrib = &pxmitframe->attrib;2878u8 k; /* for random ANonce */2879u8 *pftie = NULL, *ptimeout_ie = NULL, *plinkid_ie = NULL, *prsnie = NULL, *pftie_mic = NULL;2880u32 time;2881u8 *pframe_head;28822883if (pattrib->encrypt) {2884for (k = 0; k < 8; k++) {2885time = rtw_get_current_time();2886_rtw_memcpy(&ptdls_sta->ANonce[4 * k], (u8 *)&time, 4);2887}2888}28892890pframe_head = pframe;28912892pframe = rtw_tdls_set_payload_type(pframe, pattrib);2893pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);2894pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);2895pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);28962897if (ptxmgmt->status_code != 0) {2898RTW_INFO("[%s] status_code:%04x\n", __FUNCTION__, ptxmgmt->status_code);2899return;2900}29012902pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);2903pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);2904pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);2905pframe = rtw_tdls_set_sup_ch(padapter, pframe, pattrib);2906pframe = rtw_tdls_set_sup_reg_class(pframe, pattrib);29072908if (pattrib->encrypt) {2909prsnie = pframe;2910pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _FALSE, ptdls_sta);2911}29122913pframe = rtw_tdls_set_ext_cap(pframe, pattrib);29142915if (pattrib->encrypt) {2916if (rtw_tdls_is_driver_setup(padapter) == _TRUE)2917wpa_tdls_generate_tpk(padapter, ptdls_sta);29182919pftie = pframe;2920pftie_mic = pframe + 4;2921pframe = rtw_tdls_set_ftie(ptxmgmt2922, pframe2923, pattrib2924, ptdls_sta->ANonce2925, ptdls_sta->SNonce);29262927ptimeout_ie = pframe;2928pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _FALSE, ptdls_sta);2929}29302931#ifdef CONFIG_80211N_HT2932/* Sup_reg_classes(optional) */2933if (pregistrypriv->ht_enable == _TRUE)2934pframe = rtw_tdls_set_ht_cap(padapter, pframe_head, pattrib);2935#endif29362937pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);29382939plinkid_ie = pframe;2940pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _FALSE);29412942/* Fill FTIE mic */2943if (pattrib->encrypt && rtw_tdls_is_driver_setup(padapter) == _TRUE)2944wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);29452946if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))2947pframe = rtw_tdls_set_qos_cap(pframe, pattrib);29482949#ifdef CONFIG_80211AC_VHT2950if ((padapter->mlmepriv.htpriv.ht_option == _TRUE) && (pmlmeext->cur_channel > 14)2951&& REGSTY_IS_11AC_ENABLE(pregistrypriv)2952&& is_supported_vht(pregistrypriv->wireless_mode)2953&& (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent))2954) {2955pframe = rtw_tdls_set_aid(padapter, pframe, pattrib);2956pframe = rtw_tdls_set_vht_cap(padapter, pframe, pattrib);2957pframe = rtw_tdls_set_vht_op_mode_notify(padapter, pframe, pattrib, pmlmeext->cur_bwmode);2958}2959#endif29602961#ifdef CONFIG_WFD2962if (padapter->wdinfo.wfd_tdls_enable)2963wfd_ie_tdls(padapter, pframe, &(pattrib->pktlen));2964#endif29652966}29672968void rtw_build_tdls_setup_cfm_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, struct sta_info *ptdls_sta)2969{2970struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);2971struct registry_priv *pregistrypriv = &padapter->registrypriv;2972struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);2973struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2974struct pkt_attrib *pattrib = &pxmitframe->attrib;29752976unsigned int ie_len;2977unsigned char *p;2978u8 wmm_param_ele[24] = {0};2979u8 *pftie = NULL, *ptimeout_ie = NULL, *plinkid_ie = NULL, *prsnie = NULL, *pftie_mic = NULL;29802981pframe = rtw_tdls_set_payload_type(pframe, pattrib);2982pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);2983pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);2984pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);2985pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);29862987if (ptxmgmt->status_code != 0)2988return;29892990if (pattrib->encrypt) {2991prsnie = pframe;2992pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);2993}29942995if (pattrib->encrypt) {2996pftie = pframe;2997pftie_mic = pframe + 4;2998pframe = rtw_tdls_set_ftie(ptxmgmt2999, pframe3000, pattrib3001, ptdls_sta->ANonce3002, ptdls_sta->SNonce);30033004ptimeout_ie = pframe;3005pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);30063007if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {3008/* Start TPK timer */3009ptdls_sta->TPK_count = 0;3010_set_timer(&ptdls_sta->TPK_timer, ONE_SEC);3011}3012}30133014/* HT operation; todo */30153016plinkid_ie = pframe;3017pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _TRUE);30183019if (pattrib->encrypt && (rtw_tdls_is_driver_setup(padapter) == _TRUE))3020wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);30213022if (ptdls_sta->qos_option == _TRUE)3023pframe = rtw_tdls_set_wmm_params(padapter, pframe, pattrib);30243025#ifdef CONFIG_80211AC_VHT3026if ((padapter->mlmepriv.htpriv.ht_option == _TRUE)3027&& (ptdls_sta->vhtpriv.vht_option == _TRUE) && (pmlmeext->cur_channel > 14)3028&& REGSTY_IS_11AC_ENABLE(pregistrypriv)3029&& is_supported_vht(pregistrypriv->wireless_mode)3030&& (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent))3031) {3032pframe = rtw_tdls_set_vht_operation(padapter, pframe, pattrib, pmlmeext->cur_channel);3033pframe = rtw_tdls_set_vht_op_mode_notify(padapter, pframe, pattrib, pmlmeext->cur_bwmode);3034}3035#endif3036}30373038void rtw_build_tdls_teardown_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, struct sta_info *ptdls_sta)3039{3040struct pkt_attrib *pattrib = &pxmitframe->attrib;3041u8 *pftie = NULL, *pftie_mic = NULL, *plinkid_ie = NULL;30423043pframe = rtw_tdls_set_payload_type(pframe, pattrib);3044pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);3045pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);3046pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);30473048if (pattrib->encrypt) {3049pftie = pframe;3050pftie_mic = pframe + 4;3051pframe = rtw_tdls_set_ftie(ptxmgmt3052, pframe3053, pattrib3054, ptdls_sta->ANonce3055, ptdls_sta->SNonce);3056}30573058plinkid_ie = pframe;3059if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)3060pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _FALSE);3061else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)3062pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _TRUE);30633064if (pattrib->encrypt && (rtw_tdls_is_driver_setup(padapter) == _TRUE))3065wpa_tdls_teardown_ftie_mic(ptdls_sta->tpk.kck, plinkid_ie, ptxmgmt->status_code, 1, 4, pftie, pftie_mic);3066}30673068void rtw_build_tdls_dis_req_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)3069{3070struct pkt_attrib *pattrib = &pxmitframe->attrib;30713072pframe = rtw_tdls_set_payload_type(pframe, pattrib);3073pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);3074pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);3075pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);3076pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _TRUE);30773078}30793080void rtw_build_tdls_dis_rsp_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, u8 privacy)3081{3082struct registry_priv *pregistrypriv = &padapter->registrypriv;3083struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;3084struct pkt_attrib *pattrib = &pxmitframe->attrib;3085u8 *pframe_head, pktlen_index;30863087pktlen_index = pattrib->pktlen;3088pframe_head = pframe;30893090pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_PUBLIC);3091pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);3092pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);3093pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);30943095pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);30963097pframe = rtw_tdls_set_sup_ch(padapter, pframe, pattrib);30983099if (privacy)3100pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, NULL);31013102pframe = rtw_tdls_set_ext_cap(pframe, pattrib);31033104if (privacy) {3105pframe = rtw_tdls_set_ftie(ptxmgmt, pframe, pattrib, NULL, NULL);3106pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, NULL);3107}31083109#ifdef CONFIG_80211N_HT3110if (pregistrypriv->ht_enable == _TRUE)3111pframe = rtw_tdls_set_ht_cap(padapter, pframe_head - pktlen_index, pattrib);3112#endif31133114pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);3115pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _FALSE);31163117}311831193120void rtw_build_tdls_peer_traffic_indication_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, struct sta_info *ptdls_sta)3121{31223123struct pkt_attrib *pattrib = &pxmitframe->attrib;3124u8 AC_queue = 0;31253126pframe = rtw_tdls_set_payload_type(pframe, pattrib);3127pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);3128pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);3129pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);31303131if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)3132pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _FALSE);3133else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)3134pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _TRUE);31353136/* PTI control */3137/* PU buffer status */3138if (ptdls_sta->uapsd_bk & BIT(1))3139AC_queue = BIT(0);3140if (ptdls_sta->uapsd_be & BIT(1))3141AC_queue = BIT(1);3142if (ptdls_sta->uapsd_vi & BIT(1))3143AC_queue = BIT(2);3144if (ptdls_sta->uapsd_vo & BIT(1))3145AC_queue = BIT(3);3146pframe = rtw_set_ie(pframe, _PTI_BUFFER_STATUS_, 1, &AC_queue, &(pattrib->pktlen));31473148}31493150void rtw_build_tdls_peer_traffic_rsp_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, struct sta_info *ptdls_sta)3151{31523153struct pkt_attrib *pattrib = &pxmitframe->attrib;31543155pframe = rtw_tdls_set_payload_type(pframe, pattrib);3156pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);3157pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);3158pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);31593160if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)3161pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _FALSE);3162else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)3163pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _TRUE);3164}31653166#ifdef CONFIG_TDLS_CH_SW3167void rtw_build_tdls_ch_switch_req_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, struct sta_info *ptdls_sta)3168{3169struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;3170struct pkt_attrib *pattrib = &pxmitframe->attrib;3171struct sta_priv *pstapriv = &padapter->stapriv;3172u16 switch_time = TDLS_CH_SWITCH_TIME * 1000, switch_timeout = TDLS_CH_SWITCH_TIMEOUT * 1000;31733174ptdls_sta->ch_switch_time = switch_time;3175ptdls_sta->ch_switch_timeout = switch_timeout;31763177pframe = rtw_tdls_set_payload_type(pframe, pattrib);3178pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);3179pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);3180pframe = rtw_tdls_set_target_ch(padapter, pframe, pattrib);3181pframe = rtw_tdls_set_reg_class(pframe, pattrib, ptdls_sta);31823183if (ptdlsinfo->chsw_info.ch_offset != HAL_PRIME_CHNL_OFFSET_DONT_CARE) {3184switch (ptdlsinfo->chsw_info.ch_offset) {3185case HAL_PRIME_CHNL_OFFSET_LOWER:3186pframe = rtw_tdls_set_second_channel_offset(pframe, pattrib, SCA);3187break;3188case HAL_PRIME_CHNL_OFFSET_UPPER:3189pframe = rtw_tdls_set_second_channel_offset(pframe, pattrib, SCB);3190break;3191}3192}31933194if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)3195pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _FALSE);3196else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)3197pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _TRUE);31983199pframe = rtw_tdls_set_ch_sw(pframe, pattrib, ptdls_sta);32003201}32023203void rtw_build_tdls_ch_switch_rsp_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, struct sta_info *ptdls_sta)3204{32053206struct pkt_attrib *pattrib = &pxmitframe->attrib;3207struct sta_priv *pstapriv = &padapter->stapriv;32083209pframe = rtw_tdls_set_payload_type(pframe, pattrib);3210pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);3211pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);3212pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);32133214if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)3215pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _FALSE);3216else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)3217pframe = rtw_tdls_set_linkid(padapter, pframe, pattrib, _TRUE);32183219pframe = rtw_tdls_set_ch_sw(pframe, pattrib, ptdls_sta);3220}3221#endif32223223#ifdef CONFIG_WFD3224void rtw_build_tunneled_probe_req_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe)3225{3226u8 i;3227_adapter *iface = NULL;3228struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);3229struct pkt_attrib *pattrib = &pxmitframe->attrib;3230struct wifidirect_info *pwdinfo;32313232u8 category = RTW_WLAN_CATEGORY_P2P;3233u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};3234u8 probe_req = 4;3235u8 wfdielen = 0;32363237pframe = rtw_tdls_set_payload_type(pframe, pattrib);3238pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));3239pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));3240pframe = rtw_set_fixed_ie(pframe, 1, &(probe_req), &(pattrib->pktlen));32413242for (i = 0; i < dvobj->iface_nums; i++) {3243iface = dvobj->padapters[i];3244if ((iface) && rtw_is_adapter_up(iface)) {3245pwdinfo = &iface->wdinfo;3246if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {3247wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);3248pframe += wfdielen;3249pattrib->pktlen += wfdielen;3250}3251}3252}3253}32543255void rtw_build_tunneled_probe_rsp_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe)3256{3257u8 i;3258_adapter *iface = NULL;3259struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);3260struct pkt_attrib *pattrib = &pxmitframe->attrib;3261struct wifidirect_info *pwdinfo;3262u8 category = RTW_WLAN_CATEGORY_P2P;3263u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};3264u8 probe_rsp = 5;3265u8 wfdielen = 0;32663267pframe = rtw_tdls_set_payload_type(pframe, pattrib);3268pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));3269pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));3270pframe = rtw_set_fixed_ie(pframe, 1, &(probe_rsp), &(pattrib->pktlen));32713272for (i = 0; i < dvobj->iface_nums; i++) {3273iface = dvobj->padapters[i];3274if ((iface) && rtw_is_adapter_up(iface)) {3275pwdinfo = &iface->wdinfo;3276if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {3277wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 1);3278pframe += wfdielen;3279pattrib->pktlen += wfdielen;3280}3281}3282}3283}3284#endif /* CONFIG_WFD */32853286void _tdls_tpk_timer_hdl(void *FunctionContext)3287{3288struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;3289struct tdls_txmgmt txmgmt;32903291_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));3292ptdls_sta->TPK_count++;3293/* TPK_timer expired in a second */3294/* Retry timer should set at least 301 sec. */3295if (ptdls_sta->TPK_count >= (ptdls_sta->TDLS_PeerKey_Lifetime - 3)) {3296RTW_INFO("[TDLS] %s, Re-Setup TDLS link with "MAC_FMT" since TPK lifetime expires!\n",3297__FUNCTION__, MAC_ARG(ptdls_sta->cmn.mac_addr));3298ptdls_sta->TPK_count = 0;3299_rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN);3300issue_tdls_setup_req(ptdls_sta->padapter, &txmgmt, _FALSE);3301}33023303_set_timer(&ptdls_sta->TPK_timer, ONE_SEC);3304}33053306#ifdef CONFIG_TDLS_CH_SW3307void _tdls_ch_switch_timer_hdl(void *FunctionContext)3308{3309struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;3310_adapter *padapter = ptdls_sta->padapter;3311struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;33123313rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_END_TO_BASE_CHNL);3314RTW_INFO("[TDLS] %s, can't get traffic from op_ch:%d\n", __func__, rtw_get_oper_ch(padapter));3315}33163317void _tdls_delay_timer_hdl(void *FunctionContext)3318{3319struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;3320_adapter *padapter = ptdls_sta->padapter;3321struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;33223323RTW_INFO("[TDLS] %s, op_ch:%d, tdls_state:0x%08x\n", __func__, rtw_get_oper_ch(padapter), ptdls_sta->tdls_sta_state);3324pchsw_info->delay_switch_back = _TRUE;3325}33263327void _tdls_stay_on_base_chnl_timer_hdl(void *FunctionContext)3328{3329struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;3330_adapter *padapter = ptdls_sta->padapter;3331struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;33323333if (ptdls_sta != NULL) {3334issue_tdls_ch_switch_req(padapter, ptdls_sta);3335pchsw_info->ch_sw_state |= TDLS_WAIT_CH_RSP_STATE;3336}3337}33383339void _tdls_ch_switch_monitor_timer_hdl(void *FunctionContext)3340{3341struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;3342_adapter *padapter = ptdls_sta->padapter;3343struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;33443345rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_END);3346RTW_INFO("[TDLS] %s, does not receive ch sw req\n", __func__);3347}33483349#endif33503351void _tdls_handshake_timer_hdl(void *FunctionContext)3352{3353struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;3354_adapter *padapter = NULL;3355struct tdls_txmgmt txmgmt;33563357_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));3358_rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN);3359txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;33603361if (ptdls_sta != NULL) {3362padapter = ptdls_sta->padapter;33633364RTW_INFO("[TDLS] Handshake time out\n");3365if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)3366rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_TEARDOWN_STA);3367else3368rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_TEARDOWN_STA_LOCALLY);3369}3370}33713372void _tdls_pti_timer_hdl(void *FunctionContext)3373{3374struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;3375_adapter *padapter = NULL;3376struct tdls_txmgmt txmgmt;33773378_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));3379_rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN);3380txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_;33813382if (ptdls_sta != NULL) {3383padapter = ptdls_sta->padapter;33843385if (ptdls_sta->tdls_sta_state & TDLS_WAIT_PTR_STATE) {3386RTW_INFO("[TDLS] Doesn't receive PTR from peer dev:"MAC_FMT"; "3387"Send TDLS Tear Down\n", MAC_ARG(ptdls_sta->cmn.mac_addr));3388rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_TEARDOWN_STA);3389}3390}3391}33923393void rtw_init_tdls_timer(_adapter *padapter, struct sta_info *psta)3394{3395psta->padapter = padapter;3396rtw_init_timer(&psta->TPK_timer, padapter, _tdls_tpk_timer_hdl, psta);3397#ifdef CONFIG_TDLS_CH_SW3398rtw_init_timer(&psta->ch_sw_timer, padapter, _tdls_ch_switch_timer_hdl, psta);3399rtw_init_timer(&psta->delay_timer, padapter, _tdls_delay_timer_hdl, psta);3400rtw_init_timer(&psta->stay_on_base_chnl_timer, padapter, _tdls_stay_on_base_chnl_timer_hdl, psta);3401rtw_init_timer(&psta->ch_sw_monitor_timer, padapter, _tdls_ch_switch_monitor_timer_hdl, psta);3402#endif3403rtw_init_timer(&psta->handshake_timer, padapter, _tdls_handshake_timer_hdl, psta);3404rtw_init_timer(&psta->pti_timer, padapter, _tdls_pti_timer_hdl, psta);3405}34063407void rtw_cancel_tdls_timer(struct sta_info *psta)3408{3409_cancel_timer_ex(&psta->TPK_timer);3410#ifdef CONFIG_TDLS_CH_SW3411_cancel_timer_ex(&psta->ch_sw_timer);3412_cancel_timer_ex(&psta->delay_timer);3413_cancel_timer_ex(&psta->stay_on_base_chnl_timer);3414_cancel_timer_ex(&psta->ch_sw_monitor_timer);3415#endif3416_cancel_timer_ex(&psta->handshake_timer);3417_cancel_timer_ex(&psta->pti_timer);3418}34193420void rtw_tdls_teardown_pre_hdl(_adapter *padapter, struct sta_info *psta)3421{3422struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;3423struct sta_priv *pstapriv = &padapter->stapriv;3424_irqL irqL;34253426rtw_cancel_tdls_timer(psta);34273428_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);3429if (ptdlsinfo->sta_cnt != 0)3430ptdlsinfo->sta_cnt--;3431_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);34323433if (ptdlsinfo->sta_cnt < MAX_ALLOWED_TDLS_STA_NUM) {3434ptdlsinfo->sta_maximum = _FALSE;3435_rtw_memset(&ptdlsinfo->ss_record, 0x00, sizeof(struct tdls_ss_record));3436}34373438if (ptdlsinfo->sta_cnt == 0)3439rtw_tdls_set_link_established(padapter, _FALSE);3440else3441RTW_INFO("Remain tdls sta:%02x\n", ptdlsinfo->sta_cnt);3442}34433444void rtw_tdls_teardown_post_hdl(_adapter *padapter, struct sta_info *psta, u8 enqueue_cmd)3445{3446struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;34473448/* Clear cam */3449rtw_clearstakey_cmd(padapter, psta, enqueue_cmd);34503451/* Update sta media status */3452if (enqueue_cmd)3453rtw_sta_media_status_rpt_cmd(padapter, psta, 0);3454else3455rtw_sta_media_status_rpt(padapter, psta, 0);34563457/* Set RCR if necessary */3458if (ptdlsinfo->sta_cnt == 0) {3459if (enqueue_cmd)3460rtw_tdls_cmd(padapter, NULL, TDLS_RS_RCR);3461else3462rtw_hal_rcr_set_chk_bssid(padapter, MLME_TDLS_NOLINK);3463}34643465/* Free tdls sta info */3466rtw_free_stainfo(padapter, psta);3467}34683469int rtw_tdls_is_driver_setup(_adapter *padapter)3470{3471return padapter->tdlsinfo.driver_setup;3472}34733474const char *rtw_tdls_action_txt(enum TDLS_ACTION_FIELD action)3475{3476switch (action) {3477case TDLS_SETUP_REQUEST:3478return "TDLS_SETUP_REQUEST";3479case TDLS_SETUP_RESPONSE:3480return "TDLS_SETUP_RESPONSE";3481case TDLS_SETUP_CONFIRM:3482return "TDLS_SETUP_CONFIRM";3483case TDLS_TEARDOWN:3484return "TDLS_TEARDOWN";3485case TDLS_PEER_TRAFFIC_INDICATION:3486return "TDLS_PEER_TRAFFIC_INDICATION";3487case TDLS_CHANNEL_SWITCH_REQUEST:3488return "TDLS_CHANNEL_SWITCH_REQUEST";3489case TDLS_CHANNEL_SWITCH_RESPONSE:3490return "TDLS_CHANNEL_SWITCH_RESPONSE";3491case TDLS_PEER_PSM_REQUEST:3492return "TDLS_PEER_PSM_REQUEST";3493case TDLS_PEER_PSM_RESPONSE:3494return "TDLS_PEER_PSM_RESPONSE";3495case TDLS_PEER_TRAFFIC_RESPONSE:3496return "TDLS_PEER_TRAFFIC_RESPONSE";3497case TDLS_DISCOVERY_REQUEST:3498return "TDLS_DISCOVERY_REQUEST";3499case TDLS_DISCOVERY_RESPONSE:3500return "TDLS_DISCOVERY_RESPONSE";3501default:3502return "UNKNOWN";3503}3504}35053506#endif /* CONFIG_TDLS */350735083509