Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_mlme_ext.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2019 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_MLME_EXT_C_1516#include <drv_types.h>17#ifdef CONFIG_IOCTL_CFG8021118#include <rtw_wifi_regd.h>19#endif /* CONFIG_IOCTL_CFG80211 */20#include <hal_data.h>212223struct mlme_handler mlme_sta_tbl[] = {24{WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq},25{WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp},26{WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq},27{WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp},28{WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq},29{WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp},3031/*----------------------------------------------------------32below 2 are reserved33-----------------------------------------------------------*/34{0, "DoReserved", &DoReserved},35{0, "DoReserved", &DoReserved},36{WIFI_BEACON, "OnBeacon", &OnBeacon},37{WIFI_ATIM, "OnATIM", &OnAtim},38{WIFI_DISASSOC, "OnDisassoc", &OnDisassoc},39{WIFI_AUTH, "OnAuth", &OnAuthClient},40{WIFI_DEAUTH, "OnDeAuth", &OnDeAuth},41{WIFI_ACTION, "OnAction", &OnAction},42{WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction},43};4445#ifdef _CONFIG_NATIVEAP_MLME_46struct mlme_handler mlme_ap_tbl[] = {47{WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq},48{WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp},49{WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq},50{WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp},51{WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq},52{WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp},5354/*----------------------------------------------------------55below 2 are reserved56-----------------------------------------------------------*/57{0, "DoReserved", &DoReserved},58{0, "DoReserved", &DoReserved},59{WIFI_BEACON, "OnBeacon", &OnBeacon},60{WIFI_ATIM, "OnATIM", &OnAtim},61{WIFI_DISASSOC, "OnDisassoc", &OnDisassoc},62{WIFI_AUTH, "OnAuth", &OnAuth},63{WIFI_DEAUTH, "OnDeAuth", &OnDeAuth},64{WIFI_ACTION, "OnAction", &OnAction},65{WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction},66};67#endif6869struct action_handler OnAction_tbl[] = {70{RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct},71{RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},72{RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},73{RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},74{RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},75{RTW_WLAN_CATEGORY_RADIO_MEAS, "ACTION_RADIO_MEAS", &on_action_rm},76{RTW_WLAN_CATEGORY_FT, "ACTION_FT", &OnAction_ft},77{RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht},78#ifdef CONFIG_IEEE80211W79{RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},80#else81{RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},82#endif /* CONFIG_IEEE80211W */83#ifdef CONFIG_RTW_WNM84{RTW_WLAN_CATEGORY_WNM, "ACTION_WNM", &on_action_wnm},85#endif86{RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved},87#ifdef CONFIG_RTW_MESH88{RTW_WLAN_CATEGORY_MESH, "ACTION_MESH", &on_action_mesh},89{RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &on_action_self_protected},90#endif91{RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},92{RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &OnAction_vht},93{RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},94};959697u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};9899/**************************************************100OUI definitions for the vendor specific IE101***************************************************/102unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};103unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};104unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};105unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};106unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};107108unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};109unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};110111unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};112unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};113114extern unsigned char REALTEK_96B_IE[];115116static void init_channel_list(_adapter *padapter, RT_CHANNEL_INFO *channel_set117, struct p2p_channels *channel_list)118{119struct registry_priv *regsty = adapter_to_regsty(padapter);120121struct p2p_oper_class_map op_class[] = {122{ IEEE80211G, 81, 1, 13, 1, BW20 },123{ IEEE80211G, 82, 14, 14, 1, BW20 },124#if 0 /* Do not enable HT40 on 2 GHz */125{ IEEE80211G, 83, 1, 9, 1, BW40PLUS },126{ IEEE80211G, 84, 5, 13, 1, BW40MINUS },127#endif128{ IEEE80211A, 115, 36, 48, 4, BW20 },129{ IEEE80211A, 116, 36, 44, 8, BW40PLUS },130{ IEEE80211A, 117, 40, 48, 8, BW40MINUS },131{ IEEE80211A, 124, 149, 161, 4, BW20 },132{ IEEE80211A, 125, 149, 169, 4, BW20 },133{ IEEE80211A, 126, 149, 157, 8, BW40PLUS },134{ IEEE80211A, 127, 153, 161, 8, BW40MINUS },135{ -1, 0, 0, 0, 0, BW20 }136};137138int cla, op;139140cla = 0;141142for (op = 0; op_class[op].op_class; op++) {143u8 ch;144struct p2p_oper_class_map *o = &op_class[op];145struct p2p_reg_class *reg = NULL;146147for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {148if (rtw_chset_search_ch(channel_set, ch) == -1)149continue;150#if defined(CONFIG_80211N_HT) || defined(CONFIG_80211AC_VHT)151if ((padapter->registrypriv.ht_enable == 0) && (o->inc == 8))152continue;153154if ((REGSTY_IS_BW_5G_SUPPORT(regsty, CHANNEL_WIDTH_40)) &&155((o->bw == BW40MINUS) || (o->bw == BW40PLUS)))156continue;157#endif158if (reg == NULL) {159reg = &channel_list->reg_class[cla];160cla++;161reg->reg_class = o->op_class;162reg->channels = 0;163}164reg->channel[reg->channels] = ch;165reg->channels++;166}167}168channel_list->reg_classes = cla;169170}171172#if CONFIG_TXPWR_LIMIT173void rtw_txpwr_init_regd(struct rf_ctl_t *rfctl)174{175u8 regd;176struct regd_exc_ent *exc;177struct txpwr_lmt_ent *ent;178_irqL irqL;179180_enter_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL);181182rfctl->regd_name = NULL;183184if (rfctl->txpwr_regd_num == 0) {185RTW_PRINT("there is no any txpwr_regd\n");186goto release_lock;187}188189/* search from exception mapping */190exc = _rtw_regd_exc_search(rfctl191, rfctl->country_ent ? rfctl->country_ent->alpha2 : NULL192, rfctl->ChannelPlan);193if (exc) {194u8 has_country = (exc->country[0] == '\0' && exc->country[1] == '\0') ? 0 : 1;195196if (strcmp(exc->regd_name, regd_str(TXPWR_LMT_NONE)) == 0)197rfctl->regd_name = regd_str(TXPWR_LMT_NONE);198else if (strcmp(exc->regd_name, regd_str(TXPWR_LMT_WW)) == 0)199rfctl->regd_name = regd_str(TXPWR_LMT_WW);200else {201ent = _rtw_txpwr_lmt_get_by_name(rfctl, exc->regd_name);202if (ent)203rfctl->regd_name = ent->regd_name;204}205206RTW_PRINT("exception mapping country:%c%c domain:0x%02x to%s regd_name:%s\n"207, has_country ? exc->country[0] : '0'208, has_country ? exc->country[1] : '0'209, exc->domain210, rfctl->regd_name ? "" : " unknown"211, exc->regd_name212);213if (rfctl->regd_name)214goto release_lock;215}216217/* follow default channel plan mapping */218regd = rtw_chplan_get_default_regd(rfctl->ChannelPlan);219if (regd == TXPWR_LMT_NONE)220rfctl->regd_name = regd_str(TXPWR_LMT_NONE);221else if (regd == TXPWR_LMT_WW)222rfctl->regd_name = regd_str(TXPWR_LMT_WW);223else {224ent = _rtw_txpwr_lmt_get_by_name(rfctl, regd_str(regd));225if (ent)226rfctl->regd_name = ent->regd_name;227}228229RTW_PRINT("default mapping domain:0x%02x to%s regd_name:%s\n"230, rfctl->ChannelPlan231, rfctl->regd_name ? "" : " unknown"232, regd_str(regd)233);234if (rfctl->regd_name)235goto release_lock;236237switch (regd) {238/*239* To support older chips without new predefined regd:240* - use FCC if IC or CHILE or MEXICO not found241* - use ETSI if KCC or ACMA not found242*/243case TXPWR_LMT_IC:244case TXPWR_LMT_KCC:245case TXPWR_LMT_ACMA:246case TXPWR_LMT_CHILE:247case TXPWR_LMT_MEXICO:248if (regd == TXPWR_LMT_IC || regd == TXPWR_LMT_CHILE || regd == TXPWR_LMT_MEXICO)249regd = TXPWR_LMT_FCC;250else if (regd == TXPWR_LMT_KCC || regd == TXPWR_LMT_ACMA)251regd = TXPWR_LMT_ETSI;252ent = _rtw_txpwr_lmt_get_by_name(rfctl, regd_str(regd));253if (ent)254rfctl->regd_name = ent->regd_name;255RTW_PRINT("alternate regd_name:%s %s\n"256, regd_str(regd)257, rfctl->regd_name ? "is used" : "not found"258);259if (rfctl->regd_name)260break;261/* fall through */262default:263rfctl->regd_name = regd_str(TXPWR_LMT_WW);264RTW_PRINT("assign %s for default case\n", regd_str(TXPWR_LMT_WW));265break;266};267268release_lock:269_exit_critical_mutex(&rfctl->txpwr_lmt_mutex, &irqL);270}271#endif /* CONFIG_TXPWR_LIMIT */272273void rtw_rfctl_init(_adapter *adapter)274{275struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);276277rfctl->max_chan_nums = init_channel_set(adapter, rfctl->ChannelPlan, rfctl->channel_set);278init_channel_list(adapter, rfctl->channel_set, &rfctl->channel_list);279280_rtw_mutex_init(&rfctl->offch_mutex);281282#if CONFIG_TXPWR_LIMIT283_rtw_mutex_init(&rfctl->txpwr_lmt_mutex);284_rtw_init_listhead(&rfctl->reg_exc_list);285_rtw_init_listhead(&rfctl->txpwr_lmt_list);286#endif287288rfctl->ch_sel_same_band_prefer = 1;289290#ifdef CONFIG_DFS_MASTER291rfctl->cac_start_time = rfctl->cac_end_time = RTW_CAC_STOPPED;292rtw_init_timer(&(rfctl->radar_detect_timer), adapter, rtw_dfs_rd_timer_hdl, rfctl);293#endif294#ifdef CONFIG_DFS_SLAVE_WITH_RADAR_DETECT295rfctl->dfs_slave_with_rd = 1;296#endif297}298299void rtw_rfctl_deinit(_adapter *adapter)300{301struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);302303_rtw_mutex_free(&rfctl->offch_mutex);304305#if CONFIG_TXPWR_LIMIT306rtw_regd_exc_list_free(rfctl);307rtw_txpwr_lmt_list_free(rfctl);308_rtw_mutex_free(&rfctl->txpwr_lmt_mutex);309#endif310}311312#ifdef CONFIG_DFS_MASTER313/*314* called in rtw_dfs_rd_enable()315* assume the request channel coverage is DFS range316* base on the current status and the request channel coverage to check if need to reset complete CAC time317*/318bool rtw_is_cac_reset_needed(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset)319{320bool needed = _FALSE;321u32 cur_hi, cur_lo, hi, lo;322323if (rfctl->radar_detected == 1) {324needed = _TRUE;325goto exit;326}327328if (rfctl->radar_detect_ch == 0) {329needed = _TRUE;330goto exit;331}332333if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) {334RTW_ERR("request detection range ch:%u, bw:%u, offset:%u\n", ch, bw, offset);335rtw_warn_on(1);336}337338if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset, &cur_hi, &cur_lo) == _FALSE) {339RTW_ERR("cur detection range ch:%u, bw:%u, offset:%u\n", rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);340rtw_warn_on(1);341}342343if (hi <= lo || cur_hi <= cur_lo) {344RTW_ERR("hi:%u, lo:%u, cur_hi:%u, cur_lo:%u\n", hi, lo, cur_hi, cur_lo);345rtw_warn_on(1);346}347348if (rtw_is_range_a_in_b(hi, lo, cur_hi, cur_lo)) {349/* request is in current detect range */350goto exit;351}352353/* check if request channel coverage has new range and the new range is in DFS range */354if (!rtw_is_range_overlap(hi, lo, cur_hi, cur_lo)) {355/* request has no overlap with current */356needed = _TRUE;357} else if (rtw_is_range_a_in_b(cur_hi, cur_lo, hi, lo)) {358/* request is supper set of current */359if ((hi != cur_hi && rtw_is_dfs_range(hi, cur_hi)) || (lo != cur_lo && rtw_is_dfs_range(cur_lo, lo)))360needed = _TRUE;361} else {362/* request is not supper set of current, but has overlap */363if ((lo < cur_lo && rtw_is_dfs_range(cur_lo, lo)) || (hi > cur_hi && rtw_is_dfs_range(hi, cur_hi)))364needed = _TRUE;365}366367exit:368return needed;369}370371bool _rtw_rfctl_overlap_radar_detect_ch(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset)372{373bool ret = _FALSE;374u32 hi = 0, lo = 0;375u32 r_hi = 0, r_lo = 0;376int i;377378if (rfctl->radar_detect_by_others)379goto exit;380381if (rfctl->radar_detect_ch == 0)382goto exit;383384if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) {385rtw_warn_on(1);386goto exit;387}388389if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch390, rfctl->radar_detect_bw, rfctl->radar_detect_offset391, &r_hi, &r_lo) == _FALSE) {392rtw_warn_on(1);393goto exit;394}395396if (rtw_is_range_overlap(hi, lo, r_hi, r_lo))397ret = _TRUE;398399exit:400return ret;401}402403bool rtw_rfctl_overlap_radar_detect_ch(struct rf_ctl_t *rfctl)404{405return _rtw_rfctl_overlap_radar_detect_ch(rfctl406, rfctl_to_dvobj(rfctl)->oper_channel407, rfctl_to_dvobj(rfctl)->oper_bwmode408, rfctl_to_dvobj(rfctl)->oper_ch_offset);409}410411bool rtw_rfctl_is_tx_blocked_by_ch_waiting(struct rf_ctl_t *rfctl)412{413return rtw_rfctl_overlap_radar_detect_ch(rfctl) && IS_CH_WAITING(rfctl);414}415416bool rtw_chset_is_chbw_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset)417{418bool ret = _FALSE;419u32 hi = 0, lo = 0;420int i;421422if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)423goto exit;424425for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) {426if (!rtw_ch2freq(ch_set[i].ChannelNum)) {427rtw_warn_on(1);428continue;429}430431if (!CH_IS_NON_OCP(&ch_set[i]))432continue;433434if (lo <= rtw_ch2freq(ch_set[i].ChannelNum)435&& rtw_ch2freq(ch_set[i].ChannelNum) <= hi436) {437ret = _TRUE;438break;439}440}441442exit:443return ret;444}445446bool rtw_chset_is_ch_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch)447{448return rtw_chset_is_chbw_non_ocp(ch_set, ch, CHANNEL_WIDTH_20, HAL_PRIME_CHNL_OFFSET_DONT_CARE);449}450451u32 rtw_chset_get_ch_non_ocp_ms(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset)452{453int ms = 0;454systime current_time;455u32 hi = 0, lo = 0;456int i;457458if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)459goto exit;460461current_time = rtw_get_current_time();462463for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) {464if (!rtw_ch2freq(ch_set[i].ChannelNum)) {465rtw_warn_on(1);466continue;467}468469if (!CH_IS_NON_OCP(&ch_set[i]))470continue;471472if (lo <= rtw_ch2freq(ch_set[i].ChannelNum)473&& rtw_ch2freq(ch_set[i].ChannelNum) <= hi474) {475if (rtw_systime_to_ms(ch_set[i].non_ocp_end_time - current_time) > ms)476ms = rtw_systime_to_ms(ch_set[i].non_ocp_end_time - current_time);477}478}479480exit:481return ms;482}483484/**485* rtw_chset_update_non_ocp - update non_ocp_end_time according to the given @ch, @bw, @offset into @ch_set486* @ch_set: the given channel set487* @ch: channel number on which radar is detected488* @bw: bandwidth on which radar is detected489* @offset: bandwidth offset on which radar is detected490* @ms: ms to add from now to update non_ocp_end_time, ms < 0 means use NON_OCP_TIME_MS491*/492static void _rtw_chset_update_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset, int ms)493{494u32 hi = 0, lo = 0;495int i;496497if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)498goto exit;499500for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) {501if (!rtw_ch2freq(ch_set[i].ChannelNum)) {502rtw_warn_on(1);503continue;504}505506if (lo <= rtw_ch2freq(ch_set[i].ChannelNum)507&& rtw_ch2freq(ch_set[i].ChannelNum) <= hi508) {509if (ms >= 0)510ch_set[i].non_ocp_end_time = rtw_get_current_time() + rtw_ms_to_systime(ms);511else512ch_set[i].non_ocp_end_time = rtw_get_current_time() + rtw_ms_to_systime(NON_OCP_TIME_MS);513}514}515516exit:517return;518}519520inline void rtw_chset_update_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset)521{522_rtw_chset_update_non_ocp(ch_set, ch, bw, offset, -1);523}524525inline void rtw_chset_update_non_ocp_ms(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset, int ms)526{527_rtw_chset_update_non_ocp(ch_set, ch, bw, offset, ms);528}529530u32 rtw_get_ch_waiting_ms(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset, u32 *r_non_ocp_ms, u32 *r_cac_ms)531{532struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);533u32 non_ocp_ms;534u32 cac_ms;535u8 in_rd_range = 0; /* if in current radar detection range*/536537if (rtw_chset_is_chbw_non_ocp(rfctl->channel_set, ch, bw, offset))538non_ocp_ms = rtw_chset_get_ch_non_ocp_ms(rfctl->channel_set, ch, bw, offset);539else540non_ocp_ms = 0;541542if (rfctl->radar_detect_enabled) {543u32 cur_hi, cur_lo, hi, lo;544545if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) {546RTW_ERR("input range ch:%u, bw:%u, offset:%u\n", ch, bw, offset);547rtw_warn_on(1);548}549550if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset, &cur_hi, &cur_lo) == _FALSE) {551RTW_ERR("cur detection range ch:%u, bw:%u, offset:%u\n", rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);552rtw_warn_on(1);553}554555if (rtw_is_range_a_in_b(hi, lo, cur_hi, cur_lo))556in_rd_range = 1;557}558559if (!rtw_is_dfs_chbw(ch, bw, offset))560cac_ms = 0;561else if (in_rd_range && !non_ocp_ms) {562if (IS_CH_WAITING(rfctl))563cac_ms = rtw_systime_to_ms(rfctl->cac_end_time - rtw_get_current_time());564else565cac_ms = 0;566} else if (rtw_is_long_cac_ch(ch, bw, offset, rtw_odm_get_dfs_domain(dvobj)))567cac_ms = CAC_TIME_CE_MS;568else569cac_ms = CAC_TIME_MS;570571if (r_non_ocp_ms)572*r_non_ocp_ms = non_ocp_ms;573if (r_cac_ms)574*r_cac_ms = cac_ms;575576return non_ocp_ms + cac_ms;577}578579void rtw_reset_cac(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset)580{581u32 non_ocp_ms;582u32 cac_ms;583584rtw_get_ch_waiting_ms(rfctl585, ch586, bw587, offset588, &non_ocp_ms589, &cac_ms590);591592rfctl->cac_start_time = rtw_get_current_time() + rtw_ms_to_systime(non_ocp_ms);593rfctl->cac_end_time = rfctl->cac_start_time + rtw_ms_to_systime(cac_ms);594595/* skip special value */596if (rfctl->cac_start_time == RTW_CAC_STOPPED) {597rfctl->cac_start_time++;598rfctl->cac_end_time++;599}600if (rfctl->cac_end_time == RTW_CAC_STOPPED)601rfctl->cac_end_time++;602}603604u32 rtw_force_stop_cac(struct rf_ctl_t *rfctl, u32 timeout_ms)605{606struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);607systime start;608u32 pass_ms;609610start = rtw_get_current_time();611612rfctl->cac_force_stop = 1;613614while (rtw_get_passing_time_ms(start) <= timeout_ms615&& IS_UNDER_CAC(rfctl)616) {617if (dev_is_surprise_removed(dvobj) || dev_is_drv_stopped(dvobj))618break;619rtw_msleep_os(20);620}621622if (IS_UNDER_CAC(rfctl)) {623if (!dev_is_surprise_removed(dvobj) && !dev_is_drv_stopped(dvobj))624RTW_INFO("%s waiting for cac stop timeout!\n", __func__);625}626627rfctl->cac_force_stop = 0;628629pass_ms = rtw_get_passing_time_ms(start);630631return pass_ms;632}633#endif /* CONFIG_DFS_MASTER */634635/* choose channel with shortest waiting (non ocp + cac) time */636bool rtw_choose_shortest_waiting_ch(struct rf_ctl_t *rfctl, u8 sel_ch, u8 max_bw637, u8 *dec_ch, u8 *dec_bw, u8 *dec_offset638, u8 d_flags, u8 cur_ch, u8 same_band_prefer, u8 mesh_only)639{640#ifndef DBG_CHOOSE_SHORTEST_WAITING_CH641#define DBG_CHOOSE_SHORTEST_WAITING_CH 0642#endif643struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);644struct registry_priv *regsty = dvobj_to_regsty(dvobj);645u8 ch, bw, offset;646u8 ch_c = 0, bw_c = 0, offset_c = 0;647int i;648u32 min_waiting_ms = 0;649650if (!dec_ch || !dec_bw || !dec_offset) {651rtw_warn_on(1);652return _FALSE;653}654655/* full search and narrow bw judegement first to avoid potetial judegement timing issue */656for (bw = CHANNEL_WIDTH_20; bw <= max_bw; bw++) {657if (!hal_is_bw_support(dvobj_get_primary_adapter(dvobj), bw))658continue;659660for (i = 0; i < rfctl->max_chan_nums; i++) {661u32 non_ocp_ms = 0;662u32 cac_ms = 0;663u32 waiting_ms = 0;664665ch = rfctl->channel_set[i].ChannelNum;666if (sel_ch > 0 && ch != sel_ch)667continue;668669if ((d_flags & RTW_CHF_2G) && ch <= 14)670continue;671672if ((d_flags & RTW_CHF_5G) && ch > 14)673continue;674675if (ch > 14) {676if (bw > REGSTY_BW_5G(regsty))677continue;678} else {679if (bw > REGSTY_BW_2G(regsty))680continue;681}682683if (mesh_only && ch >= 5 && ch <= 9 && bw > CHANNEL_WIDTH_20)684continue;685686if (!rtw_get_offset_by_chbw(ch, bw, &offset))687continue;688689if (!rtw_chset_is_chbw_valid(rfctl->channel_set, ch, bw, offset))690continue;691692if ((d_flags & RTW_CHF_NON_OCP) && rtw_chset_is_chbw_non_ocp(rfctl->channel_set, ch, bw, offset))693continue;694695if ((d_flags & RTW_CHF_DFS) && rtw_is_dfs_chbw(ch, bw, offset))696continue;697698if ((d_flags & RTW_CHF_LONG_CAC) && rtw_is_long_cac_ch(ch, bw, offset, rtw_odm_get_dfs_domain(dvobj)))699continue;700701if ((d_flags & RTW_CHF_NON_DFS) && !rtw_is_dfs_chbw(ch, bw, offset))702continue;703704if ((d_flags & RTW_CHF_NON_LONG_CAC) && !rtw_is_long_cac_ch(ch, bw, offset, rtw_odm_get_dfs_domain(dvobj)))705continue;706707#ifdef CONFIG_DFS_MASTER708waiting_ms = rtw_get_ch_waiting_ms(rfctl, ch, bw, offset, &non_ocp_ms, &cac_ms);709#endif710711if (DBG_CHOOSE_SHORTEST_WAITING_CH)712RTW_INFO("%s:%u,%u,%u %u(non_ocp:%u, cac:%u)\n"713, __func__, ch, bw, offset, waiting_ms, non_ocp_ms, cac_ms);714715if (ch_c == 0716/* first: smaller wating time */717|| min_waiting_ms > waiting_ms718/* then: wider bw */719|| (min_waiting_ms == waiting_ms && bw > bw_c)720/* then: same band if requested */721|| (same_band_prefer && min_waiting_ms == waiting_ms && bw == bw_c722&& !rtw_is_same_band(cur_ch, ch_c) && rtw_is_same_band(cur_ch, ch))723) {724ch_c = ch;725bw_c = bw;726offset_c = offset;727min_waiting_ms = waiting_ms;728}729}730}731732if (ch_c != 0) {733RTW_INFO("%s: d_flags:0x%02x cur_ch:%u sb_prefer:%u%s %u,%u,%u waiting_ms:%u\n"734, __func__, d_flags, cur_ch, same_band_prefer735, mesh_only ? " mesh_only" : ""736, ch_c, bw_c, offset_c, min_waiting_ms);737738*dec_ch = ch_c;739*dec_bw = bw_c;740*dec_offset = offset_c;741return _TRUE;742}743744if (d_flags == 0) {745RTW_INFO("%s: sel_ch:%u max_bw:%u d_flags:0x%02x cur_ch:%u sb_prefer:%u%s\n"746, __func__, sel_ch, max_bw, d_flags, cur_ch, same_band_prefer747, mesh_only ? " mesh_only" : "");748rtw_warn_on(1);749}750751return _FALSE;752}753754void dump_chset(void *sel, RT_CHANNEL_INFO *ch_set)755{756u8 i;757758for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) {759RTW_PRINT_SEL(sel, "ch:%3u, freq:%u, scan_type:%d"760, ch_set[i].ChannelNum, rtw_ch2freq(ch_set[i].ChannelNum), ch_set[i].ScanType);761762#ifdef CONFIG_FIND_BEST_CHANNEL763_RTW_PRINT_SEL(sel, ", rx_count:%u", ch_set[i].rx_count);764#endif765766#ifdef CONFIG_DFS_MASTER767if (rtw_is_dfs_ch(ch_set[i].ChannelNum)) {768if (CH_IS_NON_OCP(&ch_set[i]))769_RTW_PRINT_SEL(sel, ", non_ocp:%d"770, rtw_systime_to_ms(ch_set[i].non_ocp_end_time - rtw_get_current_time()));771else772_RTW_PRINT_SEL(sel, ", non_ocp:N/A");773}774#endif775776_RTW_PRINT_SEL(sel, "\n");777}778779RTW_PRINT_SEL(sel, "total ch number:%d\n", i);780}781782void dump_cur_chset(void *sel, struct rf_ctl_t *rfctl)783{784struct dvobj_priv *dvobj = rfctl_to_dvobj(rfctl);785struct registry_priv *regsty = dvobj_to_regsty(dvobj);786int i;787788if (rfctl->country_ent)789dump_country_chplan(sel, rfctl->country_ent);790else791RTW_PRINT_SEL(sel, "chplan:0x%02X\n", rfctl->ChannelPlan);792793#if CONFIG_TXPWR_LIMIT794RTW_PRINT_SEL(sel, "PLS regd:%s\n", rfctl->regd_name);795#endif796797#ifdef CONFIG_DFS_MASTER798RTW_PRINT_SEL(sel, "dfs_domain:%u\n", rtw_odm_get_dfs_domain(dvobj));799#endif800801for (i = 0; i < MAX_CHANNEL_NUM; i++)802if (regsty->excl_chs[i] != 0)803break;804805if (i < MAX_CHANNEL_NUM) {806RTW_PRINT_SEL(sel, "excl_chs:");807for (i = 0; i < MAX_CHANNEL_NUM; i++) {808if (regsty->excl_chs[i] == 0)809break;810_RTW_PRINT_SEL(sel, "%u ", regsty->excl_chs[i]);811}812_RTW_PRINT_SEL(sel, "\n");813}814815dump_chset(sel, rfctl->channel_set);816}817818/*819* Search the @param ch in given @param ch_set820* @ch_set: the given channel set821* @ch: the given channel number822*823* return the index of channel_num in channel_set, -1 if not found824*/825int rtw_chset_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch)826{827int i;828829if (ch == 0)830return -1;831832for (i = 0; i < MAX_CHANNEL_NUM && ch_set[i].ChannelNum != 0; i++) {833if (ch == ch_set[i].ChannelNum)834return i;835}836837return -1;838}839840/*841* Check if the @param ch, bw, offset is valid for the given @param ch_set842* @ch_set: the given channel set843* @ch: the given channel number844* @bw: the given bandwidth845* @offset: the given channel offset846*847* return valid (1) or not (0)848*/849u8 rtw_chset_is_chbw_valid(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset)850{851u8 cch;852u8 *op_chs;853u8 op_ch_num;854u8 valid = 0;855int i;856857cch = rtw_get_center_ch(ch, bw, offset);858859if (!rtw_get_op_chs_by_cch_bw(cch, bw, &op_chs, &op_ch_num))860goto exit;861862for (i = 0; i < op_ch_num; i++) {863if (0)864RTW_INFO("%u,%u,%u - cch:%u, bw:%u, op_ch:%u\n", ch, bw, offset, cch, bw, *(op_chs + i));865if (rtw_chset_search_ch(ch_set, *(op_chs + i)) == -1)866break;867}868869if (op_ch_num != 0 && i == op_ch_num)870valid = 1;871872exit:873return valid;874}875876/**877* rtw_chset_sync_chbw - obey g_ch, adjust g_bw, g_offset, bw, offset to fit in channel plan878* @ch_set: channel plan to check879* @req_ch: pointer of the request ch, may be modified further880* @req_bw: pointer of the request bw, may be modified further881* @req_offset: pointer of the request offset, may be modified further882* @g_ch: pointer of the ongoing group ch883* @g_bw: pointer of the ongoing group bw, may be modified further884* @g_offset: pointer of the ongoing group offset, may be modified further885*/886void rtw_chset_sync_chbw(RT_CHANNEL_INFO *ch_set, u8 *req_ch, u8 *req_bw, u8 *req_offset887, u8 *g_ch, u8 *g_bw, u8 *g_offset)888{889u8 r_ch, r_bw, r_offset;890u8 u_ch, u_bw, u_offset;891u8 cur_bw = *req_bw;892893while (1) {894r_ch = *req_ch;895r_bw = cur_bw;896r_offset = *req_offset;897u_ch = *g_ch;898u_bw = *g_bw;899u_offset = *g_offset;900901rtw_sync_chbw(&r_ch, &r_bw, &r_offset, &u_ch, &u_bw, &u_offset);902903if (rtw_chset_is_chbw_valid(ch_set, r_ch, r_bw, r_offset))904break;905if (cur_bw == CHANNEL_WIDTH_20) {906rtw_warn_on(1);907break;908}909cur_bw--;910};911912*req_ch = r_ch;913*req_bw = r_bw;914*req_offset = r_offset;915*g_ch = u_ch;916*g_bw = u_bw;917*g_offset = u_offset;918}919920/*921* Check the @param ch is fit with setband setting of @param adapter922* @adapter: the given adapter923* @ch: the given channel number924*925* return _TRUE when check valid, _FALSE not valid926*/927bool rtw_mlme_band_check(_adapter *adapter, const u32 ch)928{929if (adapter->setband == WIFI_FREQUENCY_BAND_AUTO /* 2.4G and 5G */930|| (adapter->setband == WIFI_FREQUENCY_BAND_2GHZ && ch < 35) /* 2.4G only */931|| (adapter->setband == WIFI_FREQUENCY_BAND_5GHZ && ch > 35) /* 5G only */932)933return _TRUE;934return _FALSE;935}936inline void RTW_SET_SCAN_BAND_SKIP(_adapter *padapter, int skip_band)937{938int bs = ATOMIC_READ(&padapter->bandskip);939940bs |= skip_band;941ATOMIC_SET(&padapter->bandskip, bs);942}943944inline void RTW_CLR_SCAN_BAND_SKIP(_adapter *padapter, int skip_band)945{946int bs = ATOMIC_READ(&padapter->bandskip);947948bs &= ~(skip_band);949ATOMIC_SET(&padapter->bandskip, bs);950}951inline int RTW_GET_SCAN_BAND_SKIP(_adapter *padapter)952{953return ATOMIC_READ(&padapter->bandskip);954}955956#define RTW_IS_SCAN_BAND_SKIP(padapter, skip_band) (ATOMIC_READ(&padapter->bandskip) & (skip_band))957958bool rtw_mlme_ignore_chan(_adapter *adapter, const u32 ch)959{960if (RTW_IS_SCAN_BAND_SKIP(adapter, BAND_24G) && ch < 35) /* SKIP 2.4G Band channel */961return _TRUE;962if (RTW_IS_SCAN_BAND_SKIP(adapter, BAND_5G) && ch > 35) /* SKIP 5G Band channel */963return _TRUE;964965return _FALSE;966}967968969/****************************************************************************970971Following are the initialization functions for WiFi MLME972973*****************************************************************************/974975int init_hw_mlme_ext(_adapter *padapter)976{977struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;978HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);979u8 rx_bar_enble = _TRUE;980981/*982* Sync driver status and hardware setting983*/984985/* Modify to make sure first time change channel(band) would be done properly */986pHalData->current_channel = 0;987pHalData->current_channel_bw = CHANNEL_WIDTH_MAX;988#ifdef CONFIG_IEEE80211_BAND_5GHZ989pHalData->current_band_type = BAND_MAX;990#else991pHalData->current_band_type = BAND_ON_2_4G;992#endif993994/* set_opmode_cmd(padapter, infra_client_with_mlme); */ /* removed */995rtw_hal_set_hwreg(padapter, HW_VAR_ENABLE_RX_BAR, &rx_bar_enble);996set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);997998return _SUCCESS;999}10001001void init_mlme_default_rate_set(_adapter *padapter)1002{1003struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1004unsigned char end_set[1] = {0xff};1005u8 offset_datarate = 0;1006u8 offset_basicrate = 0;1007#ifdef CONFIG_80211N_HT1008unsigned char supported_mcs_set[16] = {0xff, 0xff, 0xff, 0xff, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};1009#endif10101011if (IsSupportedTxCCK(padapter->registrypriv.wireless_mode)) {10121013unsigned char datarate_b[B_MODE_RATE_NUM] ={_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_};1014_rtw_memcpy(pmlmeext->datarate, datarate_b, B_MODE_RATE_NUM);1015_rtw_memcpy(pmlmeext->basicrate, datarate_b, B_MODE_RATE_NUM);1016offset_datarate += B_MODE_RATE_NUM;1017offset_basicrate += B_MODE_RATE_NUM;1018RTW_INFO("%s: support CCK\n", __func__);1019}1020if(IsSupportedTxOFDM(padapter->registrypriv.wireless_mode)) {1021unsigned char datarate_g[G_MODE_RATE_NUM] ={_6M_RATE_, _9M_RATE_, _12M_RATE_, _18M_RATE_,_24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_};1022unsigned char basicrate_g[G_MODE_BASIC_RATE_NUM] = {_6M_RATE_, _12M_RATE_, _24M_RATE_};1023_rtw_memcpy(pmlmeext->datarate + offset_datarate, datarate_g, G_MODE_RATE_NUM);1024_rtw_memcpy(pmlmeext->basicrate + offset_basicrate,basicrate_g, G_MODE_BASIC_RATE_NUM);1025offset_datarate += G_MODE_RATE_NUM;1026offset_basicrate += G_MODE_BASIC_RATE_NUM;1027RTW_INFO("%s: support OFDM\n", __func__);10281029}1030_rtw_memcpy(pmlmeext->datarate + offset_datarate, end_set, 1);1031_rtw_memcpy(pmlmeext->basicrate + offset_basicrate, end_set, 1);10321033#ifdef CONFIG_80211N_HT1034if( padapter->registrypriv.ht_enable && is_supported_ht(padapter->registrypriv.wireless_mode))1035_rtw_memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set));1036#endif1037}10381039static void init_mlme_ext_priv_value(_adapter *padapter)1040{1041struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1042struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);10431044ATOMIC_SET(&pmlmeext->event_seq, 0);1045pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */1046#ifdef CONFIG_IEEE80211W1047pmlmeext->sa_query_seq = 0;1048#endif1049pmlmeext->cur_channel = padapter->registrypriv.channel;1050pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;1051pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;10521053pmlmeext->retry = 0;10541055pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;1056init_mlme_default_rate_set(padapter);10571058if ((pmlmeext->cur_channel > 14) || ((padapter->registrypriv.wireless_mode & WIRELESS_11B) == 0))1059pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;1060else1061pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;10621063mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE);1064pmlmeext->sitesurvey_res.channel_idx = 0;1065pmlmeext->sitesurvey_res.bss_cnt = 0;1066pmlmeext->sitesurvey_res.scan_ch_ms = SURVEY_TO;1067pmlmeext->sitesurvey_res.rx_ampdu_accept = RX_AMPDU_ACCEPT_INVALID;1068pmlmeext->sitesurvey_res.rx_ampdu_size = RX_AMPDU_SIZE_INVALID;1069#ifdef CONFIG_SCAN_BACKOP1070mlmeext_assign_scan_backop_flags_sta(pmlmeext, /*SS_BACKOP_EN|*/SS_BACKOP_PS_ANNC | SS_BACKOP_TX_RESUME);1071#ifdef CONFIG_AP_MODE1072mlmeext_assign_scan_backop_flags_ap(pmlmeext, SS_BACKOP_EN | SS_BACKOP_PS_ANNC | SS_BACKOP_TX_RESUME);1073#endif1074#ifdef CONFIG_RTW_MESH1075mlmeext_assign_scan_backop_flags_mesh(pmlmeext, /*SS_BACKOP_EN | */SS_BACKOP_PS_ANNC | SS_BACKOP_TX_RESUME);1076#endif1077pmlmeext->sitesurvey_res.scan_cnt = 0;1078pmlmeext->sitesurvey_res.scan_cnt_max = RTW_SCAN_NUM_OF_CH;1079pmlmeext->sitesurvey_res.backop_ms = RTW_BACK_OP_CH_MS;1080#endif1081#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)1082pmlmeext->sitesurvey_res.is_sw_antdiv_bl_scan = 0;1083#endif1084pmlmeext->scan_abort = _FALSE;10851086pmlmeinfo->state = WIFI_FW_NULL_STATE;1087pmlmeinfo->reauth_count = 0;1088pmlmeinfo->reassoc_count = 0;1089pmlmeinfo->link_count = 0;1090pmlmeinfo->auth_seq = 0;1091pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;1092pmlmeinfo->key_index = 0;1093pmlmeinfo->iv = 0;10941095pmlmeinfo->enc_algo = _NO_PRIVACY_;1096pmlmeinfo->authModeToggle = 0;10971098_rtw_memset(pmlmeinfo->chg_txt, 0, 128);10991100pmlmeinfo->slotTime = SHORT_SLOT_TIME;1101pmlmeinfo->preamble_mode = PREAMBLE_AUTO;11021103pmlmeinfo->dialogToken = 0;11041105pmlmeext->action_public_rxseq = 0xffff;1106pmlmeext->action_public_dialog_token = 0xff;1107#ifdef ROKU_PRIVATE1108/*infra mode, used to store AP's info*/1109_rtw_memset(pmlmeinfo->SupportedRates_infra_ap, 0, NDIS_802_11_LENGTH_RATES_EX);1110pmlmeinfo->ht_vht_received = 0;1111#endif /* ROKU_PRIVATE */1112}11131114void init_mlme_ext_timer(_adapter *padapter)1115{1116struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11171118rtw_init_timer(&pmlmeext->survey_timer, padapter, survey_timer_hdl, padapter);1119rtw_init_timer(&pmlmeext->link_timer, padapter, link_timer_hdl, padapter);1120#ifdef CONFIG_RTW_80211R1121rtw_init_timer(&pmlmeext->ft_link_timer, padapter, rtw_ft_link_timer_hdl, padapter);1122rtw_init_timer(&pmlmeext->ft_roam_timer, padapter, rtw_ft_roam_timer_hdl, padapter);1123#endif11241125#ifdef CONFIG_RTW_REPEATER_SON1126rtw_init_timer(&pmlmeext->rson_scan_timer, padapter, rson_timer_hdl, padapter);1127#endif1128}11291130int init_mlme_ext_priv(_adapter *padapter)1131{1132int res = _SUCCESS;1133struct registry_priv *pregistrypriv = &padapter->registrypriv;1134struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1135struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);11361137/* We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */1138/* _rtw_memset((u8 *)pmlmeext, 0, sizeof(struct mlme_ext_priv)); */11391140pmlmeext->padapter = padapter;11411142/* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */11431144init_mlme_ext_priv_value(padapter);1145pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;11461147init_mlme_ext_timer(padapter);11481149#ifdef CONFIG_AP_MODE1150init_mlme_ap_info(padapter);1151#endif11521153pmlmeext->last_scan_time = 0;1154pmlmeext->mlmeext_init = _TRUE;115511561157#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK1158pmlmeext->active_keep_alive_check = _TRUE;1159#else1160pmlmeext->active_keep_alive_check = _FALSE;1161#endif11621163#ifdef DBG_FIXED_CHAN1164pmlmeext->fixed_chan = 0xFF;1165#endif11661167pmlmeext->tsf_update_pause_factor = pregistrypriv->tsf_update_pause_factor;1168pmlmeext->tsf_update_restore_factor = pregistrypriv->tsf_update_restore_factor;11691170#ifdef CONFIG_SUPPORT_STATIC_SMPS1171pmlmeext->ssmps_en = _FALSE;1172pmlmeext->ssmps_tx_tp_th = SSMPS_TX_TP_TH;/*Mbps*/1173pmlmeext->ssmps_rx_tp_th = SSMPS_RX_TP_TH;/*Mbps*/1174#ifdef DBG_STATIC_SMPS1175pmlmeext->ssmps_test = _FALSE;1176#endif1177#endif11781179#ifdef CONFIG_CTRL_TXSS_BY_TP1180pmlmeext->txss_ctrl_en = _TRUE;1181pmlmeext->txss_tp_th = TXSS_TP_TH;1182pmlmeext->txss_tp_chk_cnt = TXSS_TP_CHK_CNT;1183#endif11841185return res;11861187}11881189void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)1190{1191_adapter *padapter = pmlmeext->padapter;11921193if (!padapter)1194return;11951196if (rtw_is_drv_stopped(padapter)) {1197_cancel_timer_ex(&pmlmeext->survey_timer);1198_cancel_timer_ex(&pmlmeext->link_timer);1199}1200}12011202#ifdef CONFIG_PATCH_JOIN_WRONG_CHANNEL1203static u8 cmp_pkt_chnl_diff(_adapter *padapter, u8 *pframe, uint packet_len)1204{1205/* if the channel is same, return 0. else return channel differential */1206uint len;1207u8 channel;1208u8 *p;12091210p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, packet_len - _BEACON_IE_OFFSET_);1211if (p) {1212channel = *(p + 2);1213if (padapter->mlmeextpriv.cur_channel >= channel)1214return padapter->mlmeextpriv.cur_channel - channel;1215else1216return channel - padapter->mlmeextpriv.cur_channel;1217} else1218return 0;1219}1220#endif /* CONFIG_PATCH_JOIN_WRONG_CHANNEL */12211222static void _mgt_dispatcher(_adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)1223{1224u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};1225u8 *pframe = precv_frame->u.hdr.rx_data;12261227if (ptable->func) {1228/* receive the frames that ra(a1) is my address or ra(a1) is bc address. */1229if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_mac_addr(padapter), ETH_ALEN) &&1230!_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))1231#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI1232{1233struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);12341235if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) != _TRUE)1236return;12371238if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _TRUE)1239return;12401241if ( pwdev_priv->pno_mac_addr[0] == 0xFF)1242return;12431244if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_pno_mac_addr(padapter), ETH_ALEN))1245return;1246}1247#else1248return;1249#endif12501251ptable->func(padapter, precv_frame);1252}12531254}12551256void mgt_dispatcher(_adapter *padapter, union recv_frame *precv_frame)1257{1258int index;1259struct mlme_handler *ptable;1260u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};1261u8 *pframe = precv_frame->u.hdr.rx_data;1262struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, get_addr2_ptr(pframe));1263struct recv_priv *precvpriv = &padapter->recvpriv;126412651266#if 01267{1268u8 *pbuf;1269pbuf = GetAddr1Ptr(pframe);1270RTW_INFO("A1-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf + 1), *(pbuf + 2), *(pbuf + 3), *(pbuf + 4), *(pbuf + 5));1271pbuf = get_addr2_ptr(pframe);1272RTW_INFO("A2-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf + 1), *(pbuf + 2), *(pbuf + 3), *(pbuf + 4), *(pbuf + 5));1273pbuf = GetAddr3Ptr(pframe);1274RTW_INFO("A3-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf + 1), *(pbuf + 2), *(pbuf + 3), *(pbuf + 4), *(pbuf + 5));1275}1276#endif12771278if (GetFrameType(pframe) != WIFI_MGT_TYPE) {1279return;1280}12811282/* receive the frames that ra(a1) is my address or ra(a1) is bc address. */1283if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_mac_addr(padapter), ETH_ALEN) &&1284!_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))1285#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI1286{1287struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);12881289if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) != _TRUE)1290return;12911292if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _TRUE)1293return;12941295if ( pwdev_priv->pno_mac_addr[0] == 0xFF)1296return;12971298if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_pno_mac_addr(padapter), ETH_ALEN))1299return;1300}1301#else1302return;1303#endif13041305ptable = mlme_sta_tbl;13061307index = get_frame_sub_type(pframe) >> 4;13081309#ifdef CONFIG_TDLS1310if ((index << 4) == WIFI_ACTION) {1311/* category==public (4), action==TDLS_DISCOVERY_RESPONSE */1312if (*(pframe + 24) == RTW_WLAN_CATEGORY_PUBLIC && *(pframe + 25) == TDLS_DISCOVERY_RESPONSE) {1313RTW_INFO("[TDLS] Recv %s from "MAC_FMT"\n", rtw_tdls_action_txt(TDLS_DISCOVERY_RESPONSE), MAC_ARG(get_addr2_ptr(pframe)));1314On_TDLS_Dis_Rsp(padapter, precv_frame);1315}1316}1317#endif /* CONFIG_TDLS */13181319if (index >= (sizeof(mlme_sta_tbl) / sizeof(struct mlme_handler))) {1320return;1321}1322ptable += index;13231324#if 11325if (psta != NULL) {1326if (GetRetry(pframe)) {1327if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {1328/* drop the duplicate management frame */1329precvpriv->dbg_rx_dup_mgt_frame_drop_count++;1330RTW_INFO("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num);1331return;1332}1333}1334psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;1335}1336#else13371338if (GetRetry(pframe)) {1339/* return; */1340}1341#endif13421343#ifdef CONFIG_AP_MODE1344switch (get_frame_sub_type(pframe)) {1345case WIFI_AUTH:1346if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter))1347ptable->func = &OnAuth;1348else1349ptable->func = &OnAuthClient;1350/* fall through */1351case WIFI_ASSOCREQ:1352case WIFI_REASSOCREQ:1353_mgt_dispatcher(padapter, ptable, precv_frame);1354#ifdef CONFIG_HOSTAPD_MLME1355if (MLME_IS_AP(padapter))1356rtw_hostapd_mlme_rx(padapter, precv_frame);1357#endif1358break;1359case WIFI_PROBEREQ:1360_mgt_dispatcher(padapter, ptable, precv_frame);1361#ifdef CONFIG_HOSTAPD_MLME1362if (MLME_IS_AP(padapter))1363rtw_hostapd_mlme_rx(padapter, precv_frame);1364#endif1365break;1366case WIFI_BEACON:1367_mgt_dispatcher(padapter, ptable, precv_frame);1368break;1369case WIFI_ACTION:1370_mgt_dispatcher(padapter, ptable, precv_frame);1371break;1372default:1373_mgt_dispatcher(padapter, ptable, precv_frame);1374#ifdef CONFIG_HOSTAPD_MLME1375if (MLME_IS_AP(padapter))1376rtw_hostapd_mlme_rx(padapter, precv_frame);1377#endif1378break;1379}1380#else13811382_mgt_dispatcher(padapter, ptable, precv_frame);13831384#endif13851386}13871388#ifdef CONFIG_P2P1389u32 p2p_listen_state_process(_adapter *padapter, unsigned char *da)1390{1391bool response = _TRUE;13921393#ifdef CONFIG_IOCTL_CFG802111394if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) {1395if (rtw_cfg80211_get_is_roch(padapter) == _FALSE1396|| rtw_get_oper_ch(padapter) != padapter->wdinfo.listen_channel1397|| adapter_wdev_data(padapter)->p2p_enabled == _FALSE1398|| padapter->mlmepriv.wps_probe_resp_ie == NULL1399|| padapter->mlmepriv.p2p_probe_resp_ie == NULL1400) {1401#ifdef CONFIG_DEBUG_CFG802111402RTW_INFO(ADPT_FMT" DON'T issue_probersp_p2p: p2p_enabled:%d, wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p\n"1403, ADPT_ARG(padapter)1404, adapter_wdev_data(padapter)->p2p_enabled1405, padapter->mlmepriv.wps_probe_resp_ie1406, padapter->mlmepriv.p2p_probe_resp_ie);1407RTW_INFO(ADPT_FMT" DON'T issue_probersp_p2p: is_ro_ch:%d, op_ch:%d, p2p_listen_channel:%d\n"1408, ADPT_ARG(padapter)1409, rtw_cfg80211_get_is_roch(padapter)1410, rtw_get_oper_ch(padapter)1411, padapter->wdinfo.listen_channel);1412#endif1413response = _FALSE;1414}1415} else1416#endif /* CONFIG_IOCTL_CFG80211 */1417if (padapter->wdinfo.driver_interface == DRIVER_WEXT) {1418/* do nothing if the device name is empty */1419if (!padapter->wdinfo.device_name_len)1420response = _FALSE;1421}14221423if (response == _TRUE)1424issue_probersp_p2p(padapter, da);14251426return _SUCCESS;1427}1428#endif /* CONFIG_P2P */142914301431/****************************************************************************14321433Following are the callback functions for each subtype of the management frames14341435*****************************************************************************/14361437unsigned int OnProbeReq(_adapter *padapter, union recv_frame *precv_frame)1438{1439unsigned int ielen;1440unsigned char *p;1441struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1442struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1443struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1444WLAN_BSSID_EX *cur = &(pmlmeinfo->network);1445u8 *pframe = precv_frame->u.hdr.rx_data;1446uint len = precv_frame->u.hdr.len;1447u8 is_valid_p2p_probereq = _FALSE;14481449#ifdef CONFIG_ATMEL_RC_PATCH1450u8 *target_ie = NULL, *wps_ie = NULL;1451u8 *start;1452uint search_len = 0, wps_ielen = 0, target_ielen = 0;1453struct sta_info *psta;1454struct sta_priv *pstapriv = &padapter->stapriv;1455#endif145614571458#ifdef CONFIG_P2P1459struct wifidirect_info *pwdinfo = &(padapter->wdinfo);1460struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;1461u8 wifi_test_chk_rate = 1;14621463#ifdef CONFIG_IOCTL_CFG802111464if ((pwdinfo->driver_interface == DRIVER_CFG80211)1465&& !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)1466&& (GET_CFG80211_REPORT_MGMT(adapter_wdev_data(padapter), IEEE80211_STYPE_PROBE_REQ) == _TRUE)1467) {1468rtw_cfg80211_rx_probe_request(padapter, precv_frame);1469return _SUCCESS;1470}1471#endif /* CONFIG_IOCTL_CFG80211 */14721473if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&1474!rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&1475!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&1476!rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&1477!rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)1478) {1479/* Commented by Albert 2011/03/17 */1480/* mcs_rate = 0->CCK 1M rate */1481/* mcs_rate = 1->CCK 2M rate */1482/* mcs_rate = 2->CCK 5.5M rate */1483/* mcs_rate = 3->CCK 11M rate */1484/* In the P2P mode, the driver should not support the CCK rate */14851486/* Commented by Kurt 2012/10/16 */1487/* IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */1488if (padapter->registrypriv.wifi_spec == 1) {1489if (pattrib->data_rate <= DESC_RATE11M)1490wifi_test_chk_rate = 0;1491}14921493if (wifi_test_chk_rate == 1) {1494is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len);1495if (is_valid_p2p_probereq == _TRUE) {1496if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {1497/* FIXME */1498if (padapter->wdinfo.driver_interface == DRIVER_WEXT)1499report_survey_event(padapter, precv_frame);15001501p2p_listen_state_process(padapter, get_sa(pframe));15021503return _SUCCESS;1504}15051506if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))1507goto _continue;1508}1509}1510}15111512_continue:1513#endif /* CONFIG_P2P */15141515if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))1516return _SUCCESS;15171518if (check_fwstate(pmlmepriv, _FW_LINKED) == _FALSE &&1519check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE | WIFI_MESH_STATE) == _FALSE)1520return _SUCCESS;152115221523/* RTW_INFO("+OnProbeReq\n"); */152415251526#ifdef CONFIG_ATMEL_RC_PATCH1527wps_ie = rtw_get_wps_ie(1528pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_,1529len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_,1530NULL, &wps_ielen);1531if (wps_ie)1532target_ie = rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_MANUFACTURER, NULL, &target_ielen);1533if ((target_ie && (target_ielen == 4)) && (_TRUE == _rtw_memcmp((void *)target_ie, "Ozmo", 4))) {1534/* psta->flag_atmel_rc = 1; */1535unsigned char *sa_addr = get_sa(pframe);1536printk("%s: Find Ozmo RC -- %02x:%02x:%02x:%02x:%02x:%02x \n\n",1537__func__, *sa_addr, *(sa_addr + 1), *(sa_addr + 2), *(sa_addr + 3), *(sa_addr + 4), *(sa_addr + 5));1538_rtw_memcpy(pstapriv->atmel_rc_pattern, get_sa(pframe), ETH_ALEN);1539}1540#endif154115421543#ifdef CONFIG_AUTO_AP_MODE1544if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&1545pmlmepriv->cur_network.join_res == _TRUE) {1546_irqL irqL;1547struct sta_info *psta;1548u8 *mac_addr, *peer_addr;1549struct sta_priv *pstapriv = &padapter->stapriv;1550u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A};1551/* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */15521553p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, (int *)&ielen,1554len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);15551556if (!p || ielen != 14)1557goto _non_rc_device;15581559if (!_rtw_memcmp(p + 2, RC_OUI, sizeof(RC_OUI)))1560goto _non_rc_device;15611562if (!_rtw_memcmp(p + 6, get_sa(pframe), ETH_ALEN)) {1563RTW_INFO("%s, do rc pairing ("MAC_FMT"), but mac addr mismatch!("MAC_FMT")\n", __FUNCTION__,1564MAC_ARG(get_sa(pframe)), MAC_ARG(p + 6));15651566goto _non_rc_device;1567}15681569RTW_INFO("%s, got the pairing device("MAC_FMT")\n", __FUNCTION__, MAC_ARG(get_sa(pframe)));15701571/* new a station */1572psta = rtw_get_stainfo(pstapriv, get_sa(pframe));1573if (psta == NULL) {1574/* allocate a new one */1575RTW_INFO("going to alloc stainfo for rc="MAC_FMT"\n", MAC_ARG(get_sa(pframe)));1576psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe));1577if (psta == NULL) {1578/* TODO: */1579RTW_INFO(" Exceed the upper limit of supported clients...\n");1580return _SUCCESS;1581}15821583_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);1584if (rtw_is_list_empty(&psta->asoc_list)) {1585psta->expire_to = pstapriv->expire_to;1586rtw_list_insert_tail(&psta->asoc_list, &pstapriv->asoc_list);1587pstapriv->asoc_list_cnt++;1588}1589_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);15901591/* generate pairing ID */1592mac_addr = adapter_mac_addr(padapter);1593peer_addr = psta->cmn.mac_addr;1594psta->pid = (u16)(((mac_addr[4] << 8) + mac_addr[5]) + ((peer_addr[4] << 8) + peer_addr[5]));15951596/* update peer stainfo */1597psta->isrc = _TRUE;15981599/* AID assignment */1600if (psta->cmn.aid > 0)1601RTW_INFO(FUNC_ADPT_FMT" old AID=%d\n", FUNC_ADPT_ARG(padapter), psta->cmn.aid);1602else {1603if (!rtw_aid_alloc(padapter, psta)) {1604RTW_INFO(FUNC_ADPT_FMT" no room for more AIDs\n", FUNC_ADPT_ARG(padapter));1605return _SUCCESS;1606}1607RTW_INFO(FUNC_ADPT_FMT" allocate new AID=%d\n", FUNC_ADPT_ARG(padapter), psta->cmn.aid);1608}16091610psta->qos_option = 1;1611psta->cmn.bw_mode = CHANNEL_WIDTH_20;1612psta->ieee8021x_blocked = _FALSE;1613#ifdef CONFIG_80211N_HT1614if(padapter->registrypriv.ht_enable &&1615is_supported_ht(padapter->registrypriv.wireless_mode)) {1616psta->htpriv.ht_option = _TRUE;1617psta->htpriv.ampdu_enable = _FALSE;1618psta->htpriv.sgi_20m = _FALSE;1619psta->htpriv.sgi_40m = _FALSE;1620psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;1621psta->htpriv.agg_enable_bitmap = 0x0;/* reset */1622psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */1623}1624#endif16251626rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);16271628_rtw_memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));16291630_enter_critical_bh(&psta->lock, &irqL);1631psta->state |= _FW_LINKED;1632_exit_critical_bh(&psta->lock, &irqL);16331634report_add_sta_event(padapter, psta->cmn.mac_addr);16351636}16371638issue_probersp(padapter, get_sa(pframe), _FALSE);16391640return _SUCCESS;16411642}16431644_non_rc_device:16451646return _SUCCESS;16471648#endif /* CONFIG_AUTO_AP_MODE */164916501651#ifdef CONFIG_CONCURRENT_MODE1652if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) &&1653rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | _FW_UNDER_SURVEY)) {1654/* don't process probe req */1655return _SUCCESS;1656}1657#endif16581659p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,1660len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);166116621663/* check (wildcard) SSID */1664if (p != NULL) {1665if (is_valid_p2p_probereq == _TRUE)1666goto _issue_probersp;16671668if ((ielen != 0 && _FALSE == _rtw_memcmp((void *)(p + 2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength))1669|| (ielen == 0 && pmlmeinfo->hidden_ssid_mode))1670goto exit;16711672#ifdef CONFIG_RTW_MESH1673if (MLME_IS_MESH(padapter)) {1674p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_MESH_ID, (int *)&ielen,1675len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);16761677if (!p)1678goto exit;1679if (ielen != 0 && _rtw_memcmp((void *)(p + 2), (void *)cur->mesh_id.Ssid, cur->mesh_id.SsidLength) == _FALSE)1680goto exit;1681}1682#endif16831684_issue_probersp:1685if (((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&1686pmlmepriv->cur_network.join_res == _TRUE)) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {1687/* RTW_INFO("+issue_probersp during ap mode\n"); */1688issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);1689}16901691}16921693exit:1694return _SUCCESS;16951696}16971698unsigned int OnProbeRsp(_adapter *padapter, union recv_frame *precv_frame)1699{1700struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1701u8 *pframe = precv_frame->u.hdr.rx_data;1702#ifdef CONFIG_P2P1703struct wifidirect_info *pwdinfo = &padapter->wdinfo;1704#endif170517061707#ifdef CONFIG_P2P1708if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {1709if (_TRUE == pwdinfo->tx_prov_disc_info.benable) {1710if (_rtw_memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, get_addr2_ptr(pframe), ETH_ALEN)) {1711if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {1712pwdinfo->tx_prov_disc_info.benable = _FALSE;1713issue_p2p_provision_request(padapter,1714pwdinfo->tx_prov_disc_info.ssid.Ssid,1715pwdinfo->tx_prov_disc_info.ssid.SsidLength,1716pwdinfo->tx_prov_disc_info.peerDevAddr);1717} else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {1718pwdinfo->tx_prov_disc_info.benable = _FALSE;1719issue_p2p_provision_request(padapter,1720NULL,17210,1722pwdinfo->tx_prov_disc_info.peerDevAddr);1723}1724}1725}1726return _SUCCESS;1727} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {1728if (_TRUE == pwdinfo->nego_req_info.benable) {1729RTW_INFO("[%s] P2P State is GONEGO ING!\n", __FUNCTION__);1730if (_rtw_memcmp(pwdinfo->nego_req_info.peerDevAddr, get_addr2_ptr(pframe), ETH_ALEN)) {1731pwdinfo->nego_req_info.benable = _FALSE;1732issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr);1733}1734}1735} else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {1736if (_TRUE == pwdinfo->invitereq_info.benable) {1737RTW_INFO("[%s] P2P_STATE_TX_INVITE_REQ!\n", __FUNCTION__);1738if (_rtw_memcmp(pwdinfo->invitereq_info.peer_macaddr, get_addr2_ptr(pframe), ETH_ALEN)) {1739pwdinfo->invitereq_info.benable = _FALSE;1740issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr);1741}1742}1743}1744#endif174517461747if ((mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS))1748|| (MLME_IS_MESH(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE))1749#ifdef CONFIG_RTW_REPEATER_SON1750|| (padapter->rtw_rson_scanstage == RSON_SCAN_PROCESS)1751#endif1752) {1753rtw_mi_report_survey_event(padapter, precv_frame);1754return _SUCCESS;1755}17561757#if 0 /* move to validate_recv_mgnt_frame */1758if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {1759if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {1760psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));1761if (psta != NULL)1762psta->sta_stats.rx_mgnt_pkts++;1763}1764}1765#endif17661767return _SUCCESS;17681769}17701771/* for 11n Logo 4.2.31/4.2.32 */1772static void rtw_check_legacy_ap(_adapter *padapter, u8 *pframe, u32 len)1773{17741775struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1776struct mlme_priv *pmlmepriv = &padapter->mlmepriv;17771778if (!padapter->registrypriv.wifi_spec)1779return;17801781if(!MLME_IS_AP(padapter))1782return;178317841785if (pmlmeext->bstart_bss == _TRUE) {1786int left;1787unsigned char *pos;1788struct rtw_ieee802_11_elems elems;1789#ifdef CONFIG_80211N_HT1790u16 cur_op_mode;1791#endif1792/* checking IEs */1793left = len - sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_;1794pos = pframe + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_;1795if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) {1796RTW_INFO("%s: parse fail for "MAC_FMT"\n", __func__, MAC_ARG(GetAddr3Ptr(pframe)));1797return;1798}1799#ifdef CONFIG_80211N_HT1800cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;1801#endif1802/* for legacy ap */1803if (elems.ht_capabilities == NULL && elems.ht_capabilities_len == 0) {18041805if (0)1806RTW_INFO("%s: "MAC_FMT" is legacy ap\n", __func__, MAC_ARG(GetAddr3Ptr(pframe)));18071808ATOMIC_SET(&pmlmepriv->olbc, _TRUE);1809ATOMIC_SET(&pmlmepriv->olbc_ht, _TRUE);1810}18111812}1813}18141815unsigned int OnBeacon(_adapter *padapter, union recv_frame *precv_frame)1816{1817struct sta_info *psta;1818struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1819struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1820struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1821struct sta_priv *pstapriv = &padapter->stapriv;1822u8 *pframe = precv_frame->u.hdr.rx_data;1823uint len = precv_frame->u.hdr.len;1824WLAN_BSSID_EX *pbss;1825int ret = _SUCCESS;1826#ifdef CONFIG_TDLS1827struct sta_info *ptdls_sta;1828struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;1829#ifdef CONFIG_TDLS_CH_SW1830struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;1831#endif1832#endif /* CONFIG_TDLS */18331834if (validate_beacon_len(pframe, len) == _FALSE)1835return _SUCCESS;18361837if (mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS)1838|| (MLME_IS_MESH(padapter) && check_fwstate(pmlmepriv, WIFI_ASOC_STATE))1839) {1840rtw_mi_report_survey_event(padapter, precv_frame);1841return _SUCCESS;1842}1843#ifdef CONFIG_RTW_REPEATER_SON1844if (padapter->rtw_rson_scanstage == RSON_SCAN_PROCESS)1845rtw_mi_report_survey_event(padapter, precv_frame);1846#endif18471848rtw_check_legacy_ap(padapter, pframe, len);18491850if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {1851if ((pmlmeinfo->state & WIFI_FW_AUTH_NULL)1852&& (rtw_sta_linking_test_wait_done() || pmlmeext->join_abort)1853) {1854if (rtw_sta_linking_test_force_fail() || pmlmeext->join_abort) {1855set_link_timer(pmlmeext, 1);1856return _SUCCESS;1857}18581859/* we should update current network before auth, or some IE is wrong */1860pbss = (WLAN_BSSID_EX *)rtw_malloc(sizeof(WLAN_BSSID_EX));1861if (pbss) {1862if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {1863struct beacon_keys recv_beacon;18641865update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE);18661867/* update bcn keys */1868if (rtw_get_bcn_keys(padapter, pframe, len, &recv_beacon) == _TRUE) {1869RTW_INFO("%s: beacon keys ready\n", __func__);1870_rtw_memcpy(&pmlmepriv->cur_beacon_keys,1871&recv_beacon, sizeof(recv_beacon));1872} else {1873RTW_ERR("%s: get beacon keys failed\n", __func__);1874_rtw_memset(&pmlmepriv->cur_beacon_keys, 0, sizeof(recv_beacon));1875}1876#ifdef CONFIG_BCN_CNT_CONFIRM_HDL1877pmlmepriv->new_beacon_cnts = 0;1878#endif1879}1880rtw_mfree((u8 *)pbss, sizeof(WLAN_BSSID_EX));1881}18821883/* check the vendor of the assoc AP */1884pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe + sizeof(struct rtw_ieee80211_hdr_3addr), len - sizeof(struct rtw_ieee80211_hdr_3addr));18851886/* update TSF Value */1887update_TSF(pmlmeext, pframe, len);1888pmlmeext->bcn_cnt = 0;1889pmlmeext->last_bcn_cnt = 0;18901891#ifdef CONFIG_P2P_PS1892/* Comment by YiWei , in wifi p2p spec the "3.3 P2P Power Management" , "These mechanisms are available in a P2P Group in which only P2P Devices are associated." */1893/* process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN)); */1894#endif /* CONFIG_P2P_PS */18951896#if defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)1897if (padapter->registrypriv.wifi_spec) {1898if (process_p2p_cross_connect_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN)) == _FALSE) {1899if (rtw_mi_buddy_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) {1900RTW_PRINT("no issue auth, P2P cross-connect does not permit\n ");1901return _SUCCESS;1902}1903}1904}1905#endif /* CONFIG_P2P CONFIG_P2P and CONFIG_CONCURRENT_MODE */19061907/* start auth */1908start_clnt_auth(padapter);19091910return _SUCCESS;1911}19121913if (((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {1914psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));1915if (psta != NULL) {1916#ifdef CONFIG_PATCH_JOIN_WRONG_CHANNEL1917/* Merge from 8712 FW code */1918if (cmp_pkt_chnl_diff(padapter, pframe, len) != 0) {1919/* join wrong channel, deauth and reconnect */1920issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING);19211922report_del_sta_event(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_JOIN_WRONG_CHANNEL, _TRUE, _FALSE);1923pmlmeinfo->state &= (~WIFI_FW_ASSOC_SUCCESS);1924return _SUCCESS;1925}1926#endif /* CONFIG_PATCH_JOIN_WRONG_CHANNEL */1927#ifdef CONFIG_RTW_80211R1928rtw_ft_update_bcn(padapter, precv_frame);1929#endif1930ret = rtw_check_bcn_info(padapter, pframe, len);1931if (!ret) {1932RTW_PRINT("ap has changed, disconnect now\n ");1933receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 0, _FALSE);1934return _SUCCESS;1935}1936/* update WMM, ERP in the beacon */1937/* todo: the timer is used instead of the number of the beacon received */1938if ((sta_rx_pkts(psta) & 0xf) == 0) {1939/* RTW_INFO("update_bcn_info\n"); */1940update_beacon_info(padapter, pframe, len, psta);1941}19421943pmlmepriv->cur_network_scanned->network.Rssi = precv_frame->u.hdr.attrib.phy_info.recv_signal_power;1944pmlmeext->bcn_cnt++;1945#ifdef CONFIG_BCN_RECV_TIME1946rtw_rx_bcn_time_update(padapter, len, precv_frame->u.hdr.attrib.data_rate);1947#endif1948#ifdef CONFIG_TDLS1949#ifdef CONFIG_TDLS_CH_SW1950if (rtw_tdls_is_chsw_allowed(padapter) == _TRUE) {1951/* Send TDLS Channel Switch Request when receiving Beacon */1952if ((padapter->tdlsinfo.chsw_info.ch_sw_state & TDLS_CH_SW_INITIATOR_STATE) && (ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE)1953&& (pmlmeext->cur_channel == rtw_get_oper_ch(padapter))) {1954ptdls_sta = rtw_get_stainfo(&padapter->stapriv, padapter->tdlsinfo.chsw_info.addr);1955if (ptdls_sta != NULL) {1956if (ptdls_sta->tdls_sta_state | TDLS_LINKED_STATE)1957_set_timer(&ptdls_sta->stay_on_base_chnl_timer, TDLS_CH_SW_STAY_ON_BASE_CHNL_TIMEOUT);1958}1959}1960}1961#endif1962#endif /* CONFIG_TDLS */19631964#ifdef CONFIG_DFS1965process_csa_ie(padapter1966, pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_1967, len - (WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_));1968#endif19691970#ifdef CONFIG_P2P_PS1971process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));1972#endif /* CONFIG_P2P_PS */19731974if (pmlmeext->tsf_update_required && pmlmeext->en_hw_update_tsf)1975rtw_enable_hw_update_tsf_cmd(padapter);19761977#if 0 /* move to validate_recv_mgnt_frame */1978psta->sta_stats.rx_mgnt_pkts++;1979#endif1980}19811982} else if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {1983u8 rate_set[16];1984u8 rate_num = 0;19851986psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));1987if (psta != NULL) {1988/*1989* update WMM, ERP in the beacon1990* todo: the timer is used instead of the number of the beacon received1991*/1992if ((sta_rx_pkts(psta) & 0xf) == 0)1993update_beacon_info(padapter, pframe, len, psta);19941995if (pmlmeext->tsf_update_required && pmlmeext->en_hw_update_tsf)1996rtw_enable_hw_update_tsf_cmd(padapter);1997} else {1998rtw_ies_get_supported_rate(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_, rate_set, &rate_num);1999if (rate_num == 0) {2000RTW_INFO(FUNC_ADPT_FMT" RX beacon with no supported rate\n", FUNC_ADPT_ARG(padapter));2001goto _END_ONBEACON_;2002}20032004psta = rtw_alloc_stainfo(pstapriv, get_addr2_ptr(pframe));2005if (psta == NULL) {2006RTW_INFO(FUNC_ADPT_FMT" Exceed the upper limit of supported clients\n", FUNC_ADPT_ARG(padapter));2007goto _END_ONBEACON_;2008}20092010psta->expire_to = pstapriv->adhoc_expire_to;20112012_rtw_memcpy(psta->bssrateset, rate_set, rate_num);2013psta->bssratelen = rate_num;20142015/* update TSF Value */2016update_TSF(pmlmeext, pframe, len);20172018/* report sta add event */2019report_add_sta_event(padapter, get_addr2_ptr(pframe));2020}2021}2022}20232024_END_ONBEACON_:20252026return _SUCCESS;20272028}20292030unsigned int OnAuth(_adapter *padapter, union recv_frame *precv_frame)2031{2032#ifdef CONFIG_AP_MODE2033_irqL irqL;2034unsigned int auth_mode, seq, ie_len;2035unsigned char *sa, *p;2036u16 algorithm;2037int status;2038static struct sta_info stat;2039struct sta_info *pstat = NULL;2040struct sta_priv *pstapriv = &padapter->stapriv;2041struct security_priv *psecuritypriv = &padapter->securitypriv;2042struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;2043struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2044u8 *pframe = precv_frame->u.hdr.rx_data;2045uint len = precv_frame->u.hdr.len;2046u8 offset = 0;204720482049#ifdef CONFIG_CONCURRENT_MODE2050if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) &&2051rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | _FW_UNDER_SURVEY)) {2052/* don't process auth request; */2053return _SUCCESS;2054}2055#endif /* CONFIG_CONCURRENT_MODE */20562057if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)2058return _FAIL;20592060if (!MLME_IS_ASOC(padapter))2061return _SUCCESS;20622063#if defined(CONFIG_IOCTL_CFG80211) && defined(CONFIG_RTW_MESH)2064if (MLME_IS_MESH(padapter))2065return rtw_mesh_on_auth(padapter, precv_frame);2066#endif20672068RTW_INFO("+OnAuth\n");20692070sa = get_addr2_ptr(pframe);20712072auth_mode = psecuritypriv->dot11AuthAlgrthm;20732074if (GetPrivacy(pframe)) {2075u8 *iv;2076struct rx_pkt_attrib *prxattrib = &(precv_frame->u.hdr.attrib);20772078prxattrib->hdrlen = WLAN_HDR_A3_LEN;2079prxattrib->encrypt = _WEP40_;20802081iv = pframe + prxattrib->hdrlen;2082prxattrib->key_index = ((iv[3] >> 6) & 0x3);20832084prxattrib->iv_len = 4;2085prxattrib->icv_len = 4;20862087rtw_wep_decrypt(padapter, (u8 *)precv_frame);20882089offset = 4;2090}20912092algorithm = le16_to_cpu(*(u16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));2093seq = le16_to_cpu(*(u16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));20942095RTW_INFO("auth alg=%x, seq=%X\n", algorithm, seq);20962097if (rtw_ap_linking_test_force_auth_fail()) {2098status = rtw_ap_linking_test_force_auth_fail();2099RTW_INFO(FUNC_ADPT_FMT" force auth fail with status:%u\n"2100, FUNC_ADPT_ARG(padapter), status);2101goto auth_fail;2102}21032104if ((auth_mode == 2) && (algorithm != WLAN_AUTH_SAE) &&2105(psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) &&2106(psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))2107auth_mode = 0;21082109if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */2110(algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */2111RTW_INFO("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",2112algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);21132114status = _STATS_NO_SUPP_ALG_;21152116goto auth_fail;2117}21182119#if CONFIG_RTW_MACADDR_ACL2120if (rtw_access_ctrl(padapter, sa) == _FALSE) {2121status = _STATS_UNABLE_HANDLE_STA_;2122goto auth_fail;2123}2124#endif21252126pstat = rtw_get_stainfo(pstapriv, sa);2127if (pstat == NULL) {21282129/* allocate a new one */2130RTW_INFO("going to alloc stainfo for sa="MAC_FMT"\n", MAC_ARG(sa));2131pstat = rtw_alloc_stainfo(pstapriv, sa);2132if (pstat == NULL) {2133RTW_INFO(" Exceed the upper limit of supported clients...\n");2134status = _STATS_UNABLE_HANDLE_STA_;2135goto auth_fail;2136}21372138pstat->state = WIFI_FW_AUTH_NULL;2139pstat->auth_seq = 0;21402141/* pstat->flags = 0; */2142/* pstat->capability = 0; */2143} else {2144#ifdef CONFIG_IEEE80211W2145if ((pstat->bpairwise_key_installed != _TRUE && (pstat->flags & WLAN_STA_MFP))2146|| !(pstat->flags & WLAN_STA_MFP))2147#endif /* CONFIG_IEEE80211W */2148{21492150_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);2151if (rtw_is_list_empty(&pstat->asoc_list) == _FALSE) {2152rtw_list_delete(&pstat->asoc_list);2153pstapriv->asoc_list_cnt--;2154if (pstat->expire_to > 0)2155;/* TODO: STA re_auth within expire_to */2156}2157_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);21582159if (seq == 1)2160; /* TODO: STA re_auth and auth timeout */21612162}2163}21642165#ifdef CONFIG_IEEE80211W2166if ((pstat->bpairwise_key_installed != _TRUE && (pstat->flags & WLAN_STA_MFP))2167|| !(pstat->flags & WLAN_STA_MFP))2168#endif /* CONFIG_IEEE80211W */2169{2170_enter_critical_bh(&pstapriv->auth_list_lock, &irqL);2171if (rtw_is_list_empty(&pstat->auth_list)) {21722173rtw_list_insert_tail(&pstat->auth_list, &pstapriv->auth_list);2174pstapriv->auth_list_cnt++;2175}2176_exit_critical_bh(&pstapriv->auth_list_lock, &irqL);2177}21782179if (pstat->auth_seq == 0)2180pstat->expire_to = pstapriv->auth_to;21812182#ifdef CONFIG_IOCTL_CFG802112183if (GET_CFG80211_REPORT_MGMT(adapter_wdev_data(padapter), IEEE80211_STYPE_AUTH) == _TRUE) {2184if ((algorithm == WLAN_AUTH_SAE) &&2185(auth_mode == dot11AuthAlgrthm_8021X)) {2186pstat->authalg = algorithm;21872188rtw_cfg80211_rx_mframe(padapter, precv_frame, NULL);2189return _SUCCESS;2190}2191}2192#endif /* CONFIG_IOCTL_CFG80211 */21932194if ((pstat->auth_seq + 1) != seq) {2195RTW_INFO("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",2196seq, pstat->auth_seq + 1);2197status = _STATS_OUT_OF_AUTH_SEQ_;2198goto auth_fail;2199}22002201if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) {2202if (seq == 1) {2203#ifdef CONFIG_IEEE80211W2204if ((pstat->bpairwise_key_installed != _TRUE && (pstat->flags & WLAN_STA_MFP))2205|| !(pstat->flags & WLAN_STA_MFP))2206#endif /* CONFIG_IEEE80211W */2207{2208pstat->state &= ~WIFI_FW_AUTH_NULL;2209pstat->state |= WIFI_FW_AUTH_SUCCESS;2210pstat->expire_to = pstapriv->assoc_to;2211}2212pstat->authalg = algorithm;2213} else {2214RTW_INFO("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",2215seq, pstat->auth_seq + 1);2216status = _STATS_OUT_OF_AUTH_SEQ_;2217goto auth_fail;2218}2219} else { /* shared system or auto authentication */2220if (seq == 1) {2221/* prepare for the challenging txt... */22222223/* get_random_bytes((void *)pstat->chg_txt, 128); */ /* TODO: */2224_rtw_memset((void *)pstat->chg_txt, 78, 128);2225#ifdef CONFIG_IEEE80211W2226if ((pstat->bpairwise_key_installed != _TRUE && (pstat->flags & WLAN_STA_MFP))2227|| !(pstat->flags & WLAN_STA_MFP))2228#endif /* CONFIG_IEEE80211W */2229{2230pstat->state &= ~WIFI_FW_AUTH_NULL;2231pstat->state |= WIFI_FW_AUTH_STATE;2232}2233pstat->authalg = algorithm;2234pstat->auth_seq = 2;2235} else if (seq == 3) {2236/* checking for challenging txt... */2237RTW_INFO("checking for challenging txt...\n");22382239p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len,2240len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);22412242if ((p == NULL) || (ie_len <= 0)) {2243RTW_INFO("auth rejected because challenge failure!(1)\n");2244status = _STATS_CHALLENGE_FAIL_;2245goto auth_fail;2246}22472248if (_rtw_memcmp((void *)(p + 2), pstat->chg_txt, 128)) {2249#ifdef CONFIG_IEEE80211W2250if ((pstat->bpairwise_key_installed != _TRUE && (pstat->flags & WLAN_STA_MFP))2251|| !(pstat->flags & WLAN_STA_MFP))2252#endif /* CONFIG_IEEE80211W */2253{2254pstat->state &= (~WIFI_FW_AUTH_STATE);2255pstat->state |= WIFI_FW_AUTH_SUCCESS;2256/* challenging txt is correct... */2257pstat->expire_to = pstapriv->assoc_to;2258}2259} else {2260RTW_INFO("auth rejected because challenge failure!\n");2261status = _STATS_CHALLENGE_FAIL_;2262goto auth_fail;2263}2264} else {2265RTW_INFO("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",2266seq, pstat->auth_seq + 1);2267status = _STATS_OUT_OF_AUTH_SEQ_;2268goto auth_fail;2269}2270}227122722273/* Now, we are going to issue_auth... */2274pstat->auth_seq = seq + 1;22752276#ifdef CONFIG_NATIVEAP_MLME2277issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));2278#endif22792280if ((pstat->state & WIFI_FW_AUTH_SUCCESS) || (pstat->state & WIFI_FW_ASSOC_SUCCESS))2281pstat->auth_seq = 0;228222832284return _SUCCESS;22852286auth_fail:22872288if (pstat)2289rtw_free_stainfo(padapter , pstat);22902291pstat = &stat;2292_rtw_memset((char *)pstat, '\0', sizeof(stat));2293pstat->auth_seq = 2;2294_rtw_memcpy(pstat->cmn.mac_addr, sa, ETH_ALEN);22952296#ifdef CONFIG_NATIVEAP_MLME2297issue_auth(padapter, pstat, (unsigned short)status);2298#endif22992300#endif2301return _FAIL;23022303}23042305unsigned int OnAuthClient(_adapter *padapter, union recv_frame *precv_frame)2306{2307unsigned int seq, len, status, algthm, offset;2308unsigned char *p;2309unsigned int go2asoc = 0;2310struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;2311struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2312u8 *pframe = precv_frame->u.hdr.rx_data;2313uint pkt_len = precv_frame->u.hdr.len;23142315RTW_INFO("%s\n", __FUNCTION__);23162317#ifdef CONFIG_IOCTL_CFG802112318if (GET_CFG80211_REPORT_MGMT(adapter_wdev_data(padapter), IEEE80211_STYPE_AUTH) == _TRUE) {2319if (rtw_sec_chk_auth_type(padapter, NL80211_AUTHTYPE_SAE)) {2320if (rtw_cached_pmkid(padapter, get_my_bssid(&pmlmeinfo->network)) != -1) {2321RTW_INFO("SAE: PMKSA cache entry found\n");2322goto normal;2323}2324rtw_cfg80211_rx_mframe(padapter, precv_frame, NULL);2325return _SUCCESS;2326}2327}23282329normal:2330#endif /* CONFIG_IOCTL_CFG80211 */23312332/* check A1 matches or not */2333if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN))2334return _SUCCESS;23352336if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE) || pmlmeext->join_abort)2337return _SUCCESS;23382339offset = (GetPrivacy(pframe)) ? 4 : 0;23402341algthm = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));2342seq = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));2343status = le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4));23442345if (status != 0) {2346RTW_INFO("clnt auth fail, status: %d\n", status);2347if (status == 13) { /* && pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */2348if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)2349pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;2350else2351pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;2352/* pmlmeinfo->reauth_count = 0; */2353}23542355pmlmeinfo->auth_status = status;2356set_link_timer(pmlmeext, 1);2357goto authclnt_fail;2358}23592360if (seq == 2) {2361if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {2362/* legendary shared system */2363p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,2364pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);23652366if (p == NULL) {2367/* RTW_INFO("marc: no challenge text?\n"); */2368goto authclnt_fail;2369}23702371_rtw_memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);2372pmlmeinfo->auth_seq = 3;2373issue_auth(padapter, NULL, 0);2374set_link_timer(pmlmeext, REAUTH_TO);23752376return _SUCCESS;2377} else {2378/* open, or 802.11r FTAA system */2379go2asoc = 1;2380}2381} else if (seq == 4) {2382if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)2383go2asoc = 1;2384else2385goto authclnt_fail;2386} else {2387/* this is also illegal */2388/* RTW_INFO("marc: clnt auth failed due to illegal seq=%x\n", seq); */2389goto authclnt_fail;2390}23912392if (go2asoc) {2393#ifdef CONFIG_RTW_80211R2394if (rtw_ft_update_auth_rsp_ies(padapter, pframe, pkt_len))2395return _SUCCESS;2396#endif2397RTW_PRINT("auth success, start assoc\n");2398start_clnt_assoc(padapter);2399return _SUCCESS;2400}24012402authclnt_fail:24032404/* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */24052406return _FAIL;24072408}24092410unsigned int OnAssocReq(_adapter *padapter, union recv_frame *precv_frame)2411{2412#ifdef CONFIG_AP_MODE2413_irqL irqL;2414u16 listen_interval;2415struct rtw_ieee802_11_elems elems;2416struct sta_info *pstat;2417unsigned char reassoc, *pos;2418int left;2419unsigned short status = _STATS_SUCCESSFUL_;2420unsigned short frame_type, ie_offset = 0;2421struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;2422struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2423WLAN_BSSID_EX *cur = &(pmlmeinfo->network);2424struct sta_priv *pstapriv = &padapter->stapriv;2425u8 *pframe = precv_frame->u.hdr.rx_data;2426uint pkt_len = precv_frame->u.hdr.len;2427#ifdef CONFIG_P2P2428struct wifidirect_info *pwdinfo = &(padapter->wdinfo);2429u8 p2p_status_code = P2P_STATUS_SUCCESS;2430u8 *p2pie;2431u32 p2pielen = 0;2432#endif /* CONFIG_P2P */24332434#ifdef CONFIG_CONCURRENT_MODE2435if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) &&2436rtw_mi_buddy_check_fwstate(padapter, _FW_UNDER_LINKING | _FW_UNDER_SURVEY)) {2437/* don't process assoc request; */2438return _SUCCESS;2439}2440#endif /* CONFIG_CONCURRENT_MODE */24412442if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)2443return _FAIL;24442445frame_type = get_frame_sub_type(pframe);2446if (frame_type == WIFI_ASSOCREQ) {2447reassoc = 0;2448ie_offset = _ASOCREQ_IE_OFFSET_;2449} else { /* WIFI_REASSOCREQ */2450reassoc = 1;2451ie_offset = _REASOCREQ_IE_OFFSET_;2452}245324542455if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {2456RTW_INFO("handle_assoc(reassoc=%d) - too short payload (len=%lu)"2457"\n", reassoc, (unsigned long)pkt_len);2458return _FAIL;2459}24602461pstat = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));2462if (pstat == (struct sta_info *)NULL) {2463status = _RSON_CLS2_;2464goto asoc_class2_error;2465}24662467RTW_INFO("%s\n", __FUNCTION__);24682469if (pstat->authalg == WLAN_AUTH_SAE) {2470/* WPA3-SAE */2471if (((pstat->state) & WIFI_FW_AUTH_NULL)) {2472/* TODO:2473Queue AssocReq and Proccess2474by external auth trigger. */2475RTW_INFO("%s: wait external auth trigger\n", __func__);2476return _SUCCESS;2477}2478}24792480/* check if this stat has been successfully authenticated/assocated */2481if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {2482if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {2483status = _RSON_CLS2_;2484goto asoc_class2_error;2485} else {2486pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);2487pstat->state |= WIFI_FW_ASSOC_STATE;2488}2489} else {2490pstat->state &= (~WIFI_FW_AUTH_SUCCESS);2491pstat->state |= WIFI_FW_ASSOC_STATE;2492}24932494#if 0/* todo:tkip_countermeasures */2495if (hapd->tkip_countermeasures) {2496resp = WLAN_REASON_MICHAEL_MIC_FAILURE;2497goto fail;2498}2499#endif25002501if (rtw_ap_linking_test_force_asoc_fail()) {2502status = rtw_ap_linking_test_force_asoc_fail();2503RTW_INFO(FUNC_ADPT_FMT" force asoc fail with status:%u\n"2504, FUNC_ADPT_ARG(padapter), status);2505goto OnAssocReqFail;2506}25072508/* now parse all ieee802_11 ie to point to elems */2509left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);2510pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);2511if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) {2512RTW_INFO("STA " MAC_FMT " sent invalid association request\n",2513MAC_ARG(pstat->cmn.mac_addr));2514status = _STATS_FAILURE_;2515goto OnAssocReqFail;2516}25172518rtw_ap_parse_sta_capability(padapter, pstat, pframe + WLAN_HDR_A3_LEN);25192520listen_interval = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN + 2);2521#if 0/* todo: */2522/* check listen_interval */2523if (listen_interval > hapd->conf->max_listen_interval) {2524hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,2525HOSTAPD_LEVEL_DEBUG,2526"Too large Listen Interval (%d)",2527listen_interval);2528resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;2529goto fail;2530}25312532pstat->listen_interval = listen_interval;2533#endif25342535/* now we should check all the fields... */2536/* checking SSID */2537if (elems.ssid == NULL2538|| elems.ssid_len == 02539|| elems.ssid_len != cur->Ssid.SsidLength2540|| _rtw_memcmp(elems.ssid, cur->Ssid.Ssid, cur->Ssid.SsidLength) == _FALSE2541) {2542status = _STATS_FAILURE_;2543goto OnAssocReqFail;2544}25452546/* (Extended) Supported rates */2547status = rtw_ap_parse_sta_supported_rates(padapter, pstat2548, pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset);2549if (status != _STATS_SUCCESSFUL_)2550goto OnAssocReqFail;25512552/* check RSN/WPA/WPS */2553status = rtw_ap_parse_sta_security_ie(padapter, pstat, &elems);2554if (status != _STATS_SUCCESSFUL_)2555goto OnAssocReqFail;25562557/* check if there is WMM IE & support WWM-PS */2558rtw_ap_parse_sta_wmm_ie(padapter, pstat2559, pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset);25602561#ifdef CONFIG_RTS_FULL_BW2562/*check vendor IE*/2563rtw_parse_sta_vendor_ie_8812(padapter, pstat2564, pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset);2565#endif/*CONFIG_RTS_FULL_BW*/25662567rtw_ap_parse_sta_ht_ie(padapter, pstat, &elems);2568rtw_ap_parse_sta_vht_ie(padapter, pstat, &elems);25692570if (((pstat->flags & WLAN_STA_HT) || (pstat->flags & WLAN_STA_VHT)) &&2571((pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) ||2572(pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP))) {25732574RTW_INFO("(V)HT: " MAC_FMT " tried to use TKIP with (V)HT association\n", MAC_ARG(pstat->cmn.mac_addr));25752576pstat->flags &= ~WLAN_STA_HT;2577pstat->flags &= ~WLAN_STA_VHT;2578/*status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;2579* goto OnAssocReqFail;2580*/2581}25822583#ifdef CONFIG_P2P2584pstat->is_p2p_device = _FALSE;2585if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {2586p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , NULL, &p2pielen);2587if (p2pie) {2588pstat->is_p2p_device = _TRUE;2589p2p_status_code = (u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat);2590if (p2p_status_code > 0) {2591pstat->p2p_status_code = p2p_status_code;2592status = _STATS_CAP_FAIL_;2593goto OnAssocReqFail;2594}2595}2596#ifdef CONFIG_WFD2597rtw_process_wfd_ies(padapter, pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset, __func__);2598#endif2599}2600pstat->p2p_status_code = p2p_status_code;2601#endif /* CONFIG_P2P */26022603#ifdef CONFIG_RTW_REPEATER_SON2604if (rtw_rson_ap_check_sta(padapter, pframe, pkt_len, ie_offset))2605goto OnAssocReqFail;2606#endif26072608/* TODO: identify_proprietary_vendor_ie(); */2609/* Realtek proprietary IE */2610/* identify if this is Broadcom sta */2611/* identify if this is ralink sta */2612/* Customer proprietary IE */26132614#ifdef CONFIG_RTW_80211K2615rtw_ap_parse_sta_rm_en_cap(padapter, pstat, &elems);2616#endif26172618/* AID assignment */2619if (pstat->cmn.aid > 0)2620RTW_INFO(FUNC_ADPT_FMT" old AID=%d\n", FUNC_ADPT_ARG(padapter), pstat->cmn.aid);2621else {2622if (!rtw_aid_alloc(padapter, pstat)) {2623RTW_INFO(FUNC_ADPT_FMT" no room for more AIDs\n", FUNC_ADPT_ARG(padapter));2624status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;2625goto OnAssocReqFail;2626}2627RTW_INFO(FUNC_ADPT_FMT" allocate new AID=%d\n", FUNC_ADPT_ARG(padapter), pstat->cmn.aid);2628}26292630pstat->state &= (~WIFI_FW_ASSOC_STATE);2631pstat->state |= WIFI_FW_ASSOC_SUCCESS;2632/* RTW_INFO("==================%s, %d, (%x), bpairwise_key_installed=%d, MAC:"MAC_FMT"\n"2633, __func__, __LINE__, pstat->state, pstat->bpairwise_key_installed, MAC_ARG(pstat->cmn.mac_addr)); */2634#ifdef CONFIG_IEEE80211W2635if ((pstat->bpairwise_key_installed != _TRUE && (pstat->flags & WLAN_STA_MFP))2636|| !(pstat->flags & WLAN_STA_MFP))2637#endif /* CONFIG_IEEE80211W */2638{2639_enter_critical_bh(&pstapriv->auth_list_lock, &irqL);2640if (!rtw_is_list_empty(&pstat->auth_list)) {2641rtw_list_delete(&pstat->auth_list);2642pstapriv->auth_list_cnt--;2643}2644_exit_critical_bh(&pstapriv->auth_list_lock, &irqL);26452646_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);2647if (rtw_is_list_empty(&pstat->asoc_list)) {2648pstat->expire_to = pstapriv->expire_to;2649rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list);2650pstapriv->asoc_list_cnt++;2651}2652_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);2653}26542655/* now the station is qualified to join our BSS... */2656if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {2657#ifdef CONFIG_NATIVEAP_MLME2658#ifdef CONFIG_IEEE80211W2659if ((pstat->bpairwise_key_installed != _TRUE && (pstat->flags & WLAN_STA_MFP))2660|| !(pstat->flags & WLAN_STA_MFP))2661#endif /* CONFIG_IEEE80211W */2662{2663/* .1 bss_cap_update & sta_info_update */2664bss_cap_update_on_sta_join(padapter, pstat);2665sta_info_update(padapter, pstat);2666}2667#ifdef CONFIG_IEEE80211W2668if (pstat->bpairwise_key_installed == _TRUE && (pstat->flags & WLAN_STA_MFP))2669status = _STATS_REFUSED_TEMPORARILY_;2670#endif /* CONFIG_IEEE80211W */2671/* .2 issue assoc rsp before notify station join event. */2672if (frame_type == WIFI_ASSOCREQ)2673issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);2674else2675issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);26762677#ifdef CONFIG_IOCTL_CFG802112678_enter_critical_bh(&pstat->lock, &irqL);2679if (pstat->passoc_req) {2680rtw_mfree(pstat->passoc_req, pstat->assoc_req_len);2681pstat->passoc_req = NULL;2682pstat->assoc_req_len = 0;2683}26842685pstat->passoc_req = rtw_zmalloc(pkt_len);2686if (pstat->passoc_req) {2687_rtw_memcpy(pstat->passoc_req, pframe, pkt_len);2688pstat->assoc_req_len = pkt_len;2689}2690_exit_critical_bh(&pstat->lock, &irqL);2691#endif /* CONFIG_IOCTL_CFG80211 */2692#ifdef CONFIG_IEEE80211W2693if ((pstat->bpairwise_key_installed != _TRUE && (pstat->flags & WLAN_STA_MFP))2694|| !(pstat->flags & WLAN_STA_MFP))2695#endif /* CONFIG_IEEE80211W */2696{2697/* .3-(1) report sta add event */2698report_add_sta_event(padapter, pstat->cmn.mac_addr);2699}2700#ifdef CONFIG_IEEE80211W2701if (pstat->bpairwise_key_installed == _TRUE && (pstat->flags & WLAN_STA_MFP)) {2702RTW_INFO(MAC_FMT"\n", MAC_ARG(pstat->cmn.mac_addr));2703issue_action_SA_Query(padapter, pstat->cmn.mac_addr, 0, 0, IEEE80211W_RIGHT_KEY);2704}2705#endif /* CONFIG_IEEE80211W */2706#endif /* CONFIG_NATIVEAP_MLME */2707}27082709return _SUCCESS;27102711asoc_class2_error:27122713#ifdef CONFIG_NATIVEAP_MLME2714issue_deauth(padapter, (void *)get_addr2_ptr(pframe), status);2715#endif27162717return _FAIL;27182719OnAssocReqFail:272027212722#ifdef CONFIG_NATIVEAP_MLME2723pstat->cmn.aid = 0;2724if (frame_type == WIFI_ASSOCREQ)2725issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);2726else2727issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);2728#endif272927302731#endif /* CONFIG_AP_MODE */27322733return _FAIL;27342735}27362737#if defined(CONFIG_LAYER2_ROAMING) && defined(CONFIG_RTW_80211K)2738void rtw_roam_nb_discover(_adapter *padapter, u8 bfroce)2739{2740struct mlme_priv *pmlmepriv = &padapter->mlmepriv;2741struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;2742struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2743struct sta_priv *pstapriv = &padapter->stapriv;2744struct sta_info *psta;2745u8 nb_req_issue = _FALSE;27462747if (!check_fwstate(pmlmepriv, _FW_LINKED))2748return;27492750if (!rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE))2751return;27522753psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);2754if (!psta)2755return;27562757if (bfroce || (!pmlmepriv->nb_info.nb_rpt_is_same))2758nb_req_issue = _TRUE;27592760if (nb_req_issue && (psta->rm_en_cap[0] & RTW_RRM_NB_RPT_EN))2761rm_add_nb_req(padapter, psta);2762}2763#endif27642765unsigned int OnAssocRsp(_adapter *padapter, union recv_frame *precv_frame)2766{2767uint i;2768int res;2769unsigned short status;2770PNDIS_802_11_VARIABLE_IEs pIE;2771struct mlme_priv *pmlmepriv = &padapter->mlmepriv;2772struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;2773struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2774/* WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); */2775u8 *pframe = precv_frame->u.hdr.rx_data;2776uint pkt_len = precv_frame->u.hdr.len;2777#ifdef CONFIG_WAPI_SUPPORT2778PNDIS_802_11_VARIABLE_IEs pWapiIE = NULL;2779#endif27802781RTW_INFO("%s\n", __FUNCTION__);27822783/* check A1 matches or not */2784if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN))2785return _SUCCESS;27862787if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)) || pmlmeext->join_abort)2788return _SUCCESS;27892790if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)2791return _SUCCESS;27922793_cancel_timer_ex(&pmlmeext->link_timer);27942795/* status */2796status = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 2));2797if (status > 0) {2798RTW_INFO("assoc reject, status code: %d\n", status);2799pmlmeinfo->state = WIFI_FW_NULL_STATE;2800res = -4;2801goto report_assoc_result;2802}28032804/* get capabilities */2805pmlmeinfo->capability = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));28062807/* set slot time */2808pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;28092810/* AID */2811res = pmlmeinfo->aid = (int)(le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 4)) & 0x3fff);28122813/* check aid value */2814if (res < 1 || res > 2007) {2815RTW_INFO("assoc reject, aid: %d\n", res);2816pmlmeinfo->state = WIFI_FW_NULL_STATE;2817res = -4;2818goto report_assoc_result;2819}28202821/* following are moved to join event callback function */2822/* to handle HT, WMM, rate adaptive, update MAC reg */2823/* for not to handle the synchronous IO in the tasklet */2824for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {2825pIE = (PNDIS_802_11_VARIABLE_IEs)(pframe + i);28262827switch (pIE->ElementID) {2828case _VENDOR_SPECIFIC_IE_:2829if (_rtw_memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */2830WMM_param_handler(padapter, pIE);2831#if defined(CONFIG_P2P) && defined(CONFIG_WFD)2832else if (_rtw_memcmp(pIE->data, WFD_OUI, 4)) /* WFD */2833rtw_process_wfd_ie(padapter, (u8 *)pIE, pIE->Length, __func__);2834#endif2835break;28362837#ifdef CONFIG_WAPI_SUPPORT2838case _WAPI_IE_:2839pWapiIE = pIE;2840break;2841#endif28422843case _HT_CAPABILITY_IE_: /* HT caps */2844HT_caps_handler(padapter, pIE);2845#ifdef ROKU_PRIVATE2846HT_caps_handler_infra_ap(padapter, pIE);2847#endif /* ROKU_PRIVATE */2848break;28492850case _HT_EXTRA_INFO_IE_: /* HT info */2851HT_info_handler(padapter, pIE);2852break;28532854#ifdef CONFIG_80211AC_VHT2855case EID_VHTCapability:2856VHT_caps_handler(padapter, pIE);2857#ifdef ROKU_PRIVATE2858VHT_caps_handler_infra_ap(padapter, pIE);2859#endif /* ROKU_PRIVATE */2860break;28612862case EID_VHTOperation:2863VHT_operation_handler(padapter, pIE);2864break;2865#endif28662867case _ERPINFO_IE_:2868ERP_IE_handler(padapter, pIE);2869break;2870#ifdef CONFIG_TDLS2871case _EXT_CAP_IE_:2872if (check_ap_tdls_prohibited(pIE->data, pIE->Length) == _TRUE)2873padapter->tdlsinfo.ap_prohibited = _TRUE;2874if (check_ap_tdls_ch_switching_prohibited(pIE->data, pIE->Length) == _TRUE)2875padapter->tdlsinfo.ch_switch_prohibited = _TRUE;2876break;2877#endif /* CONFIG_TDLS */28782879#ifdef CONFIG_RTW_80211K2880case _EID_RRM_EN_CAP_IE_:2881RM_IE_handler(padapter, pIE);2882break;2883#endif28842885#ifdef ROKU_PRIVATE2886/* Infra mode, used to store AP's info , Parse the supported rates from AssocRsp */2887case _SUPPORTEDRATES_IE_:2888Supported_rate_infra_ap(padapter, pIE);2889break;28902891case _EXT_SUPPORTEDRATES_IE_:2892Extended_Supported_rate_infra_ap(padapter, pIE);2893break;2894#endif /* ROKU_PRIVATE */2895default:2896break;2897}28982899i += (pIE->Length + 2);2900}29012902#ifdef CONFIG_WAPI_SUPPORT2903rtw_wapi_on_assoc_ok(padapter, pIE);2904#endif29052906pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);2907pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;29082909/* Update Basic Rate Table for spec, 2010-12-28 , by thomas */2910UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);29112912report_assoc_result:2913if (res > 0)2914rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);2915else2916rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);29172918report_join_res(padapter, res, status);29192920#if defined(CONFIG_LAYER2_ROAMING) && defined(CONFIG_RTW_80211K)2921rtw_roam_nb_discover(padapter, _TRUE);2922#endif2923return _SUCCESS;2924}29252926unsigned int OnDeAuth(_adapter *padapter, union recv_frame *precv_frame)2927{2928unsigned short reason;2929struct mlme_priv *pmlmepriv = &padapter->mlmepriv;2930struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;2931struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);2932u8 *pframe = precv_frame->u.hdr.rx_data;2933#ifdef CONFIG_P2P2934struct wifidirect_info *pwdinfo = &(padapter->wdinfo);2935#endif /* CONFIG_P2P */29362937/* check A3 */2938if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))2939return _SUCCESS;29402941RTW_INFO(FUNC_ADPT_FMT" - Start to Disconnect\n", FUNC_ADPT_ARG(padapter));29422943#ifdef CONFIG_P2P2944if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {2945_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);2946_set_timer(&pwdinfo->reset_ch_sitesurvey, 10);2947}2948#endif /* CONFIG_P2P */29492950reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));29512952#ifdef CONFIG_AP_MODE2953if (MLME_IS_AP(padapter)) {2954_irqL irqL;2955struct sta_info *psta;2956struct sta_priv *pstapriv = &padapter->stapriv;29572958/* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */2959/* rtw_free_stainfo(padapter, psta); */2960/* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */29612962RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM\n"2963, FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe));29642965psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));2966if (psta) {2967u8 updated = _FALSE;29682969_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);2970if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {2971rtw_list_delete(&psta->asoc_list);2972pstapriv->asoc_list_cnt--;2973updated = ap_free_sta(padapter, psta, _FALSE, reason, _TRUE);29742975}2976_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);29772978associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);2979}298029812982return _SUCCESS;2983} else2984#endif2985if (!MLME_IS_MESH(padapter)) {2986int ignore_received_deauth = 0;29872988/* Commented by Albert 20130604 */2989/* Before sending the auth frame to start the STA/GC mode connection with AP/GO, */2990/* we will send the deauth first. */2991/* However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */2992/* Added the following code to avoid this case. */2993if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||2994(pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {2995if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA)2996ignore_received_deauth = 1;2997else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) {2998/* TODO: 802.11r */2999ignore_received_deauth = 1;3000}3001}30023003RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM, ignore=%d\n"3004, FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe), ignore_received_deauth);30053006if (0 == ignore_received_deauth)3007receive_disconnect(padapter, get_addr2_ptr(pframe), reason, _FALSE);3008}3009pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;3010return _SUCCESS;30113012}30133014unsigned int OnDisassoc(_adapter *padapter, union recv_frame *precv_frame)3015{3016unsigned short reason;3017struct mlme_priv *pmlmepriv = &padapter->mlmepriv;3018struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;3019struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);3020u8 *pframe = precv_frame->u.hdr.rx_data;3021#ifdef CONFIG_P2P3022struct wifidirect_info *pwdinfo = &(padapter->wdinfo);3023#endif /* CONFIG_P2P */30243025/* check A3 */3026if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))3027return _SUCCESS;30283029RTW_INFO(FUNC_ADPT_FMT" - Start to Disconnect\n", FUNC_ADPT_ARG(padapter));30303031#ifdef CONFIG_P2P3032if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {3033_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);3034_set_timer(&pwdinfo->reset_ch_sitesurvey, 10);3035}3036#endif /* CONFIG_P2P */30373038reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));30393040#ifdef CONFIG_AP_MODE3041if (MLME_IS_AP(padapter)) {3042_irqL irqL;3043struct sta_info *psta;3044struct sta_priv *pstapriv = &padapter->stapriv;30453046/* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */3047/* rtw_free_stainfo(padapter, psta); */3048/* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */30493050RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM\n"3051, FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe));30523053psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));3054if (psta) {3055u8 updated = _FALSE;30563057_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);3058if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {3059rtw_list_delete(&psta->asoc_list);3060pstapriv->asoc_list_cnt--;3061updated = ap_free_sta(padapter, psta, _FALSE, reason, _TRUE);30623063}3064_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);30653066associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);3067}30683069return _SUCCESS;3070} else3071#endif3072if (!MLME_IS_MESH(padapter)) {3073RTW_PRINT(FUNC_ADPT_FMT" reason=%u, ta=%pM\n"3074, FUNC_ADPT_ARG(padapter), reason, get_addr2_ptr(pframe));30753076receive_disconnect(padapter, get_addr2_ptr(pframe), reason, _FALSE);3077}3078pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;3079return _SUCCESS;30803081}30823083unsigned int OnAtim(_adapter *padapter, union recv_frame *precv_frame)3084{3085RTW_INFO("%s\n", __FUNCTION__);3086return _SUCCESS;3087}30883089unsigned int on_action_spct_ch_switch(_adapter *padapter, struct sta_info *psta, u8 *ies, uint ies_len)3090{3091unsigned int ret = _FAIL;3092struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv;3093struct mlme_ext_info *pmlmeinfo = &(mlmeext->mlmext_info);30943095if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {3096ret = _SUCCESS;3097goto exit;3098}30993100if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {31013102int ch_switch_mode = -1, ch = -1, ch_switch_cnt = -1;3103int ch_offset = -1;3104u8 bwmode;3105struct ieee80211_info_element *ie;31063107RTW_INFO(FUNC_NDEV_FMT" from "MAC_FMT"\n",3108FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(psta->cmn.mac_addr));31093110for_each_ie(ie, ies, ies_len) {3111if (ie->id == WLAN_EID_CHANNEL_SWITCH) {3112ch_switch_mode = ie->data[0];3113ch = ie->data[1];3114ch_switch_cnt = ie->data[2];3115RTW_INFO("ch_switch_mode:%d, ch:%d, ch_switch_cnt:%d\n",3116ch_switch_mode, ch, ch_switch_cnt);3117} else if (ie->id == WLAN_EID_SECONDARY_CHANNEL_OFFSET) {3118ch_offset = secondary_ch_offset_to_hal_ch_offset(ie->data[0]);3119RTW_INFO("ch_offset:%d\n", ch_offset);3120}3121}31223123if (ch == -1)3124return _SUCCESS;31253126if (ch_offset == -1)3127bwmode = mlmeext->cur_bwmode;3128else3129bwmode = (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) ?3130CHANNEL_WIDTH_20 : CHANNEL_WIDTH_40;31313132ch_offset = (ch_offset == -1) ? mlmeext->cur_ch_offset : ch_offset;31333134/* todo:3135* 1. the decision of channel switching3136* 2. things after channel switching3137*/31383139ret = rtw_set_chbw_cmd(padapter, ch, bwmode, ch_offset, 0);3140}31413142exit:3143return ret;3144}31453146unsigned int on_action_spct(_adapter *padapter, union recv_frame *precv_frame)3147{3148unsigned int ret = _FAIL;3149struct sta_info *psta = NULL;3150struct sta_priv *pstapriv = &padapter->stapriv;3151u8 *pframe = precv_frame->u.hdr.rx_data;3152uint frame_len = precv_frame->u.hdr.len;3153u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));3154u8 category;3155u8 action;31563157psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));31583159if (!psta)3160goto exit;31613162category = frame_body[0];3163if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)3164goto exit;31653166action = frame_body[1];31673168RTW_INFO(FUNC_ADPT_FMT" action:%u\n", FUNC_ADPT_ARG(padapter), action);31693170switch (action) {3171case RTW_WLAN_ACTION_SPCT_MSR_REQ:3172case RTW_WLAN_ACTION_SPCT_MSR_RPRT:3173case RTW_WLAN_ACTION_SPCT_TPC_REQ:3174case RTW_WLAN_ACTION_SPCT_TPC_RPRT:3175break;3176case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:3177#ifdef CONFIG_SPCT_CH_SWITCH3178ret = on_action_spct_ch_switch(padapter, psta3179, frame_body + 2, frame_len - (frame_body - pframe) - 2);3180#elif defined(CONFIG_DFS)3181if (MLME_IS_STA(padapter) && MLME_IS_ASOC(padapter)) {3182process_csa_ie(padapter3183, frame_body + 2, frame_len - (frame_body - pframe) - 2);3184}3185#endif3186break;3187default:3188break;3189}31903191exit:3192return ret;3193}31943195unsigned int OnAction_qos(_adapter *padapter, union recv_frame *precv_frame)3196{3197return _SUCCESS;3198}31993200unsigned int OnAction_dls(_adapter *padapter, union recv_frame *precv_frame)3201{3202return _SUCCESS;3203}32043205#ifdef CONFIG_RTW_WNM3206unsigned int on_action_wnm(_adapter *adapter, union recv_frame *rframe)3207{3208unsigned int ret = _FAIL;3209struct sta_info *sta = NULL;3210struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);3211struct sta_priv *stapriv = &(adapter->stapriv);3212u8 *frame = rframe->u.hdr.rx_data;3213u32 frame_len = rframe->u.hdr.len;3214u8 *frame_body = (u8 *)(frame + sizeof(struct rtw_ieee80211_hdr_3addr));3215u32 frame_body_len = frame_len - sizeof(struct rtw_ieee80211_hdr_3addr);3216u8 category, action;3217int cnt = 0;3218char msg[16];32193220sta = rtw_get_stainfo(stapriv, get_addr2_ptr(frame));3221if (!sta)3222goto exit;32233224category = frame_body[0];3225if (category != RTW_WLAN_CATEGORY_WNM)3226goto exit;32273228action = frame_body[1];32293230switch (action) {3231#ifdef CONFIG_RTW_80211R3232case RTW_WLAN_ACTION_WNM_BTM_REQ:3233if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) {3234RTW_INFO("WNM: RTW_WLAN_ACTION_WNM_BTM_REQ recv.\n");3235rtw_wnm_process_btm_req(adapter, frame_body, frame_body_len);3236}3237ret = _SUCCESS;3238break;3239#endif3240default:3241#ifdef CONFIG_IOCTL_CFG802113242cnt += sprintf((msg + cnt), "ACT_WNM %u", action);3243rtw_cfg80211_rx_action(adapter, rframe, msg);3244#endif3245ret = _SUCCESS;3246break;3247}32483249exit:3250return ret;3251}3252#endif /* CONFIG_RTW_WNM */32533254/**3255* rtw_rx_ampdu_size - Get the target RX AMPDU buffer size for the specific @adapter3256* @adapter: the adapter to get target RX AMPDU buffer size3257*3258* Returns: the target RX AMPDU buffer size3259*/3260u8 rtw_rx_ampdu_size(_adapter *adapter)3261{3262u8 size;3263HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;32643265#ifdef CONFIG_BT_COEXIST3266if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(adapter) == _TRUE) {3267size = rtw_btcoex_GetAMPDUSize(adapter);3268goto exit;3269}3270#endif32713272/* for scan */3273if (!mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_DISABLE)3274&& !mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_COMPLETE)3275&& adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_size != RX_AMPDU_SIZE_INVALID3276) {3277size = adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_size;3278goto exit;3279}32803281/* default value based on max_rx_ampdu_factor */3282if (adapter->driver_rx_ampdu_factor != 0xFF)3283max_rx_ampdu_factor = (HT_CAP_AMPDU_FACTOR)adapter->driver_rx_ampdu_factor;3284else3285rtw_hal_get_def_var(adapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);32863287/* In Maximum A-MPDU Length Exponent subfield of A-MPDU Parameters field of HT Capabilities element,3288the unit of max_rx_ampdu_factor are octets. 8K, 16K, 32K, 64K is right.3289But the buffer size subfield of Block Ack Parameter Set field in ADDBA action frame indicates3290the number of buffers available for this particular TID. Each buffer is equal to max. size of3291MSDU or AMSDU.3292The size variable means how many MSDUs or AMSDUs, it's not Kbytes.3293*/3294if (MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)3295size = 64;3296else if (MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)3297size = 32;3298else if (MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)3299size = 16;3300else if (MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)3301size = 8;3302else3303size = 64;33043305exit:33063307if (size > 127)3308size = 127;33093310return size;3311}33123313/**3314* rtw_rx_ampdu_is_accept - Get the permission if RX AMPDU should be set up for the specific @adapter3315* @adapter: the adapter to get the permission if RX AMPDU should be set up3316*3317* Returns: accept or not3318*/3319bool rtw_rx_ampdu_is_accept(_adapter *adapter)3320{3321bool accept;33223323if (adapter->fix_rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID) {3324accept = adapter->fix_rx_ampdu_accept;3325goto exit;3326}33273328#ifdef CONFIG_BT_COEXIST3329if (rtw_btcoex_IsBTCoexRejectAMPDU(adapter) == _TRUE) {3330accept = _FALSE;3331goto exit;3332}3333#endif33343335/* for scan */3336if (!mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_DISABLE)3337&& !mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_COMPLETE)3338&& adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID3339) {3340accept = adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept;3341goto exit;3342}33433344/* default value for other cases */3345accept = adapter->mlmeextpriv.mlmext_info.bAcceptAddbaReq;33463347exit:3348return accept;3349}33503351/**3352* rtw_rx_ampdu_set_size - Set the target RX AMPDU buffer size for the specific @adapter and specific @reason3353* @adapter: the adapter to set target RX AMPDU buffer size3354* @size: the target RX AMPDU buffer size to set3355* @reason: reason for the target RX AMPDU buffer size setting3356*3357* Returns: whether the target RX AMPDU buffer size is changed3358*/3359bool rtw_rx_ampdu_set_size(_adapter *adapter, u8 size, u8 reason)3360{3361bool is_adj = _FALSE;3362struct mlme_ext_priv *mlmeext;3363struct mlme_ext_info *mlmeinfo;33643365mlmeext = &adapter->mlmeextpriv;3366mlmeinfo = &mlmeext->mlmext_info;33673368if (reason == RX_AMPDU_DRV_FIXED) {3369if (adapter->fix_rx_ampdu_size != size) {3370adapter->fix_rx_ampdu_size = size;3371is_adj = _TRUE;3372RTW_INFO(FUNC_ADPT_FMT" fix_rx_ampdu_size:%u\n", FUNC_ADPT_ARG(adapter), size);3373}3374} else if (reason == RX_AMPDU_DRV_SCAN) {3375struct ss_res *ss = &adapter->mlmeextpriv.sitesurvey_res;33763377if (ss->rx_ampdu_size != size) {3378ss->rx_ampdu_size = size;3379is_adj = _TRUE;3380RTW_INFO(FUNC_ADPT_FMT" ss.rx_ampdu_size:%u\n", FUNC_ADPT_ARG(adapter), size);3381}3382}33833384return is_adj;3385}33863387/**3388* rtw_rx_ampdu_set_accept - Set the permission if RX AMPDU should be set up for the specific @adapter and specific @reason3389* @adapter: the adapter to set if RX AMPDU should be set up3390* @accept: if RX AMPDU should be set up3391* @reason: reason for the permission if RX AMPDU should be set up3392*3393* Returns: whether the permission if RX AMPDU should be set up is changed3394*/3395bool rtw_rx_ampdu_set_accept(_adapter *adapter, u8 accept, u8 reason)3396{3397bool is_adj = _FALSE;3398struct mlme_ext_priv *mlmeext;3399struct mlme_ext_info *mlmeinfo;34003401mlmeext = &adapter->mlmeextpriv;3402mlmeinfo = &mlmeext->mlmext_info;34033404if (reason == RX_AMPDU_DRV_FIXED) {3405if (adapter->fix_rx_ampdu_accept != accept) {3406adapter->fix_rx_ampdu_accept = accept;3407is_adj = _TRUE;3408RTW_INFO(FUNC_ADPT_FMT" fix_rx_ampdu_accept:%u\n", FUNC_ADPT_ARG(adapter), accept);3409}3410} else if (reason == RX_AMPDU_DRV_SCAN) {3411if (adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept != accept) {3412adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept = accept;3413is_adj = _TRUE;3414RTW_INFO(FUNC_ADPT_FMT" ss.rx_ampdu_accept:%u\n", FUNC_ADPT_ARG(adapter), accept);3415}3416}34173418return is_adj;3419}34203421/**3422* rx_ampdu_apply_sta_tid - Apply RX AMPDU setting to the specific @sta and @tid3423* @adapter: the adapter to which @sta belongs3424* @sta: the sta to be checked3425* @tid: the tid to be checked3426* @accept: the target permission if RX AMPDU should be set up3427* @size: the target RX AMPDU buffer size3428*3429* Returns:3430* 0: no canceled3431* 1: canceled by no permission3432* 2: canceled by different buffer size3433* 3: canceled by potential mismatched status3434*3435* Blocking function, may sleep3436*/3437u8 rx_ampdu_apply_sta_tid(_adapter *adapter, struct sta_info *sta, u8 tid, u8 accept, u8 size)3438{3439u8 ret = 0;3440struct recv_reorder_ctrl *reorder_ctl = &sta->recvreorder_ctrl[tid];34413442if (reorder_ctl->enable == _FALSE) {3443if (reorder_ctl->ampdu_size != RX_AMPDU_SIZE_INVALID) {3444send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 1);3445ret = 3;3446}3447goto exit;3448}34493450if (accept == _FALSE) {3451send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 0);3452ret = 1;3453} else if (reorder_ctl->ampdu_size != size) {3454send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 0);3455ret = 2;3456}34573458exit:3459return ret;3460}34613462u8 rx_ampdu_size_sta_limit(_adapter *adapter, struct sta_info *sta)3463{3464u8 sz_limit = 0xFF;34653466#ifdef CONFIG_80211N_HT3467struct registry_priv *regsty = adapter_to_regsty(adapter);3468struct mlme_priv *mlme = &adapter->mlmepriv;3469struct mlme_ext_info *mlmeinfo = &adapter->mlmeextpriv.mlmext_info;3470s8 nss = -1;3471u8 bw = rtw_min(sta->cmn.bw_mode, adapter->mlmeextpriv.cur_bwmode);34723473#ifdef CONFIG_80211AC_VHT3474if (is_supported_vht(sta->wireless_mode)) {3475nss = rtw_min(rtw_vht_mcsmap_to_nss(mlme->vhtpriv.vht_mcs_map)3476, rtw_vht_mcsmap_to_nss(sta->vhtpriv.vht_mcs_map));3477} else3478#endif3479if (is_supported_ht(sta->wireless_mode)) {3480nss = rtw_min(rtw_ht_mcsset_to_nss(mlmeinfo->HT_caps.u.HT_cap_element.MCS_rate)3481, rtw_ht_mcsset_to_nss(sta->htpriv.ht_cap.supp_mcs_set));3482}34833484if (nss >= 1)3485sz_limit = regsty->rx_ampdu_sz_limit_by_nss_bw[nss - 1][bw];3486#endif /* CONFIG_80211N_HT */34873488return sz_limit;3489}34903491/**3492* rx_ampdu_apply_sta - Apply RX AMPDU setting to the specific @sta3493* @adapter: the adapter to which @sta belongs3494* @sta: the sta to be checked3495* @accept: the target permission if RX AMPDU should be set up3496* @size: the target RX AMPDU buffer size3497*3498* Returns: number of the RX AMPDU assciation canceled for applying current target setting3499*3500* Blocking function, may sleep3501*/3502u8 rx_ampdu_apply_sta(_adapter *adapter, struct sta_info *sta, u8 accept, u8 size)3503{3504u8 change_cnt = 0;3505int i;35063507for (i = 0; i < TID_NUM; i++) {3508if (rx_ampdu_apply_sta_tid(adapter, sta, i, accept, size) != 0)3509change_cnt++;3510}35113512return change_cnt;3513}35143515/**3516* rtw_rx_ampdu_apply - Apply the current target RX AMPDU setting for the specific @adapter3517* @adapter: the adapter to be applied3518*3519* Returns: number of the RX AMPDU assciation canceled for applying current target setting3520*/3521u16 rtw_rx_ampdu_apply(_adapter *adapter)3522{3523u16 adj_cnt = 0;3524struct sta_info *sta;3525u8 accept = rtw_rx_ampdu_is_accept(adapter);3526u8 size;35273528if (adapter->fix_rx_ampdu_size != RX_AMPDU_SIZE_INVALID)3529size = adapter->fix_rx_ampdu_size;3530else3531size = rtw_rx_ampdu_size(adapter);35323533if (MLME_IS_STA(adapter)) {3534sta = rtw_get_stainfo(&adapter->stapriv, get_bssid(&adapter->mlmepriv));3535if (sta) {3536u8 sta_size = size;35373538if (adapter->fix_rx_ampdu_size == RX_AMPDU_SIZE_INVALID)3539sta_size = rtw_min(size, rx_ampdu_size_sta_limit(adapter, sta));3540adj_cnt += rx_ampdu_apply_sta(adapter, sta, accept, sta_size);3541}3542/* TODO: TDLS peer */35433544} else if (MLME_IS_AP(adapter) || MLME_IS_MESH(adapter)) {3545_irqL irqL;3546_list *phead, *plist;3547u8 peer_num = 0;3548char peers[NUM_STA];3549struct sta_priv *pstapriv = &adapter->stapriv;3550int i;35513552_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);35533554phead = &pstapriv->asoc_list;3555plist = get_next(phead);35563557while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {3558int stainfo_offset;35593560sta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);3561plist = get_next(plist);35623563stainfo_offset = rtw_stainfo_offset(pstapriv, sta);3564if (stainfo_offset_valid(stainfo_offset))3565peers[peer_num++] = stainfo_offset;3566}35673568_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);35693570for (i = 0; i < peer_num; i++) {3571sta = rtw_get_stainfo_by_offset(pstapriv, peers[i]);3572if (sta) {3573u8 sta_size = size;35743575if (adapter->fix_rx_ampdu_size == RX_AMPDU_SIZE_INVALID)3576sta_size = rtw_min(size, rx_ampdu_size_sta_limit(adapter, sta));3577adj_cnt += rx_ampdu_apply_sta(adapter, sta, accept, sta_size);3578}3579}3580}35813582/* TODO: ADHOC */35833584return adj_cnt;3585}35863587unsigned int OnAction_back(_adapter *padapter, union recv_frame *precv_frame)3588{3589u8 *addr;3590struct sta_info *psta = NULL;3591struct recv_reorder_ctrl *preorder_ctrl;3592unsigned char *frame_body;3593unsigned char category, action;3594unsigned short tid, status, reason_code = 0;3595struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;3596struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);3597u8 *pframe = precv_frame->u.hdr.rx_data;3598struct sta_priv *pstapriv = &padapter->stapriv;3599struct registry_priv *pregpriv = &padapter->registrypriv;36003601#ifdef CONFIG_80211N_HT36023603RTW_INFO("%s\n", __FUNCTION__);36043605/* check RA matches or not */3606if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))3607return _SUCCESS;36083609#if 03610/* check A1 matches or not */3611if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN))3612return _SUCCESS;3613#endif36143615if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)3616if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))3617return _SUCCESS;36183619addr = get_addr2_ptr(pframe);3620psta = rtw_get_stainfo(pstapriv, addr);36213622if (psta == NULL)3623return _SUCCESS;36243625frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));36263627category = frame_body[0];3628if (category == RTW_WLAN_CATEGORY_BACK) { /* representing Block Ack */3629#ifdef CONFIG_TDLS3630if ((psta->tdls_sta_state & TDLS_LINKED_STATE) &&3631(psta->htpriv.ht_option == _TRUE) &&3632(psta->htpriv.ampdu_enable == _TRUE))3633RTW_INFO("Recv [%s] from direc link\n", __FUNCTION__);3634else3635#endif /* CONFIG_TDLS */3636if (!pmlmeinfo->HT_enable)3637return _SUCCESS;36383639action = frame_body[1];3640RTW_INFO("%s, action=%d\n", __FUNCTION__, action);3641switch (action) {3642case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */36433644_rtw_memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));3645/* process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */3646process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);36473648break;36493650case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */36513652/* status = frame_body[3] | (frame_body[4] << 8); */ /* endian issue */3653status = RTW_GET_LE16(&frame_body[3]);3654tid = ((frame_body[5] >> 2) & 0x7);3655if (status == 0) {3656/* successful */3657RTW_INFO("agg_enable for TID=%d\n", tid);3658psta->htpriv.agg_enable_bitmap |= 1 << tid;3659psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);3660/* amsdu in ampdu */3661if (pregpriv->tx_ampdu_amsdu == 0)3662psta->htpriv.tx_amsdu_enable = _FALSE;3663else if (pregpriv->tx_ampdu_amsdu == 1)3664psta->htpriv.tx_amsdu_enable = _TRUE;3665else {3666if (frame_body[5] & 1)3667psta->htpriv.tx_amsdu_enable = _TRUE;3668}3669} else3670psta->htpriv.agg_enable_bitmap &= ~BIT(tid);36713672if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {3673RTW_INFO("%s alive check - rx ADDBA response\n", __func__);3674psta->htpriv.agg_enable_bitmap &= ~BIT(tid);3675psta->expire_to = pstapriv->expire_to;3676psta->state ^= WIFI_STA_ALIVE_CHK_STATE;3677}36783679/* RTW_INFO("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap); */3680break;36813682case RTW_WLAN_ACTION_DELBA: /* DELBA */3683if ((frame_body[3] & BIT(3)) == 0) {3684psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));3685psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));36863687/* reason_code = frame_body[4] | (frame_body[5] << 8); */3688reason_code = RTW_GET_LE16(&frame_body[4]);3689} else if ((frame_body[3] & BIT(3)) == BIT(3)) {3690tid = (frame_body[3] >> 4) & 0x0F;36913692preorder_ctrl = &psta->recvreorder_ctrl[tid];3693preorder_ctrl->enable = _FALSE;3694preorder_ctrl->ampdu_size = RX_AMPDU_SIZE_INVALID;3695}36963697RTW_INFO("%s(): DELBA: %x(%x)\n", __FUNCTION__, pmlmeinfo->agg_enable_bitmap, reason_code);3698/* todo: how to notify the host while receiving DELETE BA */3699break;37003701default:3702break;3703}3704}3705#endif /* CONFIG_80211N_HT */3706return _SUCCESS;3707}37083709#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE3710u32 rtw_build_vendor_ie(_adapter *padapter , unsigned char **pframe , u8 mgmt_frame_tyte)3711{3712int vendor_ie_num = 0;3713struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);3714u32 len = 0;37153716for (vendor_ie_num = 0 ; vendor_ie_num < WLAN_MAX_VENDOR_IE_NUM ; vendor_ie_num++) {3717if (pmlmepriv->vendor_ielen[vendor_ie_num] > 0 && pmlmepriv->vendor_ie_mask[vendor_ie_num] & mgmt_frame_tyte) {3718_rtw_memcpy(*pframe , pmlmepriv->vendor_ie[vendor_ie_num] , pmlmepriv->vendor_ielen[vendor_ie_num]);3719*pframe += pmlmepriv->vendor_ielen[vendor_ie_num];3720len += pmlmepriv->vendor_ielen[vendor_ie_num];3721}3722}37233724return len;3725}3726#endif37273728#ifdef CONFIG_P2P3729int get_reg_classes_full_count(struct p2p_channels *channel_list)3730{3731int cnt = 0;3732int i;37333734for (i = 0; i < channel_list->reg_classes; i++)3735cnt += channel_list->reg_class[i].channels;37363737return cnt;3738}37393740void issue_p2p_GO_request(_adapter *padapter, u8 *raddr)3741{3742struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list);3743unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;3744u8 action = P2P_PUB_ACTION_ACTION;3745u32 p2poui = cpu_to_be32(P2POUI);3746u8 oui_subtype = P2P_GO_NEGO_REQ;3747u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };3748u8 wpsielen = 0, p2pielen = 0;3749u16 len_channellist_attr = 0;3750#ifdef CONFIG_WFD3751u32 wfdielen = 0;3752#endif37533754struct xmit_frame *pmgntframe;3755struct pkt_attrib *pattrib;3756unsigned char *pframe;3757struct rtw_ieee80211_hdr *pwlanhdr;3758unsigned short *fctrl;3759struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);3760struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);3761struct wifidirect_info *pwdinfo = &(padapter->wdinfo);376237633764pmgntframe = alloc_mgtxmitframe(pxmitpriv);3765if (pmgntframe == NULL)3766return;37673768RTW_INFO("[%s] In\n", __FUNCTION__);3769/* update attribute */3770pattrib = &pmgntframe->attrib;3771update_mgntframe_attrib(padapter, pattrib);37723773_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);37743775pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;3776pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;37773778fctrl = &(pwlanhdr->frame_ctl);3779*(fctrl) = 0;37803781_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);3782_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);3783_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);37843785SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);3786pmlmeext->mgnt_seq++;3787set_frame_sub_type(pframe, WIFI_ACTION);37883789pframe += sizeof(struct rtw_ieee80211_hdr_3addr);3790pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);37913792pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));3793pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));3794pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));3795pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));3796pwdinfo->negotiation_dialog_token = 1; /* Initialize the dialog value */3797pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &(pattrib->pktlen));3798379938003801/* WPS Section */3802wpsielen = 0;3803/* WPS OUI */3804*(u32 *)(wpsie) = cpu_to_be32(WPSOUI);3805wpsielen += 4;38063807/* WPS version */3808/* Type: */3809*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);3810wpsielen += 2;38113812/* Length: */3813*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);3814wpsielen += 2;38153816/* Value: */3817wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */38183819/* Device Password ID */3820/* Type: */3821*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);3822wpsielen += 2;38233824/* Length: */3825*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);3826wpsielen += 2;38273828/* Value: */38293830if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)3831*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);3832else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)3833*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);3834else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)3835*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);38363837wpsielen += 2;38383839pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);384038413842/* P2P IE Section. */38433844/* P2P OUI */3845p2pielen = 0;3846p2pie[p2pielen++] = 0x50;3847p2pie[p2pielen++] = 0x6F;3848p2pie[p2pielen++] = 0x9A;3849p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */38503851/* Commented by Albert 20110306 */3852/* According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */3853/* 1. P2P Capability */3854/* 2. Group Owner Intent */3855/* 3. Configuration Timeout */3856/* 4. Listen Channel */3857/* 5. Extended Listen Timing */3858/* 6. Intended P2P Interface Address */3859/* 7. Channel List */3860/* 8. P2P Device Info */3861/* 9. Operating Channel */386238633864/* P2P Capability */3865/* Type: */3866p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;38673868/* Length: */3869*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);3870p2pielen += 2;38713872/* Value: */3873/* Device Capability Bitmap, 1 byte */3874p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;38753876/* Group Capability Bitmap, 1 byte */3877if (pwdinfo->persistent_supported)3878p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;3879else3880p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;388138823883/* Group Owner Intent */3884/* Type: */3885p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;38863887/* Length: */3888*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);3889p2pielen += 2;38903891/* Value: */3892/* Todo the tie breaker bit. */3893p2pie[p2pielen++] = ((pwdinfo->intent << 1) & 0xFE);38943895/* Configuration Timeout */3896/* Type: */3897p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;38983899/* Length: */3900*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);3901p2pielen += 2;39023903/* Value: */3904p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */3905p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */390639073908/* Listen Channel */3909/* Type: */3910p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;39113912/* Length: */3913*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);3914p2pielen += 2;39153916/* Value: */3917/* Country String */3918p2pie[p2pielen++] = 'X';3919p2pie[p2pielen++] = 'X';39203921/* The third byte should be set to 0x04. */3922/* Described in the "Operating Channel Attribute" section. */3923p2pie[p2pielen++] = 0x04;39243925/* Operating Class */3926p2pie[p2pielen++] = 0x51; /* Copy from SD7 */39273928/* Channel Number */3929p2pie[p2pielen++] = pwdinfo->listen_channel; /* listening channel number */393039313932/* Extended Listen Timing ATTR */3933/* Type: */3934p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;39353936/* Length: */3937*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);3938p2pielen += 2;39393940/* Value: */3941/* Availability Period */3942*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);3943p2pielen += 2;39443945/* Availability Interval */3946*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);3947p2pielen += 2;394839493950/* Intended P2P Interface Address */3951/* Type: */3952p2pie[p2pielen++] = P2P_ATTR_INTENDED_IF_ADDR;39533954/* Length: */3955*(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);3956p2pielen += 2;39573958/* Value: */3959_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);3960p2pielen += ETH_ALEN;396139623963/* Channel List */3964/* Type: */3965p2pie[p2pielen++] = P2P_ATTR_CH_LIST;39663967/* Length: */3968/* Country String(3) */3969/* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */3970/* + number of channels in all classes */3971len_channellist_attr = 33972+ (1 + 1) * (u16)(ch_list->reg_classes)3973+ get_reg_classes_full_count(ch_list);39743975#ifdef CONFIG_CONCURRENT_MODE3976if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)3977*(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1);3978else3979*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);3980#else39813982*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);39833984#endif3985p2pielen += 2;39863987/* Value: */3988/* Country String */3989p2pie[p2pielen++] = 'X';3990p2pie[p2pielen++] = 'X';39913992/* The third byte should be set to 0x04. */3993/* Described in the "Operating Channel Attribute" section. */3994p2pie[p2pielen++] = 0x04;39953996/* Channel Entry List */39973998#ifdef CONFIG_CONCURRENT_MODE3999if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {4000u8 union_ch = rtw_mi_get_union_chan(padapter);40014002/* Operating Class */4003if (union_ch > 14) {4004if (union_ch >= 149)4005p2pie[p2pielen++] = 0x7c;4006else4007p2pie[p2pielen++] = 0x73;4008} else4009p2pie[p2pielen++] = 0x51;401040114012/* Number of Channels */4013/* Just support 1 channel and this channel is AP's channel */4014p2pie[p2pielen++] = 1;40154016/* Channel List */4017p2pie[p2pielen++] = union_ch;4018} else4019#endif /* CONFIG_CONCURRENT_MODE */4020{4021int i, j;4022for (j = 0; j < ch_list->reg_classes; j++) {4023/* Operating Class */4024p2pie[p2pielen++] = ch_list->reg_class[j].reg_class;40254026/* Number of Channels */4027p2pie[p2pielen++] = ch_list->reg_class[j].channels;40284029/* Channel List */4030for (i = 0; i < ch_list->reg_class[j].channels; i++)4031p2pie[p2pielen++] = ch_list->reg_class[j].channel[i];4032}4033}40344035/* Device Info */4036/* Type: */4037p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;40384039/* Length: */4040/* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */4041/* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */4042*(u16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);4043p2pielen += 2;40444045/* Value: */4046/* P2P Device Address */4047_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);4048p2pielen += ETH_ALEN;40494050/* Config Method */4051/* This field should be big endian. Noted by P2P specification. */40524053*(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);40544055p2pielen += 2;40564057/* Primary Device Type */4058/* Category ID */4059*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);4060p2pielen += 2;40614062/* OUI */4063*(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);4064p2pielen += 4;40654066/* Sub Category ID */4067*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);4068p2pielen += 2;40694070/* Number of Secondary Device Types */4071p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */40724073/* Device Name */4074/* Type: */4075*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);4076p2pielen += 2;40774078/* Length: */4079*(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);4080p2pielen += 2;40814082/* Value: */4083_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);4084p2pielen += pwdinfo->device_name_len;408540864087/* Operating Channel */4088/* Type: */4089p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;40904091/* Length: */4092*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);4093p2pielen += 2;40944095/* Value: */4096/* Country String */4097p2pie[p2pielen++] = 'X';4098p2pie[p2pielen++] = 'X';40994100/* The third byte should be set to 0x04. */4101/* Described in the "Operating Channel Attribute" section. */4102p2pie[p2pielen++] = 0x04;41034104/* Operating Class */4105if (pwdinfo->operating_channel <= 14) {4106/* Operating Class */4107p2pie[p2pielen++] = 0x51;4108} else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48)) {4109/* Operating Class */4110p2pie[p2pielen++] = 0x73;4111} else {4112/* Operating Class */4113p2pie[p2pielen++] = 0x7c;4114}41154116/* Channel Number */4117p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */41184119pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);41204121#ifdef CONFIG_WFD4122wfdielen = build_nego_req_wfd_ie(pwdinfo, pframe);4123pframe += wfdielen;4124pattrib->pktlen += wfdielen;4125#endif41264127pattrib->last_txcmdsz = pattrib->pktlen;41284129dump_mgntframe(padapter, pmgntframe);41304131return;41324133}413441354136void issue_p2p_GO_response(_adapter *padapter, u8 *raddr, u8 *frame_body, uint len, u8 result)4137{4138struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list);4139unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;4140u8 action = P2P_PUB_ACTION_ACTION;4141u32 p2poui = cpu_to_be32(P2POUI);4142u8 oui_subtype = P2P_GO_NEGO_RESP;4143u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };4144u8 p2pielen = 0;4145uint wpsielen = 0;4146u16 wps_devicepassword_id = 0x0000;4147uint wps_devicepassword_id_len = 0;4148u16 len_channellist_attr = 0;41494150struct xmit_frame *pmgntframe;4151struct pkt_attrib *pattrib;4152unsigned char *pframe;4153struct rtw_ieee80211_hdr *pwlanhdr;4154unsigned short *fctrl;4155struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);4156struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);4157struct wifidirect_info *pwdinfo = &(padapter->wdinfo);41584159#ifdef CONFIG_WFD4160u32 wfdielen = 0;4161#endif41624163pmgntframe = alloc_mgtxmitframe(pxmitpriv);4164if (pmgntframe == NULL)4165return;41664167RTW_INFO("[%s] In, result = %d\n", __FUNCTION__, result);4168/* update attribute */4169pattrib = &pmgntframe->attrib;4170update_mgntframe_attrib(padapter, pattrib);41714172_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);41734174pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;4175pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;41764177fctrl = &(pwlanhdr->frame_ctl);4178*(fctrl) = 0;41794180_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);4181_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);4182_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);41834184SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);4185pmlmeext->mgnt_seq++;4186set_frame_sub_type(pframe, WIFI_ACTION);41874188pframe += sizeof(struct rtw_ieee80211_hdr_3addr);4189pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);41904191pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));4192pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));4193pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));4194pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));4195pwdinfo->negotiation_dialog_token = frame_body[7]; /* The Dialog Token of provisioning discovery request frame. */4196pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));41974198/* Commented by Albert 20110328 */4199/* Try to get the device password ID from the WPS IE of group negotiation request frame */4200/* WiFi Direct test plan 5.1.15 */4201rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);4202rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *) &wps_devicepassword_id, &wps_devicepassword_id_len);4203wps_devicepassword_id = be16_to_cpu(wps_devicepassword_id);42044205_rtw_memset(wpsie, 0x00, 255);4206wpsielen = 0;42074208/* WPS Section */4209wpsielen = 0;4210/* WPS OUI */4211*(u32 *)(wpsie) = cpu_to_be32(WPSOUI);4212wpsielen += 4;42134214/* WPS version */4215/* Type: */4216*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);4217wpsielen += 2;42184219/* Length: */4220*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);4221wpsielen += 2;42224223/* Value: */4224wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */42254226/* Device Password ID */4227/* Type: */4228*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);4229wpsielen += 2;42304231/* Length: */4232*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);4233wpsielen += 2;42344235/* Value: */4236if (wps_devicepassword_id == WPS_DPID_USER_SPEC)4237*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);4238else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)4239*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);4240else4241*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);4242wpsielen += 2;42434244/* Commented by Kurt 20120113 */4245/* If some device wants to do p2p handshake without sending prov_disc_req */4246/* We have to get peer_req_cm from here. */4247if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {4248if (wps_devicepassword_id == WPS_DPID_USER_SPEC)4249_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);4250else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)4251_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);4252else4253_rtw_memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);4254}42554256pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);425742584259/* P2P IE Section. */42604261/* P2P OUI */4262p2pielen = 0;4263p2pie[p2pielen++] = 0x50;4264p2pie[p2pielen++] = 0x6F;4265p2pie[p2pielen++] = 0x9A;4266p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */42674268/* Commented by Albert 20100908 */4269/* According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */4270/* 1. Status */4271/* 2. P2P Capability */4272/* 3. Group Owner Intent */4273/* 4. Configuration Timeout */4274/* 5. Operating Channel */4275/* 6. Intended P2P Interface Address */4276/* 7. Channel List */4277/* 8. Device Info */4278/* 9. Group ID ( Only GO ) */427942804281/* ToDo: */42824283/* P2P Status */4284/* Type: */4285p2pie[p2pielen++] = P2P_ATTR_STATUS;42864287/* Length: */4288*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);4289p2pielen += 2;42904291/* Value: */4292p2pie[p2pielen++] = result;42934294/* P2P Capability */4295/* Type: */4296p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;42974298/* Length: */4299*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);4300p2pielen += 2;43014302/* Value: */4303/* Device Capability Bitmap, 1 byte */43044305if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {4306/* Commented by Albert 2011/03/08 */4307/* According to the P2P specification */4308/* if the sending device will be client, the P2P Capability should be reserved of group negotation response frame */4309p2pie[p2pielen++] = 0;4310} else {4311/* Be group owner or meet the error case */4312p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;4313}43144315/* Group Capability Bitmap, 1 byte */4316if (pwdinfo->persistent_supported)4317p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;4318else4319p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;43204321/* Group Owner Intent */4322/* Type: */4323p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;43244325/* Length: */4326*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);4327p2pielen += 2;43284329/* Value: */4330if (pwdinfo->peer_intent & 0x01) {4331/* Peer's tie breaker bit is 1, our tie breaker bit should be 0 */4332p2pie[p2pielen++] = (pwdinfo->intent << 1);4333} else {4334/* Peer's tie breaker bit is 0, our tie breaker bit should be 1 */4335p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));4336}433743384339/* Configuration Timeout */4340/* Type: */4341p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;43424343/* Length: */4344*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);4345p2pielen += 2;43464347/* Value: */4348p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */4349p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */43504351/* Operating Channel */4352/* Type: */4353p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;43544355/* Length: */4356*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);4357p2pielen += 2;43584359/* Value: */4360/* Country String */4361p2pie[p2pielen++] = 'X';4362p2pie[p2pielen++] = 'X';43634364/* The third byte should be set to 0x04. */4365/* Described in the "Operating Channel Attribute" section. */4366p2pie[p2pielen++] = 0x04;43674368/* Operating Class */4369if (pwdinfo->operating_channel <= 14) {4370/* Operating Class */4371p2pie[p2pielen++] = 0x51;4372} else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48)) {4373/* Operating Class */4374p2pie[p2pielen++] = 0x73;4375} else {4376/* Operating Class */4377p2pie[p2pielen++] = 0x7c;4378}43794380/* Channel Number */4381p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */43824383/* Intended P2P Interface Address */4384/* Type: */4385p2pie[p2pielen++] = P2P_ATTR_INTENDED_IF_ADDR;43864387/* Length: */4388*(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);4389p2pielen += 2;43904391/* Value: */4392_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);4393p2pielen += ETH_ALEN;43944395/* Channel List */4396/* Type: */4397p2pie[p2pielen++] = P2P_ATTR_CH_LIST;43984399/* Country String(3) */4400/* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */4401/* + number of channels in all classes */4402len_channellist_attr = 34403+ (1 + 1) * (u16)ch_list->reg_classes4404+ get_reg_classes_full_count(ch_list);44054406#ifdef CONFIG_CONCURRENT_MODE4407if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)4408*(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1);4409else4410*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);4411#else4412*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);44134414#endif4415p2pielen += 2;44164417/* Value: */4418/* Country String */4419p2pie[p2pielen++] = 'X';4420p2pie[p2pielen++] = 'X';44214422/* The third byte should be set to 0x04. */4423/* Described in the "Operating Channel Attribute" section. */4424p2pie[p2pielen++] = 0x04;44254426/* Channel Entry List */44274428#ifdef CONFIG_CONCURRENT_MODE4429if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {44304431u8 union_chan = rtw_mi_get_union_chan(padapter);44324433/*Operating Class*/4434if (union_chan > 14) {4435if (union_chan >= 149)4436p2pie[p2pielen++] = 0x7c;4437else4438p2pie[p2pielen++] = 0x73;44394440} else4441p2pie[p2pielen++] = 0x51;44424443/* Number of Channels4444Just support 1 channel and this channel is AP's channel*/4445p2pie[p2pielen++] = 1;44464447/*Channel List*/4448p2pie[p2pielen++] = union_chan;4449} else4450#endif /* CONFIG_CONCURRENT_MODE */4451{4452int i, j;4453for (j = 0; j < ch_list->reg_classes; j++) {4454/* Operating Class */4455p2pie[p2pielen++] = ch_list->reg_class[j].reg_class;44564457/* Number of Channels */4458p2pie[p2pielen++] = ch_list->reg_class[j].channels;44594460/* Channel List */4461for (i = 0; i < ch_list->reg_class[j].channels; i++)4462p2pie[p2pielen++] = ch_list->reg_class[j].channel[i];4463}4464}44654466/* Device Info */4467/* Type: */4468p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;44694470/* Length: */4471/* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */4472/* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */4473*(u16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);4474p2pielen += 2;44754476/* Value: */4477/* P2P Device Address */4478_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);4479p2pielen += ETH_ALEN;44804481/* Config Method */4482/* This field should be big endian. Noted by P2P specification. */44834484*(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);44854486p2pielen += 2;44874488/* Primary Device Type */4489/* Category ID */4490*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);4491p2pielen += 2;44924493/* OUI */4494*(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);4495p2pielen += 4;44964497/* Sub Category ID */4498*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);4499p2pielen += 2;45004501/* Number of Secondary Device Types */4502p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */45034504/* Device Name */4505/* Type: */4506*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);4507p2pielen += 2;45084509/* Length: */4510*(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);4511p2pielen += 2;45124513/* Value: */4514_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);4515p2pielen += pwdinfo->device_name_len;45164517if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {4518/* Group ID Attribute */4519/* Type: */4520p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;45214522/* Length: */4523*(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);4524p2pielen += 2;45254526/* Value: */4527/* p2P Device Address */4528_rtw_memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);4529p2pielen += ETH_ALEN;45304531/* SSID */4532_rtw_memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);4533p2pielen += pwdinfo->nego_ssidlen;45344535}45364537pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);45384539#ifdef CONFIG_WFD4540wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe);4541pframe += wfdielen;4542pattrib->pktlen += wfdielen;4543#endif45444545pattrib->last_txcmdsz = pattrib->pktlen;45464547dump_mgntframe(padapter, pmgntframe);45484549return;45504551}45524553void issue_p2p_GO_confirm(_adapter *padapter, u8 *raddr, u8 result)4554{45554556unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;4557u8 action = P2P_PUB_ACTION_ACTION;4558u32 p2poui = cpu_to_be32(P2POUI);4559u8 oui_subtype = P2P_GO_NEGO_CONF;4560u8 p2pie[255] = { 0x00 };4561u8 p2pielen = 0;45624563struct xmit_frame *pmgntframe;4564struct pkt_attrib *pattrib;4565unsigned char *pframe;4566struct rtw_ieee80211_hdr *pwlanhdr;4567unsigned short *fctrl;4568struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);4569struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);4570struct wifidirect_info *pwdinfo = &(padapter->wdinfo);4571#ifdef CONFIG_WFD4572u32 wfdielen = 0;4573#endif45744575pmgntframe = alloc_mgtxmitframe(pxmitpriv);4576if (pmgntframe == NULL)4577return;45784579RTW_INFO("[%s] In\n", __FUNCTION__);4580/* update attribute */4581pattrib = &pmgntframe->attrib;4582update_mgntframe_attrib(padapter, pattrib);45834584_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);45854586pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;4587pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;45884589fctrl = &(pwlanhdr->frame_ctl);4590*(fctrl) = 0;45914592_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);4593_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);4594_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);45954596SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);4597pmlmeext->mgnt_seq++;4598set_frame_sub_type(pframe, WIFI_ACTION);45994600pframe += sizeof(struct rtw_ieee80211_hdr_3addr);4601pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);46024603pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));4604pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));4605pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));4606pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));4607pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));4608460946104611/* P2P IE Section. */46124613/* P2P OUI */4614p2pielen = 0;4615p2pie[p2pielen++] = 0x50;4616p2pie[p2pielen++] = 0x6F;4617p2pie[p2pielen++] = 0x9A;4618p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */46194620/* Commented by Albert 20110306 */4621/* According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */4622/* 1. Status */4623/* 2. P2P Capability */4624/* 3. Operating Channel */4625/* 4. Channel List */4626/* 5. Group ID ( if this WiFi is GO ) */46274628/* P2P Status */4629/* Type: */4630p2pie[p2pielen++] = P2P_ATTR_STATUS;46314632/* Length: */4633*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);4634p2pielen += 2;46354636/* Value: */4637p2pie[p2pielen++] = result;46384639/* P2P Capability */4640/* Type: */4641p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;46424643/* Length: */4644*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);4645p2pielen += 2;46464647/* Value: */4648/* Device Capability Bitmap, 1 byte */4649p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;46504651/* Group Capability Bitmap, 1 byte */4652if (pwdinfo->persistent_supported)4653p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;4654else4655p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;465646574658/* Operating Channel */4659/* Type: */4660p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;46614662/* Length: */4663*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);4664p2pielen += 2;46654666/* Value: */4667/* Country String */4668p2pie[p2pielen++] = 'X';4669p2pie[p2pielen++] = 'X';46704671/* The third byte should be set to 0x04. */4672/* Described in the "Operating Channel Attribute" section. */4673p2pie[p2pielen++] = 0x04;467446754676if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {4677if (pwdinfo->peer_operating_ch <= 14) {4678/* Operating Class */4679p2pie[p2pielen++] = 0x51;4680} else if ((pwdinfo->peer_operating_ch >= 36) && (pwdinfo->peer_operating_ch <= 48)) {4681/* Operating Class */4682p2pie[p2pielen++] = 0x73;4683} else {4684/* Operating Class */4685p2pie[p2pielen++] = 0x7c;4686}46874688p2pie[p2pielen++] = pwdinfo->peer_operating_ch;4689} else {4690if (pwdinfo->operating_channel <= 14) {4691/* Operating Class */4692p2pie[p2pielen++] = 0x51;4693} else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48)) {4694/* Operating Class */4695p2pie[p2pielen++] = 0x73;4696} else {4697/* Operating Class */4698p2pie[p2pielen++] = 0x7c;4699}47004701/* Channel Number */4702p2pie[p2pielen++] = pwdinfo->operating_channel; /* Use the listen channel as the operating channel */4703}470447054706/* Channel List */4707/* Type: */4708p2pie[p2pielen++] = P2P_ATTR_CH_LIST;47094710*(u16 *)(p2pie + p2pielen) = 6;4711p2pielen += 2;47124713/* Country String */4714p2pie[p2pielen++] = 'X';4715p2pie[p2pielen++] = 'X';47164717/* The third byte should be set to 0x04. */4718/* Described in the "Operating Channel Attribute" section. */4719p2pie[p2pielen++] = 0x04;47204721/* Value: */4722if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {4723if (pwdinfo->peer_operating_ch <= 14) {4724/* Operating Class */4725p2pie[p2pielen++] = 0x51;4726} else if ((pwdinfo->peer_operating_ch >= 36) && (pwdinfo->peer_operating_ch <= 48)) {4727/* Operating Class */4728p2pie[p2pielen++] = 0x73;4729} else {4730/* Operating Class */4731p2pie[p2pielen++] = 0x7c;4732}4733p2pie[p2pielen++] = 1;4734p2pie[p2pielen++] = pwdinfo->peer_operating_ch;4735} else {4736if (pwdinfo->operating_channel <= 14) {4737/* Operating Class */4738p2pie[p2pielen++] = 0x51;4739} else if ((pwdinfo->operating_channel >= 36) && (pwdinfo->operating_channel <= 48)) {4740/* Operating Class */4741p2pie[p2pielen++] = 0x73;4742} else {4743/* Operating Class */4744p2pie[p2pielen++] = 0x7c;4745}47464747/* Channel Number */4748p2pie[p2pielen++] = 1;4749p2pie[p2pielen++] = pwdinfo->operating_channel; /* Use the listen channel as the operating channel */4750}47514752if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {4753/* Group ID Attribute */4754/* Type: */4755p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;47564757/* Length: */4758*(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);4759p2pielen += 2;47604761/* Value: */4762/* p2P Device Address */4763_rtw_memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);4764p2pielen += ETH_ALEN;47654766/* SSID */4767_rtw_memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);4768p2pielen += pwdinfo->nego_ssidlen;4769}47704771pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);47724773#ifdef CONFIG_WFD4774wfdielen = build_nego_confirm_wfd_ie(pwdinfo, pframe);4775pframe += wfdielen;4776pattrib->pktlen += wfdielen;4777#endif47784779pattrib->last_txcmdsz = pattrib->pktlen;47804781dump_mgntframe(padapter, pmgntframe);47824783return;47844785}47864787void issue_p2p_invitation_request(_adapter *padapter, u8 *raddr)4788{4789struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list);4790unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;4791u8 action = P2P_PUB_ACTION_ACTION;4792u32 p2poui = cpu_to_be32(P2POUI);4793u8 oui_subtype = P2P_INVIT_REQ;4794u8 p2pie[255] = { 0x00 };4795u8 p2pielen = 0;4796u8 dialogToken = 3;4797u16 len_channellist_attr = 0;4798#ifdef CONFIG_WFD4799u32 wfdielen = 0;4800#endif48014802struct xmit_frame *pmgntframe;4803struct pkt_attrib *pattrib;4804unsigned char *pframe;4805struct rtw_ieee80211_hdr *pwlanhdr;4806unsigned short *fctrl;4807struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);4808struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);4809struct wifidirect_info *pwdinfo = &(padapter->wdinfo);481048114812pmgntframe = alloc_mgtxmitframe(pxmitpriv);4813if (pmgntframe == NULL)4814return;48154816/* update attribute */4817pattrib = &pmgntframe->attrib;4818update_mgntframe_attrib(padapter, pattrib);48194820_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);48214822pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;4823pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;48244825fctrl = &(pwlanhdr->frame_ctl);4826*(fctrl) = 0;48274828_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);4829_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);4830_rtw_memcpy(pwlanhdr->addr3, raddr, ETH_ALEN);48314832SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);4833pmlmeext->mgnt_seq++;4834set_frame_sub_type(pframe, WIFI_ACTION);48354836pframe += sizeof(struct rtw_ieee80211_hdr_3addr);4837pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);48384839pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));4840pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));4841pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));4842pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));4843pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));48444845/* P2P IE Section. */48464847/* P2P OUI */4848p2pielen = 0;4849p2pie[p2pielen++] = 0x50;4850p2pie[p2pielen++] = 0x6F;4851p2pie[p2pielen++] = 0x9A;4852p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */48534854/* Commented by Albert 20101011 */4855/* According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */4856/* 1. Configuration Timeout */4857/* 2. Invitation Flags */4858/* 3. Operating Channel ( Only GO ) */4859/* 4. P2P Group BSSID ( Should be included if I am the GO ) */4860/* 5. Channel List */4861/* 6. P2P Group ID */4862/* 7. P2P Device Info */48634864/* Configuration Timeout */4865/* Type: */4866p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;48674868/* Length: */4869*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);4870p2pielen += 2;48714872/* Value: */4873p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */4874p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */48754876/* Invitation Flags */4877/* Type: */4878p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;48794880/* Length: */4881*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);4882p2pielen += 2;48834884/* Value: */4885p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;488648874888/* Operating Channel */4889/* Type: */4890p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;48914892/* Length: */4893*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);4894p2pielen += 2;48954896/* Value: */4897/* Country String */4898p2pie[p2pielen++] = 'X';4899p2pie[p2pielen++] = 'X';49004901/* The third byte should be set to 0x04. */4902/* Described in the "Operating Channel Attribute" section. */4903p2pie[p2pielen++] = 0x04;49044905/* Operating Class */4906if (pwdinfo->invitereq_info.operating_ch <= 14)4907p2pie[p2pielen++] = 0x51;4908else if ((pwdinfo->invitereq_info.operating_ch >= 36) && (pwdinfo->invitereq_info.operating_ch <= 48))4909p2pie[p2pielen++] = 0x73;4910else4911p2pie[p2pielen++] = 0x7c;49124913/* Channel Number */4914p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch; /* operating channel number */49154916if (_rtw_memcmp(adapter_mac_addr(padapter), pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) {4917/* P2P Group BSSID */4918/* Type: */4919p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;49204921/* Length: */4922*(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);4923p2pielen += 2;49244925/* Value: */4926/* P2P Device Address for GO */4927_rtw_memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);4928p2pielen += ETH_ALEN;4929}49304931/* Channel List */4932/* Type: */4933p2pie[p2pielen++] = P2P_ATTR_CH_LIST;493449354936/* Length: */4937/* Country String(3) */4938/* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */4939/* + number of channels in all classes */4940len_channellist_attr = 34941+ (1 + 1) * (u16)ch_list->reg_classes4942+ get_reg_classes_full_count(ch_list);49434944#ifdef CONFIG_CONCURRENT_MODE4945if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)4946*(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1);4947else4948*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);4949#else4950*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);4951#endif4952p2pielen += 2;49534954/* Value: */4955/* Country String */4956p2pie[p2pielen++] = 'X';4957p2pie[p2pielen++] = 'X';49584959/* The third byte should be set to 0x04. */4960/* Described in the "Operating Channel Attribute" section. */4961p2pie[p2pielen++] = 0x04;49624963/* Channel Entry List */4964#ifdef CONFIG_CONCURRENT_MODE4965if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {4966u8 union_ch = rtw_mi_get_union_chan(padapter);49674968/* Operating Class */4969if (union_ch > 14) {4970if (union_ch >= 149)4971p2pie[p2pielen++] = 0x7c;4972else4973p2pie[p2pielen++] = 0x73;4974} else4975p2pie[p2pielen++] = 0x51;497649774978/* Number of Channels */4979/* Just support 1 channel and this channel is AP's channel */4980p2pie[p2pielen++] = 1;49814982/* Channel List */4983p2pie[p2pielen++] = union_ch;4984} else4985#endif /* CONFIG_CONCURRENT_MODE */4986{4987int i, j;4988for (j = 0; j < ch_list->reg_classes; j++) {4989/* Operating Class */4990p2pie[p2pielen++] = ch_list->reg_class[j].reg_class;49914992/* Number of Channels */4993p2pie[p2pielen++] = ch_list->reg_class[j].channels;49944995/* Channel List */4996for (i = 0; i < ch_list->reg_class[j].channels; i++)4997p2pie[p2pielen++] = ch_list->reg_class[j].channel[i];4998}4999}500050015002/* P2P Group ID */5003/* Type: */5004p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;50055006/* Length: */5007*(u16 *)(p2pie + p2pielen) = cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);5008p2pielen += 2;50095010/* Value: */5011/* P2P Device Address for GO */5012_rtw_memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);5013p2pielen += ETH_ALEN;50145015/* SSID */5016_rtw_memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen);5017p2pielen += pwdinfo->invitereq_info.ssidlen;501850195020/* Device Info */5021/* Type: */5022p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;50235024/* Length: */5025/* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */5026/* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */5027*(u16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);5028p2pielen += 2;50295030/* Value: */5031/* P2P Device Address */5032_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);5033p2pielen += ETH_ALEN;50345035/* Config Method */5036/* This field should be big endian. Noted by P2P specification. */5037*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);5038p2pielen += 2;50395040/* Primary Device Type */5041/* Category ID */5042*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);5043p2pielen += 2;50445045/* OUI */5046*(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);5047p2pielen += 4;50485049/* Sub Category ID */5050*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);5051p2pielen += 2;50525053/* Number of Secondary Device Types */5054p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */50555056/* Device Name */5057/* Type: */5058*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);5059p2pielen += 2;50605061/* Length: */5062*(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);5063p2pielen += 2;50645065/* Value: */5066_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);5067p2pielen += pwdinfo->device_name_len;50685069pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);50705071#ifdef CONFIG_WFD5072wfdielen = build_invitation_req_wfd_ie(pwdinfo, pframe);5073pframe += wfdielen;5074pattrib->pktlen += wfdielen;5075#endif50765077pattrib->last_txcmdsz = pattrib->pktlen;50785079dump_mgntframe(padapter, pmgntframe);50805081return;50825083}50845085void issue_p2p_invitation_response(_adapter *padapter, u8 *raddr, u8 dialogToken, u8 status_code)5086{5087struct p2p_channels *ch_list = &(adapter_to_rfctl(padapter)->channel_list);5088unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;5089u8 action = P2P_PUB_ACTION_ACTION;5090u32 p2poui = cpu_to_be32(P2POUI);5091u8 oui_subtype = P2P_INVIT_RESP;5092u8 p2pie[255] = { 0x00 };5093u8 p2pielen = 0;5094u16 len_channellist_attr = 0;5095#ifdef CONFIG_WFD5096u32 wfdielen = 0;5097#endif50985099struct xmit_frame *pmgntframe;5100struct pkt_attrib *pattrib;5101unsigned char *pframe;5102struct rtw_ieee80211_hdr *pwlanhdr;5103unsigned short *fctrl;5104struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);5105struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);5106struct wifidirect_info *pwdinfo = &(padapter->wdinfo);510751085109pmgntframe = alloc_mgtxmitframe(pxmitpriv);5110if (pmgntframe == NULL)5111return;51125113/* update attribute */5114pattrib = &pmgntframe->attrib;5115update_mgntframe_attrib(padapter, pattrib);51165117_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);51185119pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;5120pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;51215122fctrl = &(pwlanhdr->frame_ctl);5123*(fctrl) = 0;51245125_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);5126_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);5127_rtw_memcpy(pwlanhdr->addr3, raddr, ETH_ALEN);51285129SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);5130pmlmeext->mgnt_seq++;5131set_frame_sub_type(pframe, WIFI_ACTION);51325133pframe += sizeof(struct rtw_ieee80211_hdr_3addr);5134pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);51355136pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));5137pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));5138pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));5139pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));5140pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));51415142/* P2P IE Section. */51435144/* P2P OUI */5145p2pielen = 0;5146p2pie[p2pielen++] = 0x50;5147p2pie[p2pielen++] = 0x6F;5148p2pie[p2pielen++] = 0x9A;5149p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */51505151/* Commented by Albert 20101005 */5152/* According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */5153/* 1. Status */5154/* 2. Configuration Timeout */5155/* 3. Operating Channel ( Only GO ) */5156/* 4. P2P Group BSSID ( Only GO ) */5157/* 5. Channel List */51585159/* P2P Status */5160/* Type: */5161p2pie[p2pielen++] = P2P_ATTR_STATUS;51625163/* Length: */5164*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);5165p2pielen += 2;51665167/* Value: */5168/* When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */5169/* Sent the event receiving the P2P Invitation Req frame to DMP UI. */5170/* DMP had to compare the MAC address to find out the profile. */5171/* So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */5172/* If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */5173/* to NB to rebuild the persistent group. */5174p2pie[p2pielen++] = status_code;51755176/* Configuration Timeout */5177/* Type: */5178p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;51795180/* Length: */5181*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);5182p2pielen += 2;51835184/* Value: */5185p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P GO */5186p2pie[p2pielen++] = 200; /* 2 seconds needed to be the P2P Client */51875188if (status_code == P2P_STATUS_SUCCESS) {5189if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {5190/* The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */5191/* In this case, the P2P Invitation response frame should carry the two more P2P attributes. */5192/* First one is operating channel attribute. */5193/* Second one is P2P Group BSSID attribute. */51945195/* Operating Channel */5196/* Type: */5197p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;51985199/* Length: */5200*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);5201p2pielen += 2;52025203/* Value: */5204/* Country String */5205p2pie[p2pielen++] = 'X';5206p2pie[p2pielen++] = 'X';52075208/* The third byte should be set to 0x04. */5209/* Described in the "Operating Channel Attribute" section. */5210p2pie[p2pielen++] = 0x04;52115212/* Operating Class */5213p2pie[p2pielen++] = 0x51; /* Copy from SD7 */52145215/* Channel Number */5216p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */521752185219/* P2P Group BSSID */5220/* Type: */5221p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;52225223/* Length: */5224*(u16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);5225p2pielen += 2;52265227/* Value: */5228/* P2P Device Address for GO */5229_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);5230p2pielen += ETH_ALEN;52315232}52335234/* Channel List */5235/* Type: */5236p2pie[p2pielen++] = P2P_ATTR_CH_LIST;52375238/* Length: */5239/* Country String(3) */5240/* + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?) */5241/* + number of channels in all classes */5242len_channellist_attr = 35243+ (1 + 1) * (u16)ch_list->reg_classes5244+ get_reg_classes_full_count(ch_list);52455246#ifdef CONFIG_CONCURRENT_MODE5247if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0)5248*(u16 *)(p2pie + p2pielen) = cpu_to_le16(5 + 1);5249else5250*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);5251#else5252*(u16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);5253#endif5254p2pielen += 2;52555256/* Value: */5257/* Country String */5258p2pie[p2pielen++] = 'X';5259p2pie[p2pielen++] = 'X';52605261/* The third byte should be set to 0x04. */5262/* Described in the "Operating Channel Attribute" section. */5263p2pie[p2pielen++] = 0x04;52645265/* Channel Entry List */5266#ifdef CONFIG_CONCURRENT_MODE5267if (rtw_mi_check_status(padapter, MI_LINKED) && padapter->registrypriv.full_ch_in_p2p_handshake == 0) {5268u8 union_ch = rtw_mi_get_union_chan(padapter);52695270/* Operating Class */5271if (union_ch > 14) {5272if (union_ch >= 149)5273p2pie[p2pielen++] = 0x7c;5274else5275p2pie[p2pielen++] = 0x73;5276} else5277p2pie[p2pielen++] = 0x51;527852795280/* Number of Channels */5281/* Just support 1 channel and this channel is AP's channel */5282p2pie[p2pielen++] = 1;52835284/* Channel List */5285p2pie[p2pielen++] = union_ch;5286} else5287#endif /* CONFIG_CONCURRENT_MODE */5288{5289int i, j;5290for (j = 0; j < ch_list->reg_classes; j++) {5291/* Operating Class */5292p2pie[p2pielen++] = ch_list->reg_class[j].reg_class;52935294/* Number of Channels */5295p2pie[p2pielen++] = ch_list->reg_class[j].channels;52965297/* Channel List */5298for (i = 0; i < ch_list->reg_class[j].channels; i++)5299p2pie[p2pielen++] = ch_list->reg_class[j].channel[i];5300}5301}5302}53035304pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);53055306#ifdef CONFIG_WFD5307wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe);5308pframe += wfdielen;5309pattrib->pktlen += wfdielen;5310#endif53115312pattrib->last_txcmdsz = pattrib->pktlen;53135314dump_mgntframe(padapter, pmgntframe);53155316return;53175318}53195320void issue_p2p_provision_request(_adapter *padapter, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)5321{5322unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;5323u8 action = P2P_PUB_ACTION_ACTION;5324u8 dialogToken = 1;5325u32 p2poui = cpu_to_be32(P2POUI);5326u8 oui_subtype = P2P_PROVISION_DISC_REQ;5327u8 wpsie[100] = { 0x00 };5328u8 wpsielen = 0;5329u32 p2pielen = 0;5330#ifdef CONFIG_WFD5331u32 wfdielen = 0;5332#endif53335334struct xmit_frame *pmgntframe;5335struct pkt_attrib *pattrib;5336unsigned char *pframe;5337struct rtw_ieee80211_hdr *pwlanhdr;5338unsigned short *fctrl;5339struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);5340struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);5341struct wifidirect_info *pwdinfo = &(padapter->wdinfo);534253435344pmgntframe = alloc_mgtxmitframe(pxmitpriv);5345if (pmgntframe == NULL)5346return;53475348RTW_INFO("[%s] In\n", __FUNCTION__);5349/* update attribute */5350pattrib = &pmgntframe->attrib;5351update_mgntframe_attrib(padapter, pattrib);53525353_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);53545355pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;5356pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;53575358fctrl = &(pwlanhdr->frame_ctl);5359*(fctrl) = 0;53605361_rtw_memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);5362_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);5363_rtw_memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);53645365SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);5366pmlmeext->mgnt_seq++;5367set_frame_sub_type(pframe, WIFI_ACTION);53685369pframe += sizeof(struct rtw_ieee80211_hdr_3addr);5370pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);53715372pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));5373pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));5374pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));5375pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));5376pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));53775378p2pielen = build_prov_disc_request_p2p_ie(pwdinfo, pframe, pssid, ussidlen, pdev_raddr);53795380pframe += p2pielen;5381pattrib->pktlen += p2pielen;53825383wpsielen = 0;5384/* WPS OUI */5385*(u32 *)(wpsie) = cpu_to_be32(WPSOUI);5386wpsielen += 4;53875388/* WPS version */5389/* Type: */5390*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);5391wpsielen += 2;53925393/* Length: */5394*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);5395wpsielen += 2;53965397/* Value: */5398wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */53995400/* Config Method */5401/* Type: */5402*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);5403wpsielen += 2;54045405/* Length: */5406*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);5407wpsielen += 2;54085409/* Value: */5410*(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);5411wpsielen += 2;54125413pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);541454155416#ifdef CONFIG_WFD5417wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);5418pframe += wfdielen;5419pattrib->pktlen += wfdielen;5420#endif54215422pattrib->last_txcmdsz = pattrib->pktlen;54235424dump_mgntframe(padapter, pmgntframe);54255426return;54275428}542954305431u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profileinfo)5432{5433u8 i, match_result = 0;54345435RTW_INFO("[%s] peermac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,5436peermacaddr[0], peermacaddr[1], peermacaddr[2], peermacaddr[3], peermacaddr[4], peermacaddr[5]);54375438for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {5439RTW_INFO("[%s] profileinfo_mac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,5440profileinfo->peermac[0], profileinfo->peermac[1], profileinfo->peermac[2], profileinfo->peermac[3], profileinfo->peermac[4], profileinfo->peermac[5]);5441if (_rtw_memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) {5442match_result = 1;5443RTW_INFO("[%s] Match!\n", __FUNCTION__);5444break;5445}5446}54475448return match_result ;5449}54505451void issue_probersp_p2p(_adapter *padapter, unsigned char *da)5452{5453struct xmit_frame *pmgntframe;5454struct pkt_attrib *pattrib;5455unsigned char *pframe;5456struct rtw_ieee80211_hdr *pwlanhdr;5457unsigned short *fctrl;5458unsigned char *mac;5459struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);5460struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);5461struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);5462/* WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network); */5463u16 beacon_interval = 100;5464u16 capInfo = 0;5465struct wifidirect_info *pwdinfo = &(padapter->wdinfo);5466u8 wpsie[255] = { 0x00 };5467u32 wpsielen = 0, p2pielen = 0;5468#ifdef CONFIG_WFD5469u32 wfdielen = 0;5470#endif54715472/* RTW_INFO("%s\n", __FUNCTION__); */54735474pmgntframe = alloc_mgtxmitframe(pxmitpriv);5475if (pmgntframe == NULL)5476return;54775478/* update attribute */5479pattrib = &pmgntframe->attrib;5480update_mgntframe_attrib(padapter, pattrib);54815482if (IS_CCK_RATE(pattrib->rate)) {5483/* force OFDM 6M rate */5484pattrib->rate = MGN_6M;5485pattrib->raid = rtw_get_mgntframe_raid(padapter, WIRELESS_11G);5486}54875488_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);54895490pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;5491pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;54925493mac = adapter_mac_addr(padapter);54945495fctrl = &(pwlanhdr->frame_ctl);5496*(fctrl) = 0;5497_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);5498_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);54995500/* Use the device address for BSSID field. */5501_rtw_memcpy(pwlanhdr->addr3, mac, ETH_ALEN);55025503SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);5504pmlmeext->mgnt_seq++;5505set_frame_sub_type(fctrl, WIFI_PROBERSP);55065507pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);5508pattrib->pktlen = pattrib->hdrlen;5509pframe += pattrib->hdrlen;55105511/* timestamp will be inserted by hardware */5512pframe += 8;5513pattrib->pktlen += 8;55145515/* beacon interval: 2 bytes */5516_rtw_memcpy(pframe, (unsigned char *) &beacon_interval, 2);5517pframe += 2;5518pattrib->pktlen += 2;55195520/* capability info: 2 bytes */5521/* ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */5522capInfo |= cap_ShortPremble;5523capInfo |= cap_ShortSlot;55245525_rtw_memcpy(pframe, (unsigned char *) &capInfo, 2);5526pframe += 2;5527pattrib->pktlen += 2;552855295530/* SSID */5531pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);55325533/* supported rates... */5534/* Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 ) */5535pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);55365537/* DS parameter set */5538pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);55395540#ifdef CONFIG_IOCTL_CFG802115541if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {5542if (pmlmepriv->wps_probe_resp_ie != NULL && pmlmepriv->p2p_probe_resp_ie != NULL) {5543/* WPS IE */5544_rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);5545pattrib->pktlen += pmlmepriv->wps_probe_resp_ie_len;5546pframe += pmlmepriv->wps_probe_resp_ie_len;55475548/* P2P IE */5549_rtw_memcpy(pframe, pmlmepriv->p2p_probe_resp_ie, pmlmepriv->p2p_probe_resp_ie_len);5550pattrib->pktlen += pmlmepriv->p2p_probe_resp_ie_len;5551pframe += pmlmepriv->p2p_probe_resp_ie_len;5552}5553} else5554#endif /* CONFIG_IOCTL_CFG80211 */5555{55565557/* Todo: WPS IE */5558/* Noted by Albert 20100907 */5559/* According to the WPS specification, all the WPS attribute is presented by Big Endian. */55605561wpsielen = 0;5562/* WPS OUI */5563*(u32 *)(wpsie) = cpu_to_be32(WPSOUI);5564wpsielen += 4;55655566/* WPS version */5567/* Type: */5568*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);5569wpsielen += 2;55705571/* Length: */5572*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);5573wpsielen += 2;55745575/* Value: */5576wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */55775578/* WiFi Simple Config State */5579/* Type: */5580*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);5581wpsielen += 2;55825583/* Length: */5584*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);5585wpsielen += 2;55865587/* Value: */5588wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG; /* Not Configured. */55895590/* Response Type */5591/* Type: */5592*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);5593wpsielen += 2;55945595/* Length: */5596*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);5597wpsielen += 2;55985599/* Value: */5600wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;56015602/* UUID-E */5603/* Type: */5604*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);5605wpsielen += 2;56065607/* Length: */5608*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);5609wpsielen += 2;56105611/* Value: */5612if (pwdinfo->external_uuid == 0) {5613_rtw_memset(wpsie + wpsielen, 0x0, 16);5614_rtw_memcpy(wpsie + wpsielen, mac, ETH_ALEN);5615} else5616_rtw_memcpy(wpsie + wpsielen, pwdinfo->uuid, 0x10);5617wpsielen += 0x10;56185619/* Manufacturer */5620/* Type: */5621*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);5622wpsielen += 2;56235624/* Length: */5625*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007);5626wpsielen += 2;56275628/* Value: */5629_rtw_memcpy(wpsie + wpsielen, "Realtek", 7);5630wpsielen += 7;56315632/* Model Name */5633/* Type: */5634*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);5635wpsielen += 2;56365637/* Length: */5638*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006);5639wpsielen += 2;56405641/* Value: */5642_rtw_memcpy(wpsie + wpsielen, "8192CU", 6);5643wpsielen += 6;56445645/* Model Number */5646/* Type: */5647*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);5648wpsielen += 2;56495650/* Length: */5651*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);5652wpsielen += 2;56535654/* Value: */5655wpsie[wpsielen++] = 0x31; /* character 1 */56565657/* Serial Number */5658/* Type: */5659*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);5660wpsielen += 2;56615662/* Length: */5663*(u16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);5664wpsielen += 2;56655666/* Value: */5667_rtw_memcpy(wpsie + wpsielen, "123456" , ETH_ALEN);5668wpsielen += ETH_ALEN;56695670/* Primary Device Type */5671/* Type: */5672*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);5673wpsielen += 2;56745675/* Length: */5676*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);5677wpsielen += 2;56785679/* Value: */5680/* Category ID */5681*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);5682wpsielen += 2;56835684/* OUI */5685*(u32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);5686wpsielen += 4;56875688/* Sub Category ID */5689*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);5690wpsielen += 2;56915692/* Device Name */5693/* Type: */5694*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);5695wpsielen += 2;56965697/* Length: */5698*(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);5699wpsielen += 2;57005701/* Value: */5702_rtw_memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);5703wpsielen += pwdinfo->device_name_len;57045705/* Config Method */5706/* Type: */5707*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);5708wpsielen += 2;57095710/* Length: */5711*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);5712wpsielen += 2;57135714/* Value: */5715*(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);5716wpsielen += 2;571757185719pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);572057215722p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);5723pframe += p2pielen;5724pattrib->pktlen += p2pielen;5725}57265727#ifdef CONFIG_WFD5728wfdielen = rtw_append_probe_resp_wfd_ie(padapter, pframe);5729pframe += wfdielen;5730pattrib->pktlen += wfdielen;5731#endif57325733/* Vendor Specific IE */5734#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE5735pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_P2P_PROBERESP_VENDOR_IE_BIT);5736#endif57375738pattrib->last_txcmdsz = pattrib->pktlen;573957405741dump_mgntframe(padapter, pmgntframe);57425743return;57445745}57465747int _issue_probereq_p2p(_adapter *padapter, u8 *da, int wait_ack)5748{5749int ret = _FAIL;5750struct xmit_frame *pmgntframe;5751struct pkt_attrib *pattrib;5752unsigned char *pframe;5753struct rtw_ieee80211_hdr *pwlanhdr;5754unsigned short *fctrl;5755unsigned char *mac;5756struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);5757struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);5758u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};5759struct wifidirect_info *pwdinfo = &(padapter->wdinfo);5760u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };5761u16 wpsielen = 0, p2pielen = 0;5762#ifdef CONFIG_WFD5763u32 wfdielen = 0;5764#endif57655766struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);576757685769pmgntframe = alloc_mgtxmitframe(pxmitpriv);5770if (pmgntframe == NULL)5771goto exit;57725773/* update attribute */5774pattrib = &pmgntframe->attrib;5775update_mgntframe_attrib(padapter, pattrib);57765777if (IS_CCK_RATE(pattrib->rate)) {5778/* force OFDM 6M rate */5779pattrib->rate = MGN_6M;5780pattrib->raid = rtw_get_mgntframe_raid(padapter, WIRELESS_11G);5781}57825783_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);57845785pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;5786pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;57875788mac = adapter_mac_addr(padapter);57895790fctrl = &(pwlanhdr->frame_ctl);5791*(fctrl) = 0;57925793if (da) {5794_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);5795_rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);5796} else {5797if ((pwdinfo->p2p_info.scan_op_ch_only) || (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {5798/* This two flags will be set when this is only the P2P client mode. */5799_rtw_memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);5800_rtw_memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);5801} else {5802/* broadcast probe request frame */5803_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);5804_rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);5805}5806}5807_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);58085809SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);5810pmlmeext->mgnt_seq++;5811set_frame_sub_type(pframe, WIFI_PROBEREQ);58125813pframe += sizeof(struct rtw_ieee80211_hdr_3addr);5814pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);58155816if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))5817pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &(pattrib->pktlen));5818else5819pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &(pattrib->pktlen));5820/* Use the OFDM rate in the P2P probe request frame. ( 6(B), 9(B), 12(B), 24(B), 36, 48, 54 ) */5821pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);58225823#ifdef CONFIG_IOCTL_CFG802115824if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {5825if (pmlmepriv->wps_probe_req_ie != NULL && pmlmepriv->p2p_probe_req_ie != NULL) {5826/* WPS IE */5827_rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);5828pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;5829pframe += pmlmepriv->wps_probe_req_ie_len;58305831/* P2P IE */5832_rtw_memcpy(pframe, pmlmepriv->p2p_probe_req_ie, pmlmepriv->p2p_probe_req_ie_len);5833pattrib->pktlen += pmlmepriv->p2p_probe_req_ie_len;5834pframe += pmlmepriv->p2p_probe_req_ie_len;5835}5836} else5837#endif /* CONFIG_IOCTL_CFG80211 */5838{58395840/* WPS IE */5841/* Noted by Albert 20110221 */5842/* According to the WPS specification, all the WPS attribute is presented by Big Endian. */58435844wpsielen = 0;5845/* WPS OUI */5846*(u32 *)(wpsie) = cpu_to_be32(WPSOUI);5847wpsielen += 4;58485849/* WPS version */5850/* Type: */5851*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);5852wpsielen += 2;58535854/* Length: */5855*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);5856wpsielen += 2;58575858/* Value: */5859wpsie[wpsielen++] = WPS_VERSION_1; /* Version 1.0 */58605861if (pmlmepriv->wps_probe_req_ie == NULL) {5862/* UUID-E */5863/* Type: */5864*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);5865wpsielen += 2;58665867/* Length: */5868*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);5869wpsielen += 2;58705871/* Value: */5872if (pwdinfo->external_uuid == 0) {5873_rtw_memset(wpsie + wpsielen, 0x0, 16);5874_rtw_memcpy(wpsie + wpsielen, mac, ETH_ALEN);5875} else5876_rtw_memcpy(wpsie + wpsielen, pwdinfo->uuid, 0x10);5877wpsielen += 0x10;58785879/* Config Method */5880/* Type: */5881*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);5882wpsielen += 2;58835884/* Length: */5885*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);5886wpsielen += 2;58875888/* Value: */5889*(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);5890wpsielen += 2;5891}58925893/* Device Name */5894/* Type: */5895*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);5896wpsielen += 2;58975898/* Length: */5899*(u16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);5900wpsielen += 2;59015902/* Value: */5903_rtw_memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);5904wpsielen += pwdinfo->device_name_len;59055906/* Primary Device Type */5907/* Type: */5908*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);5909wpsielen += 2;59105911/* Length: */5912*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);5913wpsielen += 2;59145915/* Value: */5916/* Category ID */5917*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);5918wpsielen += 2;59195920/* OUI */5921*(u32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);5922wpsielen += 4;59235924/* Sub Category ID */5925*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);5926wpsielen += 2;59275928/* Device Password ID */5929/* Type: */5930*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);5931wpsielen += 2;59325933/* Length: */5934*(u16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);5935wpsielen += 2;59365937/* Value: */5938*(u16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC); /* Registrar-specified */5939wpsielen += 2;59405941pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen);59425943/* P2P OUI */5944p2pielen = 0;5945p2pie[p2pielen++] = 0x50;5946p2pie[p2pielen++] = 0x6F;5947p2pie[p2pielen++] = 0x9A;5948p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */59495950/* Commented by Albert 20110221 */5951/* According to the P2P Specification, the probe request frame should contain 5 P2P attributes */5952/* 1. P2P Capability */5953/* 2. P2P Device ID if this probe request wants to find the specific P2P device */5954/* 3. Listen Channel */5955/* 4. Extended Listen Timing */5956/* 5. Operating Channel if this WiFi is working as the group owner now */59575958/* P2P Capability */5959/* Type: */5960p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;59615962/* Length: */5963*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);5964p2pielen += 2;59655966/* Value: */5967/* Device Capability Bitmap, 1 byte */5968p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;59695970/* Group Capability Bitmap, 1 byte */5971if (pwdinfo->persistent_supported)5972p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;5973else5974p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;59755976/* Listen Channel */5977/* Type: */5978p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;59795980/* Length: */5981*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);5982p2pielen += 2;59835984/* Value: */5985/* Country String */5986p2pie[p2pielen++] = 'X';5987p2pie[p2pielen++] = 'X';59885989/* The third byte should be set to 0x04. */5990/* Described in the "Operating Channel Attribute" section. */5991p2pie[p2pielen++] = 0x04;59925993/* Operating Class */5994p2pie[p2pielen++] = 0x51; /* Copy from SD7 */59955996/* Channel Number */5997p2pie[p2pielen++] = pwdinfo->listen_channel; /* listen channel */599859996000/* Extended Listen Timing */6001/* Type: */6002p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;60036004/* Length: */6005*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);6006p2pielen += 2;60076008/* Value: */6009/* Availability Period */6010*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);6011p2pielen += 2;60126013/* Availability Interval */6014*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);6015p2pielen += 2;60166017if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {6018/* Operating Channel (if this WiFi is working as the group owner now) */6019/* Type: */6020p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;60216022/* Length: */6023*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);6024p2pielen += 2;60256026/* Value: */6027/* Country String */6028p2pie[p2pielen++] = 'X';6029p2pie[p2pielen++] = 'X';60306031/* The third byte should be set to 0x04. */6032/* Described in the "Operating Channel Attribute" section. */6033p2pie[p2pielen++] = 0x04;60346035/* Operating Class */6036p2pie[p2pielen++] = 0x51; /* Copy from SD7 */60376038/* Channel Number */6039p2pie[p2pielen++] = pwdinfo->operating_channel; /* operating channel number */60406041}60426043pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);60446045}60466047#ifdef CONFIG_WFD6048wfdielen = rtw_append_probe_req_wfd_ie(padapter, pframe);6049pframe += wfdielen;6050pattrib->pktlen += wfdielen;6051#endif60526053/* Vendor Specific IE */6054#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE6055pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_P2P_PROBEREQ_VENDOR_IE_BIT);6056#endif60576058pattrib->last_txcmdsz = pattrib->pktlen;605960606061if (wait_ack)6062ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);6063else {6064dump_mgntframe(padapter, pmgntframe);6065ret = _SUCCESS;6066}60676068exit:6069return ret;6070}60716072inline void issue_probereq_p2p(_adapter *adapter, u8 *da)6073{6074_issue_probereq_p2p(adapter, da, _FALSE);6075}60766077/*6078* wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT6079* 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 TX6080* try_cnt means the maximal TX count to try6081*/6082int issue_probereq_p2p_ex(_adapter *adapter, u8 *da, int try_cnt, int wait_ms)6083{6084int ret;6085int i = 0;6086systime start = rtw_get_current_time();60876088do {6089ret = _issue_probereq_p2p(adapter, da, wait_ms > 0 ? _TRUE : _FALSE);60906091i++;60926093if (RTW_CANNOT_RUN(adapter))6094break;60956096if (i < try_cnt && wait_ms > 0 && ret == _FAIL)6097rtw_msleep_os(wait_ms);60986099} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));61006101if (ret != _FAIL) {6102ret = _SUCCESS;6103#ifndef DBG_XMIT_ACK6104goto exit;6105#endif6106}61076108if (try_cnt && wait_ms) {6109if (da)6110RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",6111FUNC_ADPT_ARG(adapter), MAC_ARG(da), rtw_get_oper_ch(adapter),6112ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));6113else6114RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",6115FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter),6116ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));6117}6118exit:6119return ret;6120}61216122#endif /* CONFIG_P2P */61236124s32 rtw_action_public_decache(union recv_frame *rframe, u8 token_offset)6125{6126_adapter *adapter = rframe->u.hdr.adapter;6127struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);6128u8 *frame = rframe->u.hdr.rx_data;6129u16 seq_ctrl = ((rframe->u.hdr.attrib.seq_num & 0xffff) << 4) | (rframe->u.hdr.attrib.frag_num & 0xf);6130u8 token = *(rframe->u.hdr.rx_data + sizeof(struct rtw_ieee80211_hdr_3addr) + token_offset);61316132if (GetRetry(frame)) {6133if ((seq_ctrl == mlmeext->action_public_rxseq)6134&& (token == mlmeext->action_public_dialog_token)6135) {6136RTW_INFO(FUNC_ADPT_FMT" seq_ctrl=0x%x, rxseq=0x%x, token:%d\n",6137FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);6138return _FAIL;6139}6140}61416142/* TODO: per sta seq & token */6143mlmeext->action_public_rxseq = seq_ctrl;6144mlmeext->action_public_dialog_token = token;61456146return _SUCCESS;6147}61486149unsigned int on_action_public_p2p(union recv_frame *precv_frame)6150{6151_adapter *padapter = precv_frame->u.hdr.adapter;6152u8 *pframe = precv_frame->u.hdr.rx_data;6153uint len = precv_frame->u.hdr.len;6154u8 *frame_body;6155#ifdef CONFIG_P2P6156u8 *p2p_ie;6157u32 p2p_ielen;6158struct wifidirect_info *pwdinfo = &(padapter->wdinfo);6159u8 result = P2P_STATUS_SUCCESS;6160u8 empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };6161u8 *merged_p2pie = NULL;6162u32 merged_p2p_ielen = 0;6163#endif /* CONFIG_P2P */61646165frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));61666167#ifdef CONFIG_P2P6168_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);6169#ifdef CONFIG_IOCTL_CFG802116170if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211)6171rtw_cfg80211_rx_p2p_action_public(padapter, precv_frame);6172else6173#endif /* CONFIG_IOCTL_CFG80211 */6174{6175/* Do nothing if the driver doesn't enable the P2P function. */6176if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))6177return _SUCCESS;61786179len -= sizeof(struct rtw_ieee80211_hdr_3addr);61806181switch (frame_body[6]) { /* OUI Subtype */6182case P2P_GO_NEGO_REQ: {6183RTW_INFO("[%s] Got GO Nego Req Frame\n", __FUNCTION__);6184_rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));61856186if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))6187rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));61886189if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) {6190/* Commented by Albert 20110526 */6191/* In this case, this means the previous nego fail doesn't be reset yet. */6192_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);6193/* Restore the previous p2p state */6194rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));6195RTW_INFO("[%s] Restore the previous p2p state to %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo));6196}6197#ifdef CONFIG_CONCURRENT_MODE6198if (rtw_mi_buddy_check_fwstate(padapter, _FW_LINKED))6199_cancel_timer_ex(&pwdinfo->ap_p2p_switch_timer);6200#endif /* CONFIG_CONCURRENT_MODE */62016202/* Commented by Kurt 20110902 */6203/* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */6204if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))6205rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));62066207/* Commented by Kurt 20120113 */6208/* Get peer_dev_addr here if peer doesn't issue prov_disc frame. */6209if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN))6210_rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, get_addr2_ptr(pframe), ETH_ALEN);62116212result = process_p2p_group_negotation_req(pwdinfo, frame_body, len);6213issue_p2p_GO_response(padapter, get_addr2_ptr(pframe), frame_body, len, result);62146215/* Commented by Albert 20110718 */6216/* No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */6217#ifdef CONFIG_CONCURRENT_MODE6218/* Commented by Albert 20120107 */6219_set_timer(&pwdinfo->restore_p2p_state_timer, 3000);6220#else /* CONFIG_CONCURRENT_MODE */6221_set_timer(&pwdinfo->restore_p2p_state_timer, 5000);6222#endif /* CONFIG_CONCURRENT_MODE */6223break;6224}6225case P2P_GO_NEGO_RESP: {6226RTW_INFO("[%s] Got GO Nego Resp Frame\n", __FUNCTION__);62276228if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {6229/* Commented by Albert 20110425 */6230/* The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */6231_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);6232pwdinfo->nego_req_info.benable = _FALSE;6233result = process_p2p_group_negotation_resp(pwdinfo, frame_body, len);6234issue_p2p_GO_confirm(pwdinfo->padapter, get_addr2_ptr(pframe), result);6235if (P2P_STATUS_SUCCESS == result) {6236if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {6237pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;6238#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH6239pwdinfo->p2p_info.operation_ch[1] = 1; /* Check whether GO is operating in channel 1; */6240pwdinfo->p2p_info.operation_ch[2] = 6; /* Check whether GO is operating in channel 6; */6241pwdinfo->p2p_info.operation_ch[3] = 11; /* Check whether GO is operating in channel 11; */6242#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */6243pwdinfo->p2p_info.scan_op_ch_only = 1;6244_set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);6245}6246}62476248/* Reset the dialog token for group negotiation frames. */6249pwdinfo->negotiation_dialog_token = 1;62506251if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))6252_set_timer(&pwdinfo->restore_p2p_state_timer, 5000);6253} else6254RTW_INFO("[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __FUNCTION__);62556256break;6257}6258case P2P_GO_NEGO_CONF: {6259RTW_INFO("[%s] Got GO Nego Confirm Frame\n", __FUNCTION__);6260result = process_p2p_group_negotation_confirm(pwdinfo, frame_body, len);6261if (P2P_STATUS_SUCCESS == result) {6262if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {6263pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;6264#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH6265pwdinfo->p2p_info.operation_ch[1] = 1; /* Check whether GO is operating in channel 1; */6266pwdinfo->p2p_info.operation_ch[2] = 6; /* Check whether GO is operating in channel 6; */6267pwdinfo->p2p_info.operation_ch[3] = 11; /* Check whether GO is operating in channel 11; */6268#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */6269pwdinfo->p2p_info.scan_op_ch_only = 1;6270_set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);6271}6272}6273break;6274}6275case P2P_INVIT_REQ: {6276/* Added by Albert 2010/10/05 */6277/* Received the P2P Invite Request frame. */62786279RTW_INFO("[%s] Got invite request frame!\n", __FUNCTION__);6280p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);6281if (p2p_ie) {6282/* Parse the necessary information from the P2P Invitation Request frame. */6283/* For example: The MAC address of sending this P2P Invitation Request frame. */6284u32 attr_contentlen = 0;6285u8 status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;6286struct group_id_info group_id;6287u8 invitation_flag = 0;62886289merged_p2p_ielen = rtw_get_p2p_merged_ies_len(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_);62906291merged_p2pie = rtw_zmalloc(merged_p2p_ielen + 2); /* 2 is for EID and Length */6292if (merged_p2pie == NULL) {6293RTW_INFO("[%s] Malloc p2p ie fail\n", __FUNCTION__);6294goto exit;6295}6296_rtw_memset(merged_p2pie, 0x00, merged_p2p_ielen);62976298merged_p2p_ielen = rtw_p2p_merge_ies(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, merged_p2pie);62996300rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);6301if (attr_contentlen) {63026303rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);6304/* Commented by Albert 20120510 */6305/* Copy to the pwdinfo->p2p_peer_interface_addr. */6306/* So that the WFD UI ( or Sigma ) can get the peer interface address by using the following command. */6307/* #> iwpriv wlan0 p2p_get peer_ifa */6308/* After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */63096310if (attr_contentlen) {6311RTW_INFO("[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,6312pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],6313pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],6314pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);6315}63166317if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT) {6318/* Re-invoke the persistent group. */63196320_rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));6321rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *) &group_id, &attr_contentlen);6322if (attr_contentlen) {6323if (_rtw_memcmp(group_id.go_device_addr, adapter_mac_addr(padapter), ETH_ALEN)) {6324/* The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */6325rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);6326rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);6327status_code = P2P_STATUS_SUCCESS;6328} else {6329/* The p2p device sending this p2p invitation request wants to be the persistent GO. */6330if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[0])) {6331u8 operatingch_info[5] = { 0x00 };6332if (rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info,6333&attr_contentlen)) {6334if (rtw_chset_search_ch(adapter_to_chset(padapter), (u32)operatingch_info[4]) >= 0) {6335/* The operating channel is acceptable for this device. */6336pwdinfo->rx_invitereq_info.operation_ch[0] = operatingch_info[4];6337#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH6338pwdinfo->rx_invitereq_info.operation_ch[1] = 1; /* Check whether GO is operating in channel 1; */6339pwdinfo->rx_invitereq_info.operation_ch[2] = 6; /* Check whether GO is operating in channel 6; */6340pwdinfo->rx_invitereq_info.operation_ch[3] = 11; /* Check whether GO is operating in channel 11; */6341#endif /* CONFIG_P2P_OP_CHK_SOCIAL_CH */6342pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;6343_set_timer(&pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH);6344rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);6345rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);6346status_code = P2P_STATUS_SUCCESS;6347} else {6348/* The operating channel isn't supported by this device. */6349rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);6350rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);6351status_code = P2P_STATUS_FAIL_NO_COMMON_CH;6352_set_timer(&pwdinfo->restore_p2p_state_timer, 3000);6353}6354} else {6355/* Commented by Albert 20121130 */6356/* Intel will use the different P2P IE to store the operating channel information */6357/* Workaround for Intel WiDi 3.5 */6358rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);6359rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);6360status_code = P2P_STATUS_SUCCESS;6361}6362} else {6363rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);6364status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;6365}6366}6367} else {6368RTW_INFO("[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__);6369status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;6370}6371} else {6372/* Received the invitation to join a P2P group. */63736374_rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));6375rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *) &group_id, &attr_contentlen);6376if (attr_contentlen) {6377if (_rtw_memcmp(group_id.go_device_addr, adapter_mac_addr(padapter), ETH_ALEN)) {6378/* In this case, the GO can't be myself. */6379rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);6380status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;6381} else {6382/* The p2p device sending this p2p invitation request wants to join an existing P2P group */6383/* Commented by Albert 2012/06/28 */6384/* In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */6385/* The peer device address should be the destination address for the provisioning discovery request. */6386/* Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */6387/* The peer interface address should be the address for WPS mac address */6388_rtw_memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN);6389rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);6390rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);6391status_code = P2P_STATUS_SUCCESS;6392}6393} else {6394RTW_INFO("[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__);6395status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;6396}6397}6398} else {6399RTW_INFO("[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __FUNCTION__);6400status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;6401}64026403RTW_INFO("[%s] status_code = %d\n", __FUNCTION__, status_code);64046405pwdinfo->inviteresp_info.token = frame_body[7];6406issue_p2p_invitation_response(padapter, get_addr2_ptr(pframe), pwdinfo->inviteresp_info.token, status_code);6407_set_timer(&pwdinfo->restore_p2p_state_timer, 3000);6408}6409break;6410}6411case P2P_INVIT_RESP: {6412u8 attr_content = 0x00;6413u32 attr_contentlen = 0;64146415RTW_INFO("[%s] Got invite response frame!\n", __FUNCTION__);6416_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);6417p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);6418if (p2p_ie) {6419rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);64206421if (attr_contentlen == 1) {6422RTW_INFO("[%s] Status = %d\n", __FUNCTION__, attr_content);6423pwdinfo->invitereq_info.benable = _FALSE;64246425if (attr_content == P2P_STATUS_SUCCESS) {6426if (_rtw_memcmp(pwdinfo->invitereq_info.go_bssid, adapter_mac_addr(padapter), ETH_ALEN))6427rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);6428else6429rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);64306431rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);6432} else {6433rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);6434rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);6435}6436} else {6437rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);6438rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);6439}6440} else {6441rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);6442rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);6443}64446445if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL))6446_set_timer(&pwdinfo->restore_p2p_state_timer, 5000);6447break;6448}6449case P2P_DEVDISC_REQ:64506451process_p2p_devdisc_req(pwdinfo, pframe, len);64526453break;64546455case P2P_DEVDISC_RESP:64566457process_p2p_devdisc_resp(pwdinfo, pframe, len);64586459break;64606461case P2P_PROVISION_DISC_REQ:6462RTW_INFO("[%s] Got Provisioning Discovery Request Frame\n", __FUNCTION__);6463process_p2p_provdisc_req(pwdinfo, pframe, len);6464_rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, get_addr2_ptr(pframe), ETH_ALEN);64656466/* 20110902 Kurt */6467/* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */6468if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))6469rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));64706471rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);6472_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);6473break;64746475case P2P_PROVISION_DISC_RESP:6476/* Commented by Albert 20110707 */6477/* Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */6478RTW_INFO("[%s] Got Provisioning Discovery Response Frame\n", __FUNCTION__);6479/* Commented by Albert 20110426 */6480/* The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */6481_cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);6482rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);6483process_p2p_provdisc_resp(pwdinfo, pframe);6484_set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);6485break;64866487}6488}648964906491exit:64926493if (merged_p2pie)6494rtw_mfree(merged_p2pie, merged_p2p_ielen + 2);6495#endif /* CONFIG_P2P */6496return _SUCCESS;6497}64986499unsigned int on_action_public_vendor(union recv_frame *precv_frame)6500{6501unsigned int ret = _FAIL;6502u8 *pframe = precv_frame->u.hdr.rx_data;6503u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);65046505if (_rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE) {6506if (rtw_action_public_decache(precv_frame, 7) == _FAIL)6507goto exit;65086509if (!hal_chk_wl_func(precv_frame->u.hdr.adapter, WL_FUNC_MIRACAST))6510rtw_rframe_del_wfd_ie(precv_frame, 8);65116512ret = on_action_public_p2p(precv_frame);6513}65146515exit:6516return ret;6517}65186519unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)6520{6521unsigned int ret = _FAIL;6522u8 *pframe = precv_frame->u.hdr.rx_data;6523u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);6524u8 token;6525_adapter *adapter = precv_frame->u.hdr.adapter;6526int cnt = 0;6527char msg[64];65286529token = frame_body[2];65306531if (rtw_action_public_decache(precv_frame, 2) == _FAIL)6532goto exit;65336534#ifdef CONFIG_IOCTL_CFG802116535cnt += sprintf((msg + cnt), "%s(token:%u)", action_public_str(action), token);6536rtw_cfg80211_rx_action(adapter, precv_frame, msg);6537#endif65386539ret = _SUCCESS;65406541exit:6542return ret;6543}65446545unsigned int on_action_public(_adapter *padapter, union recv_frame *precv_frame)6546{6547unsigned int ret = _FAIL;6548u8 *pframe = precv_frame->u.hdr.rx_data;6549uint frame_len = precv_frame->u.hdr.len;6550u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);6551u8 category, action;65526553/* check RA matches or not */6554if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))6555goto exit;65566557category = frame_body[0];6558if (category != RTW_WLAN_CATEGORY_PUBLIC)6559goto exit;65606561action = frame_body[1];6562switch (action) {6563case ACT_PUBLIC_BSSCOEXIST:6564#ifdef CONFIG_80211N_HT6565#ifdef CONFIG_AP_MODE6566/*20/40 BSS Coexistence Management frame is a Public Action frame*/6567if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)6568rtw_process_public_act_bsscoex(padapter, pframe, frame_len);6569#endif /*CONFIG_AP_MODE*/6570#endif /*CONFIG_80211N_HT*/6571break;6572case ACT_PUBLIC_VENDOR:6573ret = on_action_public_vendor(precv_frame);6574break;6575default:6576ret = on_action_public_default(precv_frame, action);6577break;6578}65796580exit:6581return ret;6582}65836584#if defined(CONFIG_RTW_WNM) || defined(CONFIG_RTW_80211K)6585static u8 rtw_wnm_nb_elem_parsing(6586u8* pdata, u32 data_len, u8 from_btm,6587u32 *nb_rpt_num, u8 *nb_rpt_is_same,6588struct roam_nb_info *pnb, struct wnm_btm_cant *pcandidates)6589{6590u8 bfound = _FALSE, ret = _SUCCESS;6591u8 *ptr, *pend, *op;6592u32 elem_len, subelem_len, op_len;6593u32 i, nb_rpt_entries = 0;6594struct nb_rpt_hdr *pie;6595struct wnm_btm_cant *pcandidate;65966597if ((!pdata) || (!pnb))6598return _FAIL;65996600if ((from_btm) && (!pcandidates))6601return _FAIL;66026603ptr = pdata;6604pend = ptr + data_len;6605elem_len = data_len;6606subelem_len = (u32)*(pdata+1);66076608for (i=0; i < RTW_MAX_NB_RPT_NUM; i++) {6609if (((ptr + 7) > pend) || (elem_len < subelem_len))6610break;66116612if (*ptr != 0x34) {6613RTW_ERR("WNM: invalid data(0x%2x)!\n", *ptr);6614ret = _FAIL;6615break;6616}66176618pie = (struct nb_rpt_hdr *)ptr;6619if (from_btm) {6620op = rtw_get_ie((u8 *)(ptr+15),6621WNM_BTM_CAND_PREF_SUBEID,6622&op_len, (subelem_len - 15));6623}66246625ptr = (u8 *)(ptr + subelem_len + 2);6626elem_len -= (subelem_len +2);6627subelem_len = *(ptr+1);6628if (from_btm) {6629pcandidate = (pcandidates + i);6630_rtw_memcpy(&pcandidate->nb_rpt, pie, sizeof(struct nb_rpt_hdr));6631if (op && (op_len !=0)) {6632pcandidate->preference = *(op + 2);6633bfound = _TRUE;6634} else6635pcandidate->preference = 0;66366637RTW_DBG("WNM: preference check bssid("MAC_FMT6638") ,bss_info(0x%04X), reg_class(0x%02X), ch(%d),"6639" phy_type(0x%02X), preference(0x%02X)\n",6640MAC_ARG(pcandidate->nb_rpt.bssid), pcandidate->nb_rpt.bss_info,6641pcandidate->nb_rpt.reg_class, pcandidate->nb_rpt.ch_num,6642pcandidate->nb_rpt.phy_type, pcandidate->preference);6643} else {6644if (_rtw_memcmp(&pnb->nb_rpt[i], pie, sizeof(struct nb_rpt_hdr)) == _FALSE)6645*nb_rpt_is_same = _FALSE;6646_rtw_memcpy(&pnb->nb_rpt[i], pie, sizeof(struct nb_rpt_hdr));6647}6648nb_rpt_entries++;6649}66506651if (from_btm)6652pnb->preference_en = (bfound)?_TRUE:_FALSE;66536654*nb_rpt_num = nb_rpt_entries;6655return ret;6656}66576658/* selection sorting based on preference value6659* : nb_rpt_entries - candidate num6660* / : pcandidates - candidate list6661* return : TRUE - means pcandidates is updated.6662*/6663static u8 rtw_wnm_candidates_sorting(6664u32 nb_rpt_entries, struct wnm_btm_cant *pcandidates)6665{6666u8 updated = _FALSE;6667u32 i, j, pos;6668struct wnm_btm_cant swap;6669struct wnm_btm_cant *pcant_1, *pcant_2;66706671if ((!nb_rpt_entries) || (!pcandidates))6672return updated;66736674for (i=0; i < (nb_rpt_entries - 1); i++) {6675pos = i;6676for (j=(i + 1); j < nb_rpt_entries; j++) {6677pcant_1 = pcandidates+pos;6678pcant_2 = pcandidates+j;6679if ((pcant_1->preference) < (pcant_2->preference))6680pos = j;6681}66826683if (pos != i) {6684updated = _TRUE;6685_rtw_memcpy(&swap, (pcandidates+i), sizeof(struct wnm_btm_cant));6686_rtw_memcpy((pcandidates+i), (pcandidates+pos), sizeof(struct wnm_btm_cant));6687_rtw_memcpy((pcandidates+pos), &swap, sizeof(struct wnm_btm_cant));6688}6689}6690return updated;6691}66926693static void rtw_wnm_nb_info_update(6694u32 nb_rpt_entries, u8 from_btm,6695struct roam_nb_info *pnb, struct wnm_btm_cant *pcandidates,6696u8 *nb_rpt_is_same)6697{6698u8 is_found;6699u32 i, j;6700struct wnm_btm_cant *pcand;67016702if (!pnb)6703return;67046705pnb->nb_rpt_ch_list_num = 0;6706for (i=0; i<nb_rpt_entries; i++) {6707is_found = _FALSE;6708if (from_btm) {6709pcand = (pcandidates+i);6710if (_rtw_memcmp(&pnb->nb_rpt[i], &pcand->nb_rpt,6711sizeof(struct nb_rpt_hdr)) == _FALSE)6712*nb_rpt_is_same = _FALSE;6713_rtw_memcpy(&pnb->nb_rpt[i], &pcand->nb_rpt, sizeof(struct nb_rpt_hdr));6714}67156716RTW_DBG("WNM: bssid(" MAC_FMT6717") , bss_info(0x%04X), reg_class(0x%02X), ch_num(%d), phy_type(0x%02X)\n",6718MAC_ARG(pnb->nb_rpt[i].bssid), pnb->nb_rpt[i].bss_info,6719pnb->nb_rpt[i].reg_class, pnb->nb_rpt[i].ch_num,6720pnb->nb_rpt[i].phy_type);67216722if (pnb->nb_rpt[i].ch_num == 0)6723continue;67246725for (j=0; j<nb_rpt_entries; j++) {6726if (pnb->nb_rpt[i].ch_num == pnb->nb_rpt_ch_list[j].hw_value) {6727is_found = _TRUE;6728break;6729}6730}67316732if (!is_found) {6733pnb->nb_rpt_ch_list[pnb->nb_rpt_ch_list_num].hw_value = pnb->nb_rpt[i].ch_num;6734pnb->nb_rpt_ch_list_num++;6735}6736}6737}67386739static void rtw_wnm_btm_candidate_select(_adapter *padapter)6740{6741struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);6742struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info);6743struct wlan_network *pnetwork;6744u8 bfound = _FALSE;6745u32 i;67466747for (i = 0; i < pnb->last_nb_rpt_entries; i++) {6748pnetwork = rtw_find_network(6749&(pmlmepriv->scanned_queue),6750pnb->nb_rpt[i].bssid);67516752if (pnetwork) {6753bfound = _TRUE;6754break;6755}6756}67576758if (bfound) {6759_rtw_memcpy(pnb->roam_target_addr, pnb->nb_rpt[i].bssid, ETH_ALEN);6760RTW_INFO("WNM : select btm entry(%d) - %s("MAC_FMT", ch%u) rssi:%d\n"6761, i6762, pnetwork->network.Ssid.Ssid6763, MAC_ARG(pnetwork->network.MacAddress)6764, pnetwork->network.Configuration.DSConfig6765, (int)pnetwork->network.Rssi);6766} else6767_rtw_memset(pnb->roam_target_addr,0, ETH_ALEN);6768}67696770u32 rtw_wnm_btm_candidates_survey(6771_adapter *padapter, u8* pframe, u32 elem_len, u8 from_btm)6772{6773struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info);6774struct wnm_btm_cant *pcandidate_list = NULL;6775u8 nb_rpt_is_same = _TRUE;6776u32 ret = _FAIL;6777u32 nb_rpt_entries = 0;67786779if (from_btm) {6780u32 mlen = sizeof(struct wnm_btm_cant) * RTW_MAX_NB_RPT_NUM;6781pcandidate_list = (struct wnm_btm_cant *)rtw_malloc(mlen);6782if (pcandidate_list == NULL)6783goto exit;6784}67856786/*clean the status set last time*/6787_rtw_memset(&pnb->nb_rpt_ch_list, 0, sizeof(pnb->nb_rpt_ch_list));6788pnb->nb_rpt_valid = _FALSE;6789if (!rtw_wnm_nb_elem_parsing(6790pframe, elem_len, from_btm,6791&nb_rpt_entries, &nb_rpt_is_same,6792pnb, pcandidate_list))6793goto exit;67946795if (nb_rpt_entries != 0) {6796if ((from_btm) && (rtw_wnm_btm_preference_cap(padapter)))6797rtw_wnm_candidates_sorting(nb_rpt_entries, pcandidate_list);67986799rtw_wnm_nb_info_update(6800nb_rpt_entries, from_btm,6801pnb, pcandidate_list, &nb_rpt_is_same);6802}68036804RTW_INFO("nb_rpt_is_same = %d, nb_rpt_entries = %d, last_nb_rpt_entries = %d\n",6805nb_rpt_is_same, nb_rpt_entries, pnb->last_nb_rpt_entries);6806if ((nb_rpt_is_same == _TRUE) && (nb_rpt_entries == pnb->last_nb_rpt_entries))6807pnb->nb_rpt_is_same = _TRUE;6808else {6809pnb->nb_rpt_is_same = _FALSE;6810pnb->last_nb_rpt_entries = nb_rpt_entries;6811}68126813if ((from_btm) && (nb_rpt_entries != 0))6814rtw_wnm_btm_candidate_select(padapter);68156816pnb->nb_rpt_valid = _TRUE;6817ret = _SUCCESS;68186819exit:6820if (from_btm && pcandidate_list)6821rtw_mfree((u8 *)pcandidate_list, sizeof(struct wnm_btm_cant) * RTW_MAX_NB_RPT_NUM);68226823return ret;6824}6825#endif68266827unsigned int OnAction_ft(_adapter *padapter, union recv_frame *precv_frame)6828{6829#ifdef CONFIG_RTW_80211R6830u32 ret = _FAIL;6831u32 frame_len = 0;6832u8 action_code = 0;6833u8 category = 0;6834u8 *pframe = NULL;6835u8 *pframe_body = NULL;6836u8 sta_addr[ETH_ALEN] = {0};6837u8 *pie = NULL;6838u32 ft_ie_len = 0;6839u32 status_code = 0;6840struct mlme_ext_priv *pmlmeext = NULL;6841struct mlme_ext_info *pmlmeinfo = NULL;6842struct mlme_priv *pmlmepriv = NULL;6843struct wlan_network *proam_target = NULL;6844struct ft_roam_info *pft_roam = NULL;6845_irqL irqL;68466847pmlmeext = &(padapter->mlmeextpriv);6848pmlmeinfo = &(pmlmeext->mlmext_info);6849pmlmepriv = &(padapter->mlmepriv);6850pft_roam = &(pmlmepriv->ft_roam);6851pframe = precv_frame->u.hdr.rx_data;6852frame_len = precv_frame->u.hdr.len;6853pframe_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);6854category = pframe_body[0];68556856if (category != RTW_WLAN_CATEGORY_FT)6857goto exit;68586859action_code = pframe_body[1];6860switch (action_code) {6861case RTW_WLAN_ACTION_FT_RSP:6862RTW_INFO("FT: RTW_WLAN_ACTION_FT_RSP recv.\n");6863if (!_rtw_memcmp(adapter_mac_addr(padapter), &pframe_body[2], ETH_ALEN)) {6864RTW_ERR("FT: Unmatched STA MAC Address "MAC_FMT"\n", MAC_ARG(&pframe_body[2]));6865goto exit;6866}68676868status_code = le16_to_cpu(*(u16 *)((SIZE_PTR)pframe + sizeof(struct rtw_ieee80211_hdr_3addr) + 14));6869if (status_code != 0) {6870RTW_ERR("FT: WLAN ACTION FT RESPONSE fail, status: %d\n", status_code);6871goto exit;6872}68736874if (is_zero_mac_addr(&pframe_body[8]) || is_broadcast_mac_addr(&pframe_body[8])) {6875RTW_ERR("FT: Invalid Target MAC Address "MAC_FMT"\n", MAC_ARG(padapter->mlmepriv.roam_tgt_addr));6876goto exit;6877}68786879pie = rtw_get_ie(pframe_body, _MDIE_, &ft_ie_len, frame_len);6880if (pie) {6881if (!_rtw_memcmp(&pft_roam->mdid, pie+2, 2)) {6882RTW_ERR("FT: Invalid MDID\n");6883goto exit;6884}6885}68866887rtw_ft_set_status(padapter, RTW_FT_REQUESTED_STA);6888_cancel_timer_ex(&pmlmeext->ft_link_timer);68896890/*Disconnect current AP*/6891receive_disconnect(padapter, pmlmepriv->cur_network.network.MacAddress, WLAN_REASON_ACTIVE_ROAM, _FALSE);68926893pft_roam->ft_action_len = frame_len;6894_rtw_memcpy(pft_roam->ft_action, pframe, rtw_min(frame_len, RTW_FT_MAX_IE_SZ));6895ret = _SUCCESS;6896break;6897case RTW_WLAN_ACTION_FT_REQ:6898case RTW_WLAN_ACTION_FT_CONF:6899case RTW_WLAN_ACTION_FT_ACK:6900default:6901RTW_ERR("FT: Unsupported FT Action!\n");6902break;6903}69046905exit:6906return ret;6907#else6908return _SUCCESS;6909#endif6910}69116912#ifdef CONFIG_RTW_WNM6913u8 rtw_wmn_btm_rsp_reason_decision(_adapter *padapter, u8* req_mode)6914{6915struct recv_priv *precvpriv = &padapter->recvpriv;6916struct mlme_priv *pmlmepriv = &padapter->mlmepriv;6917u8 reason = 0;69186919if (!rtw_wnm_btm_diff_bss(padapter)) {6920/* Reject - No suitable BSS transition candidates */6921reason = 7;6922goto candidate_remove;6923}69246925#ifdef CONFIG_RTW_80211R6926if (rtw_ft_chk_flags(padapter, RTW_FT_BTM_ROAM)) {6927/* Accept */6928reason = 0;6929goto under_survey;6930}6931#endif69326933if (((*req_mode) & DISASSOC_IMMINENT) == 0) {6934/* Reject - Unspecified reject reason */6935reason = 1;6936goto candidate_remove;6937}69386939if (precvpriv->signal_strength_data.avg_val >= pmlmepriv->roam_rssi_threshold) {6940reason = 1;6941goto candidate_remove;6942}69436944under_survey:6945if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {6946RTW_INFO("%s reject due to _FW_UNDER_SURVEY\n", __func__);6947reason = 1;6948}69496950candidate_remove:6951if (reason !=0)6952rtw_wnm_reset_btm_candidate(&padapter->mlmepriv.nb_info);69536954return reason;6955}69566957static u32 rtw_wnm_btm_candidates_offset_get(u8* pframe)6958{6959u8 *pos = pframe;6960u32 offset = 0;69616962if (!pframe)6963return 0;69646965offset += 7;6966pos += offset;69676968/* BSS Termination Duration check */6969if (wnm_btm_bss_term_inc(pframe)) {6970offset += 12;6971pos += offset;6972}69736974/* Session Information URL check*/6975if (wnm_btm_ess_disassoc_im(pframe)) {6976/*URL length field + URL variable length*/6977offset = 1 + *(pframe + offset);6978pos += offset;6979}69806981offset = (pos - pframe);6982return offset;6983}69846985static void rtw_wnm_btm_req_hdr_parsing(u8* pframe, struct btm_req_hdr *phdr)6986{6987u8 *pos = pframe;6988u32 offset = 0;69896990if (!pframe || !phdr)6991return;69926993_rtw_memset(phdr, 0, sizeof(struct btm_req_hdr));6994phdr->req_mode = wnm_btm_req_mode(pframe);6995phdr->disassoc_timer = wnm_btm_disassoc_timer(pframe);6996phdr->validity_interval = wnm_btm_valid_interval(pframe);6997if (wnm_btm_bss_term_inc(pframe)) {6998_rtw_memcpy(&phdr->term_duration,6999wnm_btm_term_duration_offset(pframe),7000sizeof(struct btm_term_duration));7001}70027003RTW_DBG("WNM: req_mode(%1x), disassoc_timer(%02x), interval(%x)\n",7004phdr->req_mode, phdr->disassoc_timer, phdr->validity_interval);7005if (wnm_btm_bss_term_inc(pframe))7006RTW_INFO("WNM: tsf(%llx), duration(%2x)\n",7007phdr->term_duration.tsf, phdr->term_duration.duration);7008}70097010void rtw_wnm_roam_scan_hdl(void *ctx)7011{7012_adapter *padapter = (_adapter *)ctx;7013struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);70147015if (rtw_is_scan_deny(padapter))7016RTW_INFO("WNM: roam scan would abort by scan_deny!\n");70177018pmlmepriv->need_to_roam = _TRUE;7019rtw_drv_scan_by_self(padapter, RTW_AUTO_SCAN_REASON_ROAM);7020}70217022static void rtw_wnm_roam_scan(_adapter *padapter)7023{7024struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info);70257026if (rtw_is_scan_deny(padapter)) {7027_cancel_timer_ex(&pnb->roam_scan_timer);7028_set_timer(&pnb->roam_scan_timer, 1000);7029} else7030rtw_wnm_roam_scan_hdl((void *)padapter);7031}70327033void rtw_wnm_process_btm_req(_adapter *padapter, u8* pframe, u32 frame_len)7034{7035struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info);7036struct btm_req_hdr req_hdr;7037u8 *ptr, reason;7038u32 elem_len, offset;70397040rtw_wnm_btm_req_hdr_parsing(pframe, &req_hdr);7041offset = rtw_wnm_btm_candidates_offset_get(pframe);7042if ((offset == 0) || ((frame_len - offset) <= 15))7043return;70447045ptr = (pframe + offset);7046elem_len = (frame_len - offset);7047rtw_wnm_btm_candidates_survey(padapter, ptr, elem_len, _TRUE);7048reason = rtw_wmn_btm_rsp_reason_decision(padapter, &pframe[3]);7049rtw_wnm_issue_action(padapter,7050RTW_WLAN_ACTION_WNM_BTM_RSP, reason);70517052if (reason == 0)7053rtw_wnm_roam_scan(padapter);7054}70557056void rtw_wnm_reset_btm_candidate(struct roam_nb_info *pnb)7057{7058pnb->preference_en = _FALSE;7059_rtw_memset(pnb->roam_target_addr, 0, ETH_ALEN);7060}70617062void rtw_wnm_reset_btm_state(_adapter *padapter)7063{7064struct roam_nb_info *pnb = &(padapter->mlmepriv.nb_info);70657066pnb->last_nb_rpt_entries = 0;7067pnb->nb_rpt_is_same = _TRUE;7068pnb->nb_rpt_valid = _FALSE;7069pnb->nb_rpt_ch_list_num = 0;7070rtw_wnm_reset_btm_candidate(pnb);7071_rtw_memset(&pnb->nb_rpt, 0, sizeof(pnb->nb_rpt));7072_rtw_memset(&pnb->nb_rpt_ch_list, 0, sizeof(pnb->nb_rpt_ch_list));7073}70747075void rtw_wnm_issue_action(_adapter *padapter, u8 action, u8 reason)7076{7077struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);7078struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);7079struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);7080struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);7081struct xmit_frame *pmgntframe;7082struct rtw_ieee80211_hdr *pwlanhdr;7083struct pkt_attrib *pattrib;7084u8 category, dialog_token, termination_delay, *pframe;7085u16 *fctrl;70867087if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)7088return ;70897090pattrib = &(pmgntframe->attrib);7091update_mgntframe_attrib(padapter, pattrib);7092_rtw_memset(pmgntframe->buf_addr, 0, (WLANHDR_OFFSET + TXDESC_OFFSET));70937094pframe = (u8 *)(pmgntframe->buf_addr + TXDESC_OFFSET);7095pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;70967097fctrl = &(pwlanhdr->frame_ctl);7098*(fctrl) = 0;70997100_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);7101_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);7102_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);71037104SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);7105pmlmeext->mgnt_seq++;7106set_frame_sub_type(pframe, WIFI_ACTION);71077108pframe += sizeof(struct rtw_ieee80211_hdr_3addr);7109pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);71107111category = RTW_WLAN_CATEGORY_WNM;7112pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));7113pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));71147115switch (action) {7116case RTW_WLAN_ACTION_WNM_BTM_QUERY:7117pframe = rtw_set_fixed_ie(pframe, 1, &(dialog_token), &(pattrib->pktlen));7118pframe = rtw_set_fixed_ie(pframe, 1, &(reason), &(pattrib->pktlen));7119RTW_INFO("WNM: RTW_WLAN_ACTION_WNM_BTM_QUERY sent.\n");7120break;7121case RTW_WLAN_ACTION_WNM_BTM_RSP:7122termination_delay = 0;7123pframe = rtw_set_fixed_ie(pframe, 1, &(dialog_token), &(pattrib->pktlen));7124pframe = rtw_set_fixed_ie(pframe, 1, &(reason), &(pattrib->pktlen));7125pframe = rtw_set_fixed_ie(pframe, 1, &(termination_delay), &(pattrib->pktlen));7126if (!is_zero_mac_addr(pmlmepriv->nb_info.roam_target_addr)) {7127pframe = rtw_set_fixed_ie(pframe, 6,7128pmlmepriv->nb_info.roam_target_addr, &(pattrib->pktlen));7129}7130RTW_INFO("WNM: RTW_WLAN_ACTION_WNM_BTM_RSP sent. reason = %d\n", reason);7131break;7132default:7133goto exit;7134}71357136pattrib->last_txcmdsz = pattrib->pktlen;7137dump_mgntframe(padapter, pmgntframe);71387139exit:7140return;7141}7142#endif71437144unsigned int OnAction_ht(_adapter *padapter, union recv_frame *precv_frame)7145{7146u8 *pframe = precv_frame->u.hdr.rx_data;7147u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);7148u8 category, action;71497150/* check RA matches or not */7151if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))7152goto exit;71537154category = frame_body[0];7155if (category != RTW_WLAN_CATEGORY_HT)7156goto exit;71577158action = frame_body[1];7159switch (action) {7160case RTW_WLAN_ACTION_HT_SM_PS:7161#ifdef CONFIG_80211N_HT7162#ifdef CONFIG_AP_MODE7163if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)7164rtw_process_ht_action_smps(padapter, get_addr2_ptr(pframe), frame_body[2]);7165#endif /*CONFIG_AP_MODE*/7166#endif /*CONFIG_80211N_HT*/7167break;7168case RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING:7169#ifdef CONFIG_BEAMFORMING7170/*RTW_INFO("RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING\n");*/7171rtw_beamforming_get_report_frame(padapter, precv_frame);7172#endif /*CONFIG_BEAMFORMING*/7173break;7174default:7175break;7176}71777178exit:71797180return _SUCCESS;7181}71827183#ifdef CONFIG_IEEE80211W7184unsigned int OnAction_sa_query(_adapter *padapter, union recv_frame *precv_frame)7185{7186u8 *pframe = precv_frame->u.hdr.rx_data;7187struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;7188struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);7189struct sta_info *psta;7190struct sta_priv *pstapriv = &padapter->stapriv;7191struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);7192u16 tid;7193/* Baron */71947195RTW_INFO("OnAction_sa_query\n");71967197switch (pframe[WLAN_HDR_A3_LEN + 1]) {7198case 0: /* SA Query req */7199_rtw_memcpy(&tid, &pframe[WLAN_HDR_A3_LEN + 2], sizeof(u16));7200RTW_INFO("OnAction_sa_query request,action=%d, tid=%04x, pframe=%02x-%02x\n"7201, pframe[WLAN_HDR_A3_LEN + 1], tid, pframe[WLAN_HDR_A3_LEN + 2], pframe[WLAN_HDR_A3_LEN + 3]);7202issue_action_SA_Query(padapter, get_addr2_ptr(pframe), 1, tid, IEEE80211W_RIGHT_KEY);7203break;72047205case 1: /* SA Query rsp */7206psta = rtw_get_stainfo(pstapriv, get_addr2_ptr(pframe));7207if (psta != NULL)7208_cancel_timer_ex(&psta->dot11w_expire_timer);72097210_rtw_memcpy(&tid, &pframe[WLAN_HDR_A3_LEN + 2], sizeof(u16));7211RTW_INFO("OnAction_sa_query response,action=%d, tid=%04x, cancel timer\n", pframe[WLAN_HDR_A3_LEN + 1], tid);7212break;7213default:7214break;7215}7216if (0) {7217int pp;7218printk("pattrib->pktlen = %d =>", pattrib->pkt_len);7219for (pp = 0; pp < pattrib->pkt_len; pp++)7220printk(" %02x ", pframe[pp]);7221printk("\n");7222}72237224return _SUCCESS;7225}7226#endif /* CONFIG_IEEE80211W */72277228unsigned int on_action_rm(_adapter *padapter, union recv_frame *precv_frame)7229{7230#ifdef CONFIG_RTW_80211K7231return rm_on_action(padapter, precv_frame);7232#else7233return _SUCCESS;7234#endif /* CONFIG_RTW_80211K */7235}72367237unsigned int OnAction_wmm(_adapter *padapter, union recv_frame *precv_frame)7238{7239return _SUCCESS;7240}72417242unsigned int OnAction_vht(_adapter *padapter, union recv_frame *precv_frame)7243{7244#ifdef CONFIG_80211AC_VHT7245u8 *pframe = precv_frame->u.hdr.rx_data;7246struct rtw_ieee80211_hdr_3addr *whdr = (struct rtw_ieee80211_hdr_3addr *)pframe;7247u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);7248u8 category, action;7249struct sta_info *psta = NULL;72507251/* check RA matches or not */7252if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))7253goto exit;72547255category = frame_body[0];7256if (category != RTW_WLAN_CATEGORY_VHT)7257goto exit;72587259action = frame_body[1];7260switch (action) {7261case RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING:7262#ifdef CONFIG_BEAMFORMING7263/*RTW_INFO("RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING\n");*/7264rtw_beamforming_get_report_frame(padapter, precv_frame);7265#endif /*CONFIG_BEAMFORMING*/7266break;7267case RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION:7268/* CategoryCode(1) + ActionCode(1) + OpModeNotification(1) */7269/* RTW_INFO("RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION\n"); */7270psta = rtw_get_stainfo(&padapter->stapriv, whdr->addr2);7271if (psta)7272rtw_process_vht_op_mode_notify(padapter, &frame_body[2], psta);7273break;7274case RTW_WLAN_ACTION_VHT_GROUPID_MANAGEMENT:7275#ifdef CONFIG_BEAMFORMING7276#ifdef RTW_BEAMFORMING_VERSION_27277rtw_beamforming_get_vht_gid_mgnt_frame(padapter, precv_frame);7278#endif /* RTW_BEAMFORMING_VERSION_2 */7279#endif /* CONFIG_BEAMFORMING */7280break;7281default:7282break;7283}72847285exit:7286#endif /* CONFIG_80211AC_VHT */72877288return _SUCCESS;7289}72907291unsigned int OnAction_p2p(_adapter *padapter, union recv_frame *precv_frame)7292{7293#ifdef CONFIG_P2P7294u8 *frame_body;7295u8 category, OUI_Subtype, dialogToken = 0;7296u8 *pframe = precv_frame->u.hdr.rx_data;7297uint len = precv_frame->u.hdr.len;7298struct wifidirect_info *pwdinfo = &(padapter->wdinfo);72997300/* check RA matches or not */7301if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))7302return _SUCCESS;73037304frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));73057306category = frame_body[0];7307if (category != RTW_WLAN_CATEGORY_P2P)7308return _SUCCESS;73097310if (cpu_to_be32(*((u32 *)(frame_body + 1))) != P2POUI)7311return _SUCCESS;73127313#ifdef CONFIG_IOCTL_CFG802117314if (adapter_wdev_data(padapter)->p2p_enabled7315&& pwdinfo->driver_interface == DRIVER_CFG802117316) {7317rtw_cfg80211_rx_action_p2p(padapter, precv_frame);7318return _SUCCESS;7319} else7320#endif /* CONFIG_IOCTL_CFG80211 */7321{7322len -= sizeof(struct rtw_ieee80211_hdr_3addr);7323OUI_Subtype = frame_body[5];7324dialogToken = frame_body[6];73257326switch (OUI_Subtype) {7327case P2P_NOTICE_OF_ABSENCE:73287329break;73307331case P2P_PRESENCE_REQUEST:73327333process_p2p_presence_req(pwdinfo, pframe, len);73347335break;73367337case P2P_PRESENCE_RESPONSE:73387339break;73407341case P2P_GO_DISC_REQUEST:73427343break;73447345default:7346break;73477348}7349}7350#endif /* CONFIG_P2P */73517352return _SUCCESS;73537354}73557356unsigned int OnAction(_adapter *padapter, union recv_frame *precv_frame)7357{7358int i;7359unsigned char category;7360struct action_handler *ptable;7361unsigned char *frame_body;7362u8 *pframe = precv_frame->u.hdr.rx_data;73637364frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));73657366category = frame_body[0];73677368for (i = 0; i < sizeof(OnAction_tbl) / sizeof(struct action_handler); i++) {7369ptable = &OnAction_tbl[i];73707371if (category == ptable->num)7372ptable->func(padapter, precv_frame);73737374}73757376return _SUCCESS;73777378}73797380unsigned int DoReserved(_adapter *padapter, union recv_frame *precv_frame)7381{73827383/* RTW_INFO("rcvd mgt frame(%x, %x)\n", (get_frame_sub_type(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe)); */7384return _SUCCESS;7385}73867387struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)7388{7389struct xmit_frame *pmgntframe;7390struct xmit_buf *pxmitbuf;73917392if (once)7393pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);7394else7395pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);73967397if (pmgntframe == NULL) {7398RTW_INFO(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once);7399goto exit;7400}74017402pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);7403if (pxmitbuf == NULL) {7404RTW_INFO(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter));7405rtw_free_xmitframe(pxmitpriv, pmgntframe);7406pmgntframe = NULL;7407goto exit;7408}74097410pmgntframe->frame_tag = MGNT_FRAMETAG;7411pmgntframe->pxmitbuf = pxmitbuf;7412pmgntframe->buf_addr = pxmitbuf->pbuf;7413pxmitbuf->priv_data = pmgntframe;74147415exit:7416return pmgntframe;74177418}74197420inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)7421{7422return _alloc_mgtxmitframe(pxmitpriv, _FALSE);7423}74247425inline struct xmit_frame *alloc_mgtxmitframe_once(struct xmit_priv *pxmitpriv)7426{7427return _alloc_mgtxmitframe(pxmitpriv, _TRUE);7428}742974307431/****************************************************************************74327433Following are some TX fuctions for WiFi MLME74347435*****************************************************************************/74367437void update_mgnt_tx_rate(_adapter *padapter, u8 rate)7438{7439struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);74407441pmlmeext->tx_rate = rate;7442/* RTW_INFO("%s(): rate = %x\n",__FUNCTION__, rate); */7443}744474457446void update_monitor_frame_attrib(_adapter *padapter, struct pkt_attrib *pattrib)7447{7448HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);7449u8 wireless_mode;7450struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);7451struct xmit_priv *pxmitpriv = &padapter->xmitpriv;7452struct sta_info *psta = NULL;7453struct sta_priv *pstapriv = &padapter->stapriv;74547455psta = rtw_get_stainfo(pstapriv, pattrib->ra);74567457pattrib->hdrlen = 24;7458pattrib->nr_frags = 1;7459pattrib->priority = 7;7460pattrib->mac_id = RTW_DEFAULT_MGMT_MACID;7461pattrib->qsel = QSLT_MGNT;74627463pattrib->pktlen = 0;74647465if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)7466wireless_mode = WIRELESS_11B;7467else7468wireless_mode = WIRELESS_11G;74697470pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode);7471#ifdef CONFIG_80211AC_VHT7472if (pHalData->rf_type == RF_1T1R)7473pattrib->raid = RATEID_IDX_VHT_1SS;7474else if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_2T4R)7475pattrib->raid = RATEID_IDX_VHT_2SS;7476else if (pHalData->rf_type == RF_3T3R)7477pattrib->raid = RATEID_IDX_VHT_3SS;7478else7479pattrib->raid = RATEID_IDX_BGN_40M_1SS;7480#endif74817482#ifdef CONFIG_80211AC_VHT7483pattrib->rate = MGN_VHT1SS_MCS9;7484#else7485pattrib->rate = MGN_MCS7;7486#endif74877488pattrib->encrypt = _NO_PRIVACY_;7489pattrib->bswenc = _FALSE;74907491pattrib->qos_en = _FALSE;7492pattrib->ht_en = 1;7493pattrib->bwmode = CHANNEL_WIDTH_20;7494pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;7495pattrib->sgi = _FALSE;74967497pattrib->seqnum = pmlmeext->mgnt_seq;74987499pattrib->retry_ctrl = _TRUE;75007501pattrib->mbssid = 0;7502pattrib->hw_ssn_sel = pxmitpriv->hw_ssn_seq_no;75037504}750575067507void update_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib)7508{7509u8 wireless_mode;7510struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);7511struct xmit_priv *pxmitpriv = &padapter->xmitpriv;75127513#ifdef CONFIG_P2P_PS_NOA_USE_MACID_SLEEP7514struct wifidirect_info *pwdinfo = &(padapter->wdinfo);7515#endif /* CONFIG_P2P_PS_NOA_USE_MACID_SLEEP */75167517/* _rtw_memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */75187519pattrib->hdrlen = 24;7520pattrib->nr_frags = 1;7521pattrib->priority = 7;7522pattrib->mac_id = RTW_DEFAULT_MGMT_MACID;7523pattrib->qsel = QSLT_MGNT;75247525#ifdef CONFIG_MCC_MODE7526update_mcc_mgntframe_attrib(padapter, pattrib);7527#endif752875297530#ifdef CONFIG_P2P_PS_NOA_USE_MACID_SLEEP7531#ifdef CONFIG_CONCURRENT_MODE7532if (rtw_mi_buddy_check_fwstate(padapter, WIFI_ASOC_STATE))7533#endif /* CONFIG_CONCURRENT_MODE */7534if (MLME_IS_GC(padapter)) {7535if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {7536struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;7537struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);7538WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);7539struct sta_priv *pstapriv = &padapter->stapriv;7540struct sta_info *psta;75417542psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);7543if (psta) {7544/* use macid sleep during NoA, mgmt frame use ac queue & ap macid */7545pattrib->mac_id = psta->cmn.mac_id;7546pattrib->qsel = QSLT_VO;7547} else {7548if (pwdinfo->p2p_ps_state != P2P_PS_DISABLE)7549RTW_ERR("%s , psta was NULL\n", __func__);7550}7551}7552}7553#endif /* CONFIG_P2P_PS_NOA_USE_MACID_SLEEP */755475557556pattrib->pktlen = 0;75577558if (IS_CCK_RATE(pmlmeext->tx_rate))7559wireless_mode = WIRELESS_11B;7560else7561wireless_mode = WIRELESS_11G;7562pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode);7563pattrib->rate = pmlmeext->tx_rate;75647565pattrib->encrypt = _NO_PRIVACY_;7566pattrib->bswenc = _FALSE;75677568pattrib->qos_en = _FALSE;7569pattrib->ht_en = _FALSE;7570pattrib->bwmode = CHANNEL_WIDTH_20;7571pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;7572pattrib->sgi = _FALSE;75737574pattrib->seqnum = pmlmeext->mgnt_seq;75757576pattrib->retry_ctrl = _TRUE;75777578pattrib->mbssid = 0;7579pattrib->hw_ssn_sel = pxmitpriv->hw_ssn_seq_no;7580}75817582void update_mgntframe_attrib_addr(_adapter *padapter, struct xmit_frame *pmgntframe)7583{7584u8 *pframe;7585struct pkt_attrib *pattrib = &pmgntframe->attrib;7586#if defined(CONFIG_BEAMFORMING) || defined(CONFIG_ANTENNA_DIVERSITY)7587struct sta_info *sta = NULL;7588#endif75897590pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;75917592_rtw_memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);7593_rtw_memcpy(pattrib->ta, get_addr2_ptr(pframe), ETH_ALEN);75947595#if defined(CONFIG_BEAMFORMING) || defined(CONFIG_ANTENNA_DIVERSITY)7596sta = pattrib->psta;7597if (!sta) {7598sta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);7599pattrib->psta = sta;7600}7601#ifdef CONFIG_BEAMFORMING7602if (sta)7603update_attrib_txbf_info(padapter, pattrib, sta);7604#endif7605#endif /* defined(CONFIG_BEAMFORMING) || defined(CONFIG_ANTENNA_DIVERSITY) */7606}76077608void dump_mgntframe(_adapter *padapter, struct xmit_frame *pmgntframe)7609{7610if (RTW_CANNOT_RUN(padapter)) {7611rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);7612rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);7613return;7614}76157616rtw_hal_mgnt_xmit(padapter, pmgntframe);7617}76187619s32 dump_mgntframe_and_wait(_adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)7620{7621s32 ret = _FAIL;7622_irqL irqL;7623struct xmit_priv *pxmitpriv = &padapter->xmitpriv;7624struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;7625struct submit_ctx sctx;76267627if (RTW_CANNOT_RUN(padapter)) {7628rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);7629rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);7630return ret;7631}76327633rtw_sctx_init(&sctx, timeout_ms);7634pxmitbuf->sctx = &sctx;76357636ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);76377638if (ret == _SUCCESS)7639ret = rtw_sctx_wait(&sctx, __func__);76407641_enter_critical(&pxmitpriv->lock_sctx, &irqL);7642pxmitbuf->sctx = NULL;7643_exit_critical(&pxmitpriv->lock_sctx, &irqL);76447645return ret;7646}76477648s32 dump_mgntframe_and_wait_ack_timeout(_adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)7649{7650#ifdef CONFIG_XMIT_ACK7651static u8 seq_no = 0;7652s32 ret = _FAIL;7653struct xmit_priv *pxmitpriv = &(GET_PRIMARY_ADAPTER(padapter))->xmitpriv;76547655if (RTW_CANNOT_RUN(padapter)) {7656rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);7657rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);7658return -1;7659}76607661_enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);7662pxmitpriv->ack_tx = _TRUE;7663pxmitpriv->seq_no = seq_no++;7664pmgntframe->ack_report = 1;7665rtw_sctx_init(&(pxmitpriv->ack_tx_ops), timeout_ms);7666if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)7667ret = rtw_sctx_wait(&(pxmitpriv->ack_tx_ops), __func__);76687669pxmitpriv->ack_tx = _FALSE;7670_exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);76717672return ret;7673#else /* !CONFIG_XMIT_ACK */7674dump_mgntframe(padapter, pmgntframe);7675rtw_msleep_os(50);7676return _SUCCESS;7677#endif /* !CONFIG_XMIT_ACK */7678}76797680s32 dump_mgntframe_and_wait_ack(_adapter *padapter, struct xmit_frame *pmgntframe)7681{7682/* In this case, use 500 ms as the default wait_ack timeout */7683return dump_mgntframe_and_wait_ack_timeout(padapter, pmgntframe, 500);7684}768576867687int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)7688{7689u8 *ssid_ie;7690sint ssid_len_ori;7691int len_diff = 0;76927693ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len);76947695/* RTW_INFO("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __FUNCTION__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */76967697if (ssid_ie && ssid_len_ori > 0) {7698switch (hidden_ssid_mode) {7699case 1: {7700u8 *next_ie = ssid_ie + 2 + ssid_len_ori;7701u32 remain_len = 0;77027703remain_len = ies_len - (next_ie - ies);77047705ssid_ie[1] = 0;7706_rtw_memcpy(ssid_ie + 2, next_ie, remain_len);7707len_diff -= ssid_len_ori;77087709break;7710}7711case 2:7712_rtw_memset(&ssid_ie[2], 0, ssid_len_ori);7713break;7714default:7715break;7716}7717}77187719return len_diff;7720}77217722void issue_beacon(_adapter *padapter, int timeout_ms)7723{7724struct xmit_frame *pmgntframe;7725struct pkt_attrib *pattrib;7726unsigned char *pframe;7727struct rtw_ieee80211_hdr *pwlanhdr;7728unsigned short *fctrl;7729unsigned int rate_len;7730struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);7731#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)7732_irqL irqL;7733struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);7734#endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */7735struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);7736struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);7737WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);7738u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};7739#ifdef CONFIG_P2P7740struct wifidirect_info *pwdinfo = &(padapter->wdinfo);7741#endif /* CONFIG_P2P */774277437744/* RTW_INFO("%s\n", __FUNCTION__); */77457746#ifdef CONFIG_BCN_ICF7747pmgntframe = rtw_alloc_bcnxmitframe(pxmitpriv);7748if (pmgntframe == NULL)7749#else7750pmgntframe = alloc_mgtxmitframe(pxmitpriv);7751if (pmgntframe == NULL)7752#endif7753{7754RTW_INFO("%s, alloc mgnt frame fail\n", __FUNCTION__);7755return;7756}7757#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)7758_enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);7759#endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */77607761/* update attribute */7762pattrib = &pmgntframe->attrib;7763update_mgntframe_attrib(padapter, pattrib);7764pattrib->qsel = QSLT_BEACON;77657766#if defined(CONFIG_CONCURRENT_MODE) && (!defined(CONFIG_SWTIMER_BASED_TXBCN))7767if (padapter->hw_port == HW_PORT1)7768pattrib->mbssid = 1;7769#endif7770#ifdef CONFIG_FW_HANDLE_TXBCN7771if (padapter->vap_id != CONFIG_LIMITED_AP_NUM)7772pattrib->mbssid = padapter->vap_id;7773#endif77747775_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);77767777pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;7778pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;777977807781fctrl = &(pwlanhdr->frame_ctl);7782*(fctrl) = 0;77837784_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);7785_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);7786_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);77877788SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);7789/* pmlmeext->mgnt_seq++; */7790set_frame_sub_type(pframe, WIFI_BEACON);77917792pframe += sizeof(struct rtw_ieee80211_hdr_3addr);7793pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);77947795if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {7796/* RTW_INFO("ie len=%d\n", cur_network->IELength); */7797#ifdef CONFIG_P2P7798/* for P2P : Primary Device Type & Device Name */7799u32 wpsielen = 0, insert_len = 0;7800u8 *wpsie = NULL;7801wpsie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wpsielen);78027803if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) {7804uint wps_offset, remainder_ielen;7805u8 *premainder_ie, *pframe_wscie;78067807wps_offset = (uint)(wpsie - cur_network->IEs);78087809premainder_ie = wpsie + wpsielen;78107811remainder_ielen = cur_network->IELength - wps_offset - wpsielen;78127813#ifdef CONFIG_IOCTL_CFG802117814if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {7815if (pmlmepriv->wps_beacon_ie && pmlmepriv->wps_beacon_ie_len > 0) {7816_rtw_memcpy(pframe, cur_network->IEs, wps_offset);7817pframe += wps_offset;7818pattrib->pktlen += wps_offset;78197820_rtw_memcpy(pframe, pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);7821pframe += pmlmepriv->wps_beacon_ie_len;7822pattrib->pktlen += pmlmepriv->wps_beacon_ie_len;78237824/* copy remainder_ie to pframe */7825_rtw_memcpy(pframe, premainder_ie, remainder_ielen);7826pframe += remainder_ielen;7827pattrib->pktlen += remainder_ielen;7828} else {7829_rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);7830pframe += cur_network->IELength;7831pattrib->pktlen += cur_network->IELength;7832}7833} else7834#endif /* CONFIG_IOCTL_CFG80211 */7835{7836pframe_wscie = pframe + wps_offset;7837_rtw_memcpy(pframe, cur_network->IEs, wps_offset + wpsielen);7838pframe += (wps_offset + wpsielen);7839pattrib->pktlen += (wps_offset + wpsielen);78407841/* now pframe is end of wsc ie, insert Primary Device Type & Device Name */7842/* Primary Device Type */7843/* Type: */7844*(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);7845insert_len += 2;78467847/* Length: */7848*(u16 *)(pframe + insert_len) = cpu_to_be16(0x0008);7849insert_len += 2;78507851/* Value: */7852/* Category ID */7853*(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);7854insert_len += 2;78557856/* OUI */7857*(u32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI);7858insert_len += 4;78597860/* Sub Category ID */7861*(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);7862insert_len += 2;786378647865/* Device Name */7866/* Type: */7867*(u16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);7868insert_len += 2;78697870/* Length: */7871*(u16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len);7872insert_len += 2;78737874/* Value: */7875_rtw_memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len);7876insert_len += pwdinfo->device_name_len;787778787879/* update wsc ie length */7880*(pframe_wscie + 1) = (wpsielen - 2) + insert_len;78817882/* pframe move to end */7883pframe += insert_len;7884pattrib->pktlen += insert_len;78857886/* copy remainder_ie to pframe */7887_rtw_memcpy(pframe, premainder_ie, remainder_ielen);7888pframe += remainder_ielen;7889pattrib->pktlen += remainder_ielen;7890}7891} else7892#endif /* CONFIG_P2P */7893{7894int len_diff;7895_rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);7896len_diff = update_hidden_ssid(7897pframe + _BEACON_IE_OFFSET_7898, cur_network->IELength - _BEACON_IE_OFFSET_7899, pmlmeinfo->hidden_ssid_mode7900);7901pframe += (cur_network->IELength + len_diff);7902pattrib->pktlen += (cur_network->IELength + len_diff);7903}79047905{7906u8 *wps_ie;7907uint wps_ielen;7908u8 sr = 0;7909wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_,7910pattrib->pktlen - sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_, NULL, &wps_ielen);7911if (wps_ie && wps_ielen > 0)7912rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);7913if (sr != 0)7914set_fwstate(pmlmepriv, WIFI_UNDER_WPS);7915else7916_clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);7917}79187919#ifdef CONFIG_RTW_80211K7920pframe = rtw_set_ie(pframe, _EID_RRM_EN_CAP_IE_,7921sizeof(padapter->rmpriv.rm_en_cap_def),7922padapter->rmpriv.rm_en_cap_def, &pattrib->pktlen);7923#endif79247925#ifdef CONFIG_P2P7926if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {7927u32 len;7928#ifdef CONFIG_IOCTL_CFG802117929if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {7930len = pmlmepriv->p2p_beacon_ie_len;7931if (pmlmepriv->p2p_beacon_ie && len > 0)7932_rtw_memcpy(pframe, pmlmepriv->p2p_beacon_ie, len);7933} else7934#endif /* CONFIG_IOCTL_CFG80211 */7935{7936len = build_beacon_p2p_ie(pwdinfo, pframe);7937}79387939pframe += len;7940pattrib->pktlen += len;79417942#ifdef CONFIG_MCC_MODE7943pframe = rtw_hal_mcc_append_go_p2p_ie(padapter, pframe, &pattrib->pktlen);7944#endif /* CONFIG_MCC_MODE*/79457946#ifdef CONFIG_WFD7947len = rtw_append_beacon_wfd_ie(padapter, pframe);7948pframe += len;7949pattrib->pktlen += len;7950#endif7951}7952#endif /* CONFIG_P2P */7953#ifdef CONFIG_RTW_REPEATER_SON7954rtw_rson_append_ie(padapter, pframe, &pattrib->pktlen);7955#endif7956#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE7957pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_BEACON_VENDOR_IE_BIT);7958#endif79597960#ifdef CONFIG_RTL8812A7961pframe = rtw_hal_set_8812a_vendor_ie(padapter, pframe, &pattrib->pktlen );7962#endif/*CONFIG_RTL8812A*/79637964goto _issue_bcn;79657966}79677968/* below for ad-hoc mode */79697970/* timestamp will be inserted by hardware */7971pframe += 8;7972pattrib->pktlen += 8;79737974/* beacon interval: 2 bytes */79757976_rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);79777978pframe += 2;7979pattrib->pktlen += 2;79807981/* capability info: 2 bytes */79827983_rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);79847985pframe += 2;7986pattrib->pktlen += 2;79877988/* SSID */7989pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);79907991/* supported rates... */7992rate_len = rtw_get_rateset_len(cur_network->SupportedRates);7993pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);79947995/* DS parameter set */7996pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);79977998/* if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */7999{8000u8 erpinfo = 0;8001u32 ATIMWindow;8002/* IBSS Parameter Set... */8003/* ATIMWindow = cur->Configuration.ATIMWindow; */8004ATIMWindow = 0;8005pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);80068007/* ERP IE */8008pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);8009}801080118012/* EXTERNDED SUPPORTED RATE */8013if (rate_len > 8)8014pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);801580168017/* todo:HT for adhoc */80188019_issue_bcn:80208021#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)8022pmlmepriv->update_bcn = _FALSE;80238024_exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);8025#endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */80268027if ((pattrib->pktlen + TXDESC_SIZE) > MAX_BEACON_LEN) {8028RTW_ERR("beacon frame too large ,len(%d,%d)\n",8029(pattrib->pktlen + TXDESC_SIZE), MAX_BEACON_LEN);8030rtw_warn_on(1);8031return;8032}80338034pattrib->last_txcmdsz = pattrib->pktlen;80358036/* RTW_INFO("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */8037if (timeout_ms > 0)8038dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);8039else8040dump_mgntframe(padapter, pmgntframe);80418042}80438044void issue_probersp(_adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)8045{8046struct xmit_frame *pmgntframe;8047struct pkt_attrib *pattrib;8048unsigned char *pframe;8049struct rtw_ieee80211_hdr *pwlanhdr;8050unsigned short *fctrl;8051unsigned char *mac, *bssid;8052struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);8053#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)8054u8 *pwps_ie;8055uint wps_ielen;8056struct mlme_priv *pmlmepriv = &padapter->mlmepriv;8057#endif /* #if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME) */8058struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);8059struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);8060WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);8061unsigned int rate_len;8062#ifdef CONFIG_P2P8063struct wifidirect_info *pwdinfo = &(padapter->wdinfo);8064#endif /* CONFIG_P2P */80658066/* RTW_INFO("%s\n", __FUNCTION__); */80678068if (da == NULL)8069return;80708071if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))8072return;80738074pmgntframe = alloc_mgtxmitframe(pxmitpriv);8075if (pmgntframe == NULL) {8076RTW_INFO("%s, alloc mgnt frame fail\n", __FUNCTION__);8077return;8078}807980808081/* update attribute */8082pattrib = &pmgntframe->attrib;8083update_mgntframe_attrib(padapter, pattrib);80848085_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);80868087pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;8088pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;80898090mac = adapter_mac_addr(padapter);8091bssid = cur_network->MacAddress;80928093fctrl = &(pwlanhdr->frame_ctl);8094*(fctrl) = 0;8095_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);8096_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);8097_rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);80988099SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);8100pmlmeext->mgnt_seq++;8101set_frame_sub_type(fctrl, WIFI_PROBERSP);81028103pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);8104pattrib->pktlen = pattrib->hdrlen;8105pframe += pattrib->hdrlen;810681078108if (cur_network->IELength > MAX_IE_SZ)8109return;81108111#if defined(CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)8112if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {8113pwps_ie = rtw_get_wps_ie(cur_network->IEs + _FIXED_IE_LENGTH_, cur_network->IELength - _FIXED_IE_LENGTH_, NULL, &wps_ielen);81148115/* inerset & update wps_probe_resp_ie */8116if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {8117uint wps_offset, remainder_ielen;8118u8 *premainder_ie;81198120wps_offset = (uint)(pwps_ie - cur_network->IEs);81218122premainder_ie = pwps_ie + wps_ielen;81238124remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;81258126_rtw_memcpy(pframe, cur_network->IEs, wps_offset);8127pframe += wps_offset;8128pattrib->pktlen += wps_offset;81298130wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */8131if ((wps_offset + wps_ielen + 2) <= MAX_IE_SZ) {8132_rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen + 2);8133pframe += wps_ielen + 2;8134pattrib->pktlen += wps_ielen + 2;8135}81368137if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) {8138_rtw_memcpy(pframe, premainder_ie, remainder_ielen);8139pframe += remainder_ielen;8140pattrib->pktlen += remainder_ielen;8141}8142} else {8143_rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);8144pframe += cur_network->IELength;8145pattrib->pktlen += cur_network->IELength;8146}81478148/* retrieve SSID IE from cur_network->Ssid */8149{8150u8 *ssid_ie;8151sint ssid_ielen;8152sint ssid_ielen_diff;8153u8 buf[MAX_IE_SZ];8154u8 *ies = pmgntframe->buf_addr + TXDESC_OFFSET + sizeof(struct rtw_ieee80211_hdr_3addr);81558156ssid_ie = rtw_get_ie(ies + _FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,8157(pframe - ies) - _FIXED_IE_LENGTH_);81588159ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;81608161if (ssid_ie && cur_network->Ssid.SsidLength) {8162uint remainder_ielen;8163u8 *remainder_ie;8164remainder_ie = ssid_ie + 2;8165remainder_ielen = (pframe - remainder_ie);81668167if (remainder_ielen > MAX_IE_SZ) {8168RTW_WARN(FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));8169remainder_ielen = MAX_IE_SZ;8170}81718172_rtw_memcpy(buf, remainder_ie, remainder_ielen);8173_rtw_memcpy(remainder_ie + ssid_ielen_diff, buf, remainder_ielen);8174*(ssid_ie + 1) = cur_network->Ssid.SsidLength;8175_rtw_memcpy(ssid_ie + 2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);81768177pframe += ssid_ielen_diff;8178pattrib->pktlen += ssid_ielen_diff;8179}8180}8181#ifdef CONFIG_RTW_REPEATER_SON8182rtw_rson_append_ie(padapter, pframe, &pattrib->pktlen);8183#endif8184#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE8185pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_PROBERESP_VENDOR_IE_BIT);8186#endif8187} else8188#endif8189{81908191/* timestamp will be inserted by hardware */8192pframe += 8;8193pattrib->pktlen += 8;81948195/* beacon interval: 2 bytes */81968197_rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);81988199pframe += 2;8200pattrib->pktlen += 2;82018202/* capability info: 2 bytes */82038204_rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);82058206pframe += 2;8207pattrib->pktlen += 2;82088209/* below for ad-hoc mode */82108211/* SSID */8212pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);82138214/* supported rates... */8215rate_len = rtw_get_rateset_len(cur_network->SupportedRates);8216pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);82178218/* DS parameter set */8219pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);82208221if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {8222u8 erpinfo = 0;8223u32 ATIMWindow;8224/* IBSS Parameter Set... */8225/* ATIMWindow = cur->Configuration.ATIMWindow; */8226ATIMWindow = 0;8227pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);82288229/* ERP IE */8230pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);8231}823282338234/* EXTERNDED SUPPORTED RATE */8235if (rate_len > 8)8236pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);823782388239/* todo:HT for adhoc */82408241}82428243#ifdef CONFIG_RTW_80211K8244pframe = rtw_set_ie(pframe, _EID_RRM_EN_CAP_IE_,8245sizeof(padapter->rmpriv.rm_en_cap_def),8246padapter->rmpriv.rm_en_cap_def, &pattrib->pktlen);8247#endif82488249#ifdef CONFIG_P2P8250if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)8251/* IOT issue, When wifi_spec is not set, send probe_resp with P2P IE even if probe_req has no P2P IE */8252&& (is_valid_p2p_probereq || !padapter->registrypriv.wifi_spec)) {8253u32 len;8254#ifdef CONFIG_IOCTL_CFG802118255if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {8256/* if pwdinfo->role == P2P_ROLE_DEVICE will call issue_probersp_p2p() */8257len = pmlmepriv->p2p_go_probe_resp_ie_len;8258if (pmlmepriv->p2p_go_probe_resp_ie && len > 0)8259_rtw_memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie, len);8260} else8261#endif /* CONFIG_IOCTL_CFG80211 */8262{8263len = build_probe_resp_p2p_ie(pwdinfo, pframe);8264}82658266pframe += len;8267pattrib->pktlen += len;82688269#ifdef CONFIG_MCC_MODE8270pframe = rtw_hal_mcc_append_go_p2p_ie(padapter, pframe, &pattrib->pktlen);8271#endif /* CONFIG_MCC_MODE*/82728273#ifdef CONFIG_WFD8274len = rtw_append_probe_resp_wfd_ie(padapter, pframe);8275pframe += len;8276pattrib->pktlen += len;8277#endif8278}8279#endif /* CONFIG_P2P */828082818282#ifdef CONFIG_AUTO_AP_MODE8283{8284struct sta_info *psta;8285struct sta_priv *pstapriv = &padapter->stapriv;82868287RTW_INFO("(%s)\n", __FUNCTION__);82888289/* check rc station */8290psta = rtw_get_stainfo(pstapriv, da);8291if (psta && psta->isrc && psta->pid > 0) {8292u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A};8293u8 RC_INFO[14] = {0};8294/* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */8295u16 cu_ch = (u16)cur_network->Configuration.DSConfig;82968297RTW_INFO("%s, reply rc(pid=0x%x) device "MAC_FMT" in ch=%d\n", __FUNCTION__,8298psta->pid, MAC_ARG(psta->cmn.mac_addr), cu_ch);82998300/* append vendor specific ie */8301_rtw_memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI));8302_rtw_memcpy(&RC_INFO[4], mac, ETH_ALEN);8303_rtw_memcpy(&RC_INFO[10], (u8 *)&psta->pid, 2);8304_rtw_memcpy(&RC_INFO[12], (u8 *)&cu_ch, 2);83058306pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen);8307}8308}8309#endif /* CONFIG_AUTO_AP_MODE */83108311#ifdef CONFIG_RTL8812A8312pframe = rtw_hal_set_8812a_vendor_ie(padapter, pframe, &pattrib->pktlen);8313#endif/*CONFIG_RTL8812A*/83148315pattrib->last_txcmdsz = pattrib->pktlen;831683178318dump_mgntframe(padapter, pmgntframe);83198320return;83218322}83238324int _issue_probereq(_adapter *padapter, const NDIS_802_11_SSID *pssid, const u8 *da, u8 ch, bool append_wps, int wait_ack)8325{8326int ret = _FAIL;8327struct xmit_frame *pmgntframe;8328struct pkt_attrib *pattrib;8329unsigned char *pframe;8330struct rtw_ieee80211_hdr *pwlanhdr;8331unsigned short *fctrl;8332unsigned char *mac;8333unsigned char bssrate[NumRates];8334struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);8335struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);8336struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);8337int bssrate_len = 0;8338u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};8339#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI8340struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);8341#endif83428343if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))8344goto exit;83458346pmgntframe = alloc_mgtxmitframe(pxmitpriv);8347if (pmgntframe == NULL)8348goto exit;83498350/* update attribute */8351pattrib = &pmgntframe->attrib;8352update_mgntframe_attrib(padapter, pattrib);835383548355_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);83568357pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;8358pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;83598360#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI8361if ((pwdev_priv->pno_mac_addr[0] != 0xFF)8362&& (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE)8363&& (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _FALSE))8364mac = pwdev_priv->pno_mac_addr;8365else8366#endif8367mac = adapter_mac_addr(padapter);83688369fctrl = &(pwlanhdr->frame_ctl);8370*(fctrl) = 0;83718372if (da) {8373/* unicast probe request frame */8374_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);8375_rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);8376} else {8377/* broadcast probe request frame */8378_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);8379_rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);8380}83818382_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);83838384#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI8385if ((pwdev_priv->pno_mac_addr[0] != 0xFF)8386&& (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE)8387&& (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _FALSE)) {8388#ifdef CONFIG_RTW_DEBUG8389RTW_DBG("%s pno_scan_seq_num: %d\n", __func__,8390pwdev_priv->pno_scan_seq_num);8391#endif8392SetSeqNum(pwlanhdr, pwdev_priv->pno_scan_seq_num);8393pattrib->seqnum = pwdev_priv->pno_scan_seq_num;8394pattrib->qos_en = 1;8395pwdev_priv->pno_scan_seq_num++;8396} else8397#endif8398{8399SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);8400pmlmeext->mgnt_seq++;8401}8402set_frame_sub_type(pframe, WIFI_PROBEREQ);84038404pframe += sizeof(struct rtw_ieee80211_hdr_3addr);8405pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);84068407if (pssid && !MLME_IS_MESH(padapter))8408pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));8409else8410pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));84118412get_rate_set(padapter, bssrate, &bssrate_len);84138414if (bssrate_len > 8) {8415pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));8416pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));8417} else8418pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));84198420if (ch)8421pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, &ch, &pattrib->pktlen);84228423#ifdef CONFIG_RTW_MESH8424if (MLME_IS_MESH(padapter)) {8425if (pssid)8426pframe = rtw_set_ie_mesh_id(pframe, &pattrib->pktlen, pssid->Ssid, pssid->SsidLength);8427else8428pframe = rtw_set_ie_mesh_id(pframe, &pattrib->pktlen, NULL, 0);8429}8430#endif84318432if (append_wps) {8433/* add wps_ie for wps2.0 */8434if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {8435_rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);8436pframe += pmlmepriv->wps_probe_req_ie_len;8437pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;8438/* pmlmepriv->wps_probe_req_ie_len = 0 ; */ /* reset to zero */8439}8440}8441#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE8442pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_PROBEREQ_VENDOR_IE_BIT);8443#endif84448445#ifdef CONFIG_RTL8812A8446pframe = rtw_hal_set_8812a_vendor_ie(padapter, pframe, &pattrib->pktlen );8447#endif/*CONFIG_RTL8812A*/844884498450pattrib->last_txcmdsz = pattrib->pktlen;845184528453if (wait_ack)8454ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);8455else {8456dump_mgntframe(padapter, pmgntframe);8457ret = _SUCCESS;8458}84598460exit:8461return ret;8462}84638464inline void issue_probereq(_adapter *padapter, const NDIS_802_11_SSID *pssid, const u8 *da)8465{8466_issue_probereq(padapter, pssid, da, 0, 1, _FALSE);8467}84688469/*8470* wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT8471* 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 TX8472* try_cnt means the maximal TX count to try8473*/8474int issue_probereq_ex(_adapter *padapter, const NDIS_802_11_SSID *pssid, const u8 *da, u8 ch, bool append_wps,8475int try_cnt, int wait_ms)8476{8477int ret = _FAIL;8478int i = 0;8479systime start = rtw_get_current_time();84808481if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))8482goto exit;84838484do {8485ret = _issue_probereq(padapter, pssid, da, ch, append_wps, wait_ms > 0 ? _TRUE : _FALSE);84868487i++;84888489if (RTW_CANNOT_RUN(padapter))8490break;84918492if (i < try_cnt && wait_ms > 0 && ret == _FAIL)8493rtw_msleep_os(wait_ms);84948495} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));84968497if (ret != _FAIL) {8498ret = _SUCCESS;8499#ifndef DBG_XMIT_ACK8500goto exit;8501#endif8502}85038504if (try_cnt && wait_ms) {8505if (da)8506RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",8507FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),8508ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));8509else8510RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",8511FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),8512ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));8513}8514exit:8515return ret;8516}85178518/* if psta == NULL, indiate we are station(client) now... */8519void issue_auth(_adapter *padapter, struct sta_info *psta, unsigned short status)8520{8521struct xmit_frame *pmgntframe;8522struct pkt_attrib *pattrib;8523unsigned char *pframe;8524struct rtw_ieee80211_hdr *pwlanhdr;8525unsigned short *fctrl;8526unsigned int val32;8527unsigned short val16;8528int use_shared_key = 0;8529struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);8530struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);8531struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);85328533if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))8534return;85358536pmgntframe = alloc_mgtxmitframe(pxmitpriv);8537if (pmgntframe == NULL)8538return;85398540/* update attribute */8541pattrib = &pmgntframe->attrib;8542update_mgntframe_attrib(padapter, pattrib);85438544_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);85458546pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;8547pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;85488549fctrl = &(pwlanhdr->frame_ctl);8550*(fctrl) = 0;85518552SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);8553pmlmeext->mgnt_seq++;8554set_frame_sub_type(pframe, WIFI_AUTH);85558556pframe += sizeof(struct rtw_ieee80211_hdr_3addr);8557pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);855885598560if (psta) { /* for AP mode */8561#ifdef CONFIG_NATIVEAP_MLME85628563_rtw_memcpy(pwlanhdr->addr1, psta->cmn.mac_addr, ETH_ALEN);8564_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);8565_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);856685678568/* setting auth algo number */8569val16 = (u16)psta->authalg;85708571if (status != _STATS_SUCCESSFUL_)8572val16 = 0;85738574if (val16) {8575val16 = cpu_to_le16(val16);8576use_shared_key = 1;8577}85788579pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));85808581/* setting auth seq number */8582val16 = (u16)psta->auth_seq;8583val16 = cpu_to_le16(val16);8584pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));85858586/* setting status code... */8587val16 = status;8588val16 = cpu_to_le16(val16);8589pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));85908591/* added challenging text... */8592if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))8593pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));8594#endif8595} else {8596_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);8597_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);8598_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);85998600#ifdef CONFIG_RTW_80211R8601if (rtw_ft_roam(padapter)) {8602/* 2: 802.11R FTAA */8603val16 = cpu_to_le16(2);8604} else8605#endif8606{8607/* setting auth algo number */8608val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0; /* 0:OPEN System, 1:Shared key */8609if (val16) {8610val16 = cpu_to_le16(val16);8611use_shared_key = 1;8612}8613}86148615/* RTW_INFO("%s auth_algo= %s auth_seq=%d\n",__FUNCTION__,(pmlmeinfo->auth_algo==0)?"OPEN":"SHARED",pmlmeinfo->auth_seq); */86168617/* setting IV for auth seq #3 */8618if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {8619/* RTW_INFO("==> iv(%d),key_index(%d)\n",pmlmeinfo->iv,pmlmeinfo->key_index); */8620val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));8621val32 = cpu_to_le32(val32);8622pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&val32, &(pattrib->pktlen));86238624pattrib->iv_len = 4;8625}86268627pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));86288629/* setting auth seq number */8630val16 = pmlmeinfo->auth_seq;8631val16 = cpu_to_le16(val16);8632pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));863386348635/* setting status code... */8636val16 = status;8637val16 = cpu_to_le16(val16);8638pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));86398640#ifdef CONFIG_RTW_80211R8641rtw_ft_build_auth_req_ies(padapter, pattrib, &pframe);8642#endif86438644/* then checking to see if sending challenging text... */8645if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {8646pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));86478648SetPrivacy(fctrl);86498650pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);86518652pattrib->encrypt = _WEP40_;86538654pattrib->icv_len = 4;86558656pattrib->pktlen += pattrib->icv_len;86578658}86598660}86618662pattrib->last_txcmdsz = pattrib->pktlen;86638664rtw_wep_encrypt(padapter, (u8 *)pmgntframe);8665RTW_INFO("%s\n", __FUNCTION__);8666dump_mgntframe(padapter, pmgntframe);86678668return;8669}867086718672void issue_asocrsp(_adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)8673{8674#ifdef CONFIG_AP_MODE8675struct xmit_frame *pmgntframe;8676struct rtw_ieee80211_hdr *pwlanhdr;8677struct pkt_attrib *pattrib;8678unsigned char *pbuf, *pframe;8679unsigned short val, ie_status;8680unsigned short *fctrl;8681struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);8682struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);8683struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;8684struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);8685WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);8686u8 *ie = pnetwork->IEs;8687#ifdef CONFIG_P2P8688struct wifidirect_info *pwdinfo = &(padapter->wdinfo);8689#ifdef CONFIG_WFD8690u32 wfdielen = 0;8691#endif86928693#endif /* CONFIG_P2P */86948695if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))8696return;86978698RTW_INFO("%s\n", __FUNCTION__);86998700pmgntframe = alloc_mgtxmitframe(pxmitpriv);8701if (pmgntframe == NULL)8702return;87038704/* update attribute */8705pattrib = &pmgntframe->attrib;8706update_mgntframe_attrib(padapter, pattrib);870787088709_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);87108711pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;8712pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;87138714fctrl = &(pwlanhdr->frame_ctl);8715*(fctrl) = 0;87168717_rtw_memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->cmn.mac_addr, ETH_ALEN);8718_rtw_memcpy((void *)get_addr2_ptr(pwlanhdr), adapter_mac_addr(padapter), ETH_ALEN);8719_rtw_memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);872087218722SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);8723pmlmeext->mgnt_seq++;8724if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))8725set_frame_sub_type(pwlanhdr, pkt_type);8726else8727return;87288729pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);8730pattrib->pktlen += pattrib->hdrlen;8731pframe += pattrib->hdrlen;87328733/* capability */8734val = *(unsigned short *)rtw_get_capability_from_ie(ie);87358736pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_ , (unsigned char *)&val, &(pattrib->pktlen));87378738ie_status = cpu_to_le16(status);8739pframe = rtw_set_fixed_ie(pframe , _STATUS_CODE_ , (unsigned char *)&ie_status, &(pattrib->pktlen));87408741val = cpu_to_le16(pstat->cmn.aid | BIT(14) | BIT(15));8742pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_ , (unsigned char *)&val, &(pattrib->pktlen));87438744if (pstat->bssratelen <= 8)8745pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));8746else {8747pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));8748pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen - 8), pstat->bssrateset + 8, &(pattrib->pktlen));8749}87508751#ifdef CONFIG_IEEE80211W8752if (status == _STATS_REFUSED_TEMPORARILY_) {8753u8 timeout_itvl[5];8754u32 timeout_interval = 3000;8755/* Association Comeback time */8756timeout_itvl[0] = 0x03;8757timeout_interval = cpu_to_le32(timeout_interval);8758_rtw_memcpy(timeout_itvl + 1, &timeout_interval, 4);8759pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));8760}8761#endif /* CONFIG_IEEE80211W */87628763#ifdef CONFIG_80211N_HT8764if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {8765uint ie_len = 0;87668767/* FILL HT CAP INFO IE */8768/* p = hostapd_eid_ht_capabilities_info(hapd, p); */8769pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));8770if (pbuf && ie_len > 0) {8771_rtw_memcpy(pframe, pbuf, ie_len + 2);8772pframe += (ie_len + 2);8773pattrib->pktlen += (ie_len + 2);8774}87758776/* FILL HT ADD INFO IE */8777/* p = hostapd_eid_ht_operation(hapd, p); */8778pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));8779if (pbuf && ie_len > 0) {8780_rtw_memcpy(pframe, pbuf, ie_len + 2);8781pframe += (ie_len + 2);8782pattrib->pktlen += (ie_len + 2);8783}87848785}8786#endif87878788/*adding EXT_CAPAB_IE */8789if (pmlmepriv->ext_capab_ie_len > 0) {8790uint ie_len = 0;87918792pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_CAP_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));8793if (pbuf && ie_len > 0) {8794_rtw_memcpy(pframe, pbuf, ie_len + 2);8795pframe += (ie_len + 2);8796pattrib->pktlen += (ie_len + 2);8797}8798}87998800#ifdef CONFIG_80211AC_VHT8801if ((pstat->flags & WLAN_STA_VHT) && (pmlmepriv->vhtpriv.vht_option)8802&& (pstat->wpa_pairwise_cipher != WPA_CIPHER_TKIP)8803&& (pstat->wpa2_pairwise_cipher != WPA_CIPHER_TKIP)) {8804u32 ie_len = 0;88058806/* FILL VHT CAP IE */8807pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));8808if (pbuf && ie_len > 0) {8809_rtw_memcpy(pframe, pbuf, ie_len + 2);8810pframe += (ie_len + 2);8811pattrib->pktlen += (ie_len + 2);8812}88138814/* FILL VHT OPERATION IE */8815pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTOperation, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));8816if (pbuf && ie_len > 0) {8817_rtw_memcpy(pframe, pbuf, ie_len + 2);8818pframe += (ie_len + 2);8819pattrib->pktlen += (ie_len + 2);8820}8821}8822#endif /* CONFIG_80211AC_VHT */88238824/* FILL WMM IE */8825if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {8826uint ie_len = 0;8827unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};88288829for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {8830pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));8831if (pbuf && _rtw_memcmp(pbuf + 2, WMM_PARA_IE, 6)) {8832_rtw_memcpy(pframe, pbuf, ie_len + 2);8833pframe += (ie_len + 2);8834pattrib->pktlen += (ie_len + 2);88358836break;8837}88388839if ((pbuf == NULL) || (ie_len == 0))8840break;8841}88428843}884488458846if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)8847pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));88488849/* add WPS IE ie for wps 2.0 */8850if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {8851_rtw_memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);88528853pframe += pmlmepriv->wps_assoc_resp_ie_len;8854pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;8855}88568857#ifdef CONFIG_P2P8858if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device == _TRUE)) {8859u32 len;88608861if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) {8862len = 0;8863if (pmlmepriv->p2p_assoc_resp_ie && pmlmepriv->p2p_assoc_resp_ie_len > 0) {8864len = pmlmepriv->p2p_assoc_resp_ie_len;8865_rtw_memcpy(pframe, pmlmepriv->p2p_assoc_resp_ie, len);8866}8867} else8868len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);8869pframe += len;8870pattrib->pktlen += len;8871}88728873#ifdef CONFIG_WFD8874if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {8875wfdielen = rtw_append_assoc_resp_wfd_ie(padapter, pframe);8876pframe += wfdielen;8877pattrib->pktlen += wfdielen;8878}8879#endif88808881#endif /* CONFIG_P2P */8882#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE8883pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_ASSOCRESP_VENDOR_IE_BIT);8884#endif88858886#ifdef CONFIG_RTL8812A8887pframe = rtw_hal_set_8812a_vendor_ie(padapter, pframe, &pattrib->pktlen );8888#endif/*CONFIG_RTL8812A*/888988908891pattrib->last_txcmdsz = pattrib->pktlen;88928893dump_mgntframe(padapter, pmgntframe);88948895#endif8896}88978898void _issue_assocreq(_adapter *padapter, u8 is_reassoc)8899{8900int ret = _FAIL;8901struct xmit_frame *pmgntframe;8902struct pkt_attrib *pattrib;8903unsigned char *pframe;8904struct rtw_ieee80211_hdr *pwlanhdr;8905unsigned short *fctrl;8906unsigned short val16;8907unsigned int i, j, index = 0;8908unsigned char bssrate[NumRates], sta_bssrate[NumRates];8909PNDIS_802_11_VARIABLE_IEs pIE;8910struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);8911struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);8912struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);8913struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);8914int bssrate_len = 0, sta_bssrate_len = 0;8915u8 vs_ie_length = 0;8916#ifdef CONFIG_P2P8917struct wifidirect_info *pwdinfo = &(padapter->wdinfo);8918u8 p2pie[255] = { 0x00 };8919u16 p2pielen = 0;8920#ifdef CONFIG_WFD8921u32 wfdielen = 0;8922#endif8923#endif /* CONFIG_P2P */89248925#ifdef CONFIG_DFS8926struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);8927u16 cap;89288929/* Dot H */8930u8 pow_cap_ele[2] = { 0x00 };8931u8 sup_ch[30 * 2] = {0x00 }, sup_ch_idx = 0, idx_5g = 2; /* For supported channel */8932#endif /* CONFIG_DFS */89338934if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))8935goto exit;89368937pmgntframe = alloc_mgtxmitframe(pxmitpriv);8938if (pmgntframe == NULL)8939goto exit;89408941/* update attribute */8942pattrib = &pmgntframe->attrib;8943update_mgntframe_attrib(padapter, pattrib);894489458946_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);89478948pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;8949pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;89508951fctrl = &(pwlanhdr->frame_ctl);8952*(fctrl) = 0;8953_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);8954_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);8955_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);89568957SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);8958pmlmeext->mgnt_seq++;8959if (is_reassoc == _TRUE)8960set_frame_sub_type(pframe, WIFI_REASSOCREQ);8961else8962set_frame_sub_type(pframe, WIFI_ASSOCREQ);89638964pframe += sizeof(struct rtw_ieee80211_hdr_3addr);8965pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);89668967/* caps */89688969#ifdef CONFIG_DFS8970_rtw_memcpy(&cap, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);8971cap |= cap_SpecMgmt;8972_rtw_memcpy(pframe, &cap, 2);8973#else8974_rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);8975#endif /* CONFIG_DFS */89768977pframe += 2;8978pattrib->pktlen += 2;89798980/* listen interval */8981/* todo: listen interval for power saving */8982val16 = cpu_to_le16(3);8983_rtw_memcpy(pframe , (unsigned char *)&val16, 2);8984pframe += 2;8985pattrib->pktlen += 2;89868987/*Construct Current AP Field for Reassoc-Req only*/8988if (is_reassoc == _TRUE) {8989_rtw_memcpy(pframe, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);8990pframe += ETH_ALEN;8991pattrib->pktlen += ETH_ALEN;8992}89938994/* SSID */8995pframe = rtw_set_ie(pframe, _SSID_IE_, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));89968997#ifdef CONFIG_DFS8998/* Dot H */8999if (pmlmeext->cur_channel > 14) {9000pow_cap_ele[0] = 13; /* Minimum transmit power capability */9001pow_cap_ele[1] = 21; /* Maximum transmit power capability */9002pframe = rtw_set_ie(pframe, EID_PowerCap, 2, pow_cap_ele, &(pattrib->pktlen));90039004/* supported channels */9005while (sup_ch_idx < rfctl->max_chan_nums && rfctl->channel_set[sup_ch_idx].ChannelNum != 0) {9006if (rfctl->channel_set[sup_ch_idx].ChannelNum <= 14) {9007/* TODO: fix 2.4G supported channel when channel doesn't start from 1 and continuous */9008sup_ch[0] = 1; /* First channel number */9009sup_ch[1] = rfctl->channel_set[sup_ch_idx].ChannelNum; /* Number of channel */9010} else {9011sup_ch[idx_5g++] = rfctl->channel_set[sup_ch_idx].ChannelNum;9012sup_ch[idx_5g++] = 1;9013}9014sup_ch_idx++;9015}9016pframe = rtw_set_ie(pframe, EID_SupportedChannels, idx_5g, sup_ch, &(pattrib->pktlen));9017}9018#endif /* CONFIG_DFS */90199020/* supported rate & extended supported rate */90219022#if 1 /* Check if the AP's supported rates are also supported by STA. */9023get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);9024/* RTW_INFO("sta_bssrate_len=%d\n", sta_bssrate_len); */90259026if (pmlmeext->cur_channel == 14) /* for JAPAN, channel 14 can only uses B Mode(CCK) */9027sta_bssrate_len = 4;902890299030/* for (i = 0; i < sta_bssrate_len; i++) { */9031/* RTW_INFO("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */9032/* } */90339034for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {9035if (pmlmeinfo->network.SupportedRates[i] == 0)9036break;9037RTW_INFO("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);9038}903990409041for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {9042if (pmlmeinfo->network.SupportedRates[i] == 0)9043break;904490459046/* Check if the AP's supported rates are also supported by STA. */9047for (j = 0; j < sta_bssrate_len; j++) {9048/* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */9049if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK)9050== (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) {9051/* RTW_INFO("match i = %d, j=%d\n", i, j); */9052break;9053} else {9054/* RTW_INFO("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)); */9055}9056}90579058if (j == sta_bssrate_len) {9059/* the rate is not supported by STA */9060RTW_INFO("%s(): the rate[%d]=%02X is not supported by STA!\n", __FUNCTION__, i, pmlmeinfo->network.SupportedRates[i]);9061} else {9062/* the rate is supported by STA */9063bssrate[index++] = pmlmeinfo->network.SupportedRates[i];9064}9065}90669067bssrate_len = index;9068RTW_INFO("bssrate_len = %d\n", bssrate_len);90699070#else /* Check if the AP's supported rates are also supported by STA. */9071#if 09072get_rate_set(padapter, bssrate, &bssrate_len);9073#else9074for (bssrate_len = 0; bssrate_len < NumRates; bssrate_len++) {9075if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0)9076break;90779078if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0x2C) /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */9079break;90809081bssrate[bssrate_len] = pmlmeinfo->network.SupportedRates[bssrate_len];9082}9083#endif9084#endif /* Check if the AP's supported rates are also supported by STA. */90859086if ((bssrate_len == 0) && (pmlmeinfo->network.SupportedRates[0] != 0)) {9087rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);9088rtw_free_xmitframe(pxmitpriv, pmgntframe);9089goto exit; /* don't connect to AP if no joint supported rate */9090}909190929093if (bssrate_len > 8) {9094pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));9095pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));9096} else if (bssrate_len > 0)9097pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));9098else9099RTW_INFO("%s: Connect to AP without 11b and 11g data rate!\n", __FUNCTION__);91009101#ifdef CONFIG_RTW_80211K9102if (pmlmeinfo->network.PhyInfo.rm_en_cap[0] /* RM Enabled Capabilities */9103| pmlmeinfo->network.PhyInfo.rm_en_cap[1]9104| pmlmeinfo->network.PhyInfo.rm_en_cap[2]9105| pmlmeinfo->network.PhyInfo.rm_en_cap[3]9106| pmlmeinfo->network.PhyInfo.rm_en_cap[4])9107pframe = rtw_set_ie(pframe, _EID_RRM_EN_CAP_IE_, 5,9108(u8 *)padapter->rmpriv.rm_en_cap_def, &(pattrib->pktlen));9109#endif /* CONFIG_RTW_80211K */91109111/* vendor specific IE, such as WPA, WMM, WPS */9112for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pmlmeinfo->network.IELength;) {9113pIE = (PNDIS_802_11_VARIABLE_IEs)(pmlmeinfo->network.IEs + i);91149115switch (pIE->ElementID) {9116case _VENDOR_SPECIFIC_IE_:9117if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) ||9118(_rtw_memcmp(pIE->data, WMM_OUI, 4)) ||9119(_rtw_memcmp(pIE->data, WPS_OUI, 4))) {9120vs_ie_length = pIE->Length;9121if ((!padapter->registrypriv.wifi_spec) && (_rtw_memcmp(pIE->data, WPS_OUI, 4))) {9122/* Commented by Kurt 20110629 */9123/* In some older APs, WPS handshake */9124/* would be fail if we append vender extensions informations to AP */91259126vs_ie_length = 14;9127}91289129pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, vs_ie_length, pIE->data, &(pattrib->pktlen));9130}9131break;91329133case EID_WPA2:9134#ifdef CONFIG_RTW_80211R9135if ((is_reassoc) && (rtw_ft_roam(padapter))) {9136rtw_ft_update_rsnie(padapter, _TRUE, pattrib, &pframe);9137} else9138#endif9139{9140#ifdef CONFIG_IOCTL_CFG802119141if (rtw_sec_chk_auth_alg(padapter, WLAN_AUTH_OPEN) &&9142rtw_sec_chk_auth_type(padapter, NL80211_AUTHTYPE_SAE)) {9143s32 entry = rtw_cached_pmkid(padapter, pmlmepriv->assoc_bssid);91449145rtw_rsn_sync_pmkid(padapter, (u8 *)pIE, (pIE->Length + 2), entry);9146}9147#endif /* CONFIG_IOCTL_CFG80211 */91489149pframe = rtw_set_ie(pframe, EID_WPA2, pIE->Length, pIE->data, &(pattrib->pktlen));9150}9151break;9152#ifdef CONFIG_80211N_HT9153case EID_HTCapability:9154if (padapter->mlmepriv.htpriv.ht_option == _TRUE) {9155if (!(is_ap_in_tkip(padapter))) {9156_rtw_memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));91579158pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);91599160pframe = rtw_set_ie(pframe, EID_HTCapability, pIE->Length , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));9161}9162}9163break;91649165case EID_EXTCapability:9166if (padapter->mlmepriv.htpriv.ht_option == _TRUE)9167pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));9168break;9169#endif /* CONFIG_80211N_HT */9170#ifdef CONFIG_80211AC_VHT9171case EID_VHTCapability:9172if (padapter->mlmepriv.vhtpriv.vht_option == _TRUE)9173pframe = rtw_set_ie(pframe, EID_VHTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));9174break;91759176case EID_OpModeNotification:9177if (padapter->mlmepriv.vhtpriv.vht_option == _TRUE)9178pframe = rtw_set_ie(pframe, EID_OpModeNotification, pIE->Length, pIE->data, &(pattrib->pktlen));9179break;9180#endif /* CONFIG_80211AC_VHT */9181default:9182break;9183}91849185i += (pIE->Length + 2);9186}91879188if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)9189pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));919091919192#ifdef CONFIG_WAPI_SUPPORT9193rtw_build_assoc_req_wapi_ie(padapter, pframe, pattrib);9194#endif919591969197#ifdef CONFIG_P2P91989199#ifdef CONFIG_IOCTL_CFG802119200if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211) {9201if (pmlmepriv->p2p_assoc_req_ie && pmlmepriv->p2p_assoc_req_ie_len > 0) {9202_rtw_memcpy(pframe, pmlmepriv->p2p_assoc_req_ie, pmlmepriv->p2p_assoc_req_ie_len);9203pframe += pmlmepriv->p2p_assoc_req_ie_len;9204pattrib->pktlen += pmlmepriv->p2p_assoc_req_ie_len;9205}9206} else9207#endif /* CONFIG_IOCTL_CFG80211 */9208{9209if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {9210/* Should add the P2P IE in the association request frame. */9211/* P2P OUI */92129213p2pielen = 0;9214p2pie[p2pielen++] = 0x50;9215p2pie[p2pielen++] = 0x6F;9216p2pie[p2pielen++] = 0x9A;9217p2pie[p2pielen++] = 0x09; /* WFA P2P v1.0 */92189219/* Commented by Albert 20101109 */9220/* According to the P2P Specification, the association request frame should contain 3 P2P attributes */9221/* 1. P2P Capability */9222/* 2. Extended Listen Timing */9223/* 3. Device Info */9224/* Commented by Albert 20110516 */9225/* 4. P2P Interface */92269227/* P2P Capability */9228/* Type: */9229p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;92309231/* Length: */9232*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);9233p2pielen += 2;92349235/* Value: */9236/* Device Capability Bitmap, 1 byte */9237p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;92389239/* Group Capability Bitmap, 1 byte */9240if (pwdinfo->persistent_supported)9241p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;9242else9243p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;92449245/* Extended Listen Timing */9246/* Type: */9247p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;92489249/* Length: */9250*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);9251p2pielen += 2;92529253/* Value: */9254/* Availability Period */9255*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);9256p2pielen += 2;92579258/* Availability Interval */9259*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);9260p2pielen += 2;92619262/* Device Info */9263/* Type: */9264p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;92659266/* Length: */9267/* 21->P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */9268/* + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */9269*(u16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);9270p2pielen += 2;92719272/* Value: */9273/* P2P Device Address */9274_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);9275p2pielen += ETH_ALEN;92769277/* Config Method */9278/* This field should be big endian. Noted by P2P specification. */9279if ((pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||9280(pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))9281*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);9282else9283*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC);92849285p2pielen += 2;92869287/* Primary Device Type */9288/* Category ID */9289*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);9290p2pielen += 2;92919292/* OUI */9293*(u32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);9294p2pielen += 4;92959296/* Sub Category ID */9297*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);9298p2pielen += 2;92999300/* Number of Secondary Device Types */9301p2pie[p2pielen++] = 0x00; /* No Secondary Device Type List */93029303/* Device Name */9304/* Type: */9305*(u16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);9306p2pielen += 2;93079308/* Length: */9309*(u16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);9310p2pielen += 2;93119312/* Value: */9313_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);9314p2pielen += pwdinfo->device_name_len;93159316/* P2P Interface */9317/* Type: */9318p2pie[p2pielen++] = P2P_ATTR_INTERFACE;93199320/* Length: */9321*(u16 *)(p2pie + p2pielen) = cpu_to_le16(0x000D);9322p2pielen += 2;93239324/* Value: */9325_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Device Address */9326p2pielen += ETH_ALEN;93279328p2pie[p2pielen++] = 1; /* P2P Interface Address Count */93299330_rtw_memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN); /* P2P Interface Address List */9331p2pielen += ETH_ALEN;93329333pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen);9334}9335}93369337#ifdef CONFIG_WFD9338wfdielen = rtw_append_assoc_req_wfd_ie(padapter, pframe);9339pframe += wfdielen;9340pattrib->pktlen += wfdielen;9341#endif9342#endif /* CONFIG_P2P */93439344#ifdef CONFIG_RTW_REPEATER_SON9345rtw_rson_append_ie(padapter, pframe, &pattrib->pktlen);9346#endif9347#ifdef CONFIG_APPEND_VENDOR_IE_ENABLE9348pattrib->pktlen += rtw_build_vendor_ie(padapter , &pframe , WIFI_ASSOCREQ_VENDOR_IE_BIT);9349#endif93509351#ifdef CONFIG_RTL8812A9352pframe = rtw_hal_set_8812a_vendor_ie(padapter, pframe, &pattrib->pktlen );9353#endif/*CONFIG_RTL8812A*/93549355#ifdef CONFIG_RTW_80211R9356rtw_ft_build_assoc_req_ies(padapter, is_reassoc, pattrib, &pframe);9357#endif93589359pattrib->last_txcmdsz = pattrib->pktlen;9360dump_mgntframe(padapter, pmgntframe);93619362ret = _SUCCESS;93639364exit:9365if (ret == _SUCCESS)9366rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);9367else9368rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);93699370return;9371}93729373void issue_assocreq(_adapter *padapter)9374{9375_issue_assocreq(padapter, _FALSE);9376}93779378void issue_reassocreq(_adapter *padapter)9379{9380_issue_assocreq(padapter, _TRUE);9381}93829383/* when wait_ack is ture, this function shoule be called at process context */9384static int _issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)9385{9386int ret = _FAIL;9387struct xmit_frame *pmgntframe;9388struct pkt_attrib *pattrib;9389unsigned char *pframe;9390struct rtw_ieee80211_hdr *pwlanhdr;9391unsigned short *fctrl;9392struct xmit_priv *pxmitpriv;9393struct mlme_ext_priv *pmlmeext;9394struct mlme_ext_info *pmlmeinfo;9395u8 a4_shift;93969397/* RTW_INFO("%s:%d\n", __FUNCTION__, power_mode); */93989399if (!padapter)9400goto exit;94019402if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))9403goto exit;94049405pxmitpriv = &(padapter->xmitpriv);9406pmlmeext = &(padapter->mlmeextpriv);9407pmlmeinfo = &(pmlmeext->mlmext_info);94089409pmgntframe = alloc_mgtxmitframe(pxmitpriv);9410if (pmgntframe == NULL)9411goto exit;94129413/* update attribute */9414pattrib = &pmgntframe->attrib;9415update_mgntframe_attrib(padapter, pattrib);9416pattrib->retry_ctrl = _FALSE;94179418_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);94199420pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;9421pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;94229423fctrl = &(pwlanhdr->frame_ctl);9424*(fctrl) = 0;94259426if (MLME_IS_AP(padapter))9427SetFrDs(fctrl);9428else if (MLME_IS_STA(padapter))9429SetToDs(fctrl);9430else if (MLME_IS_MESH(padapter)) {9431SetToDs(fctrl);9432SetFrDs(fctrl);9433}94349435if (power_mode)9436SetPwrMgt(fctrl);94379438if (get_tofr_ds(fctrl) == 3) {9439_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);9440_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);9441_rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);9442_rtw_memcpy(pwlanhdr->addr4, adapter_mac_addr(padapter), ETH_ALEN);9443a4_shift = ETH_ALEN;9444pattrib->hdrlen += ETH_ALEN;9445} else {9446_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);9447_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);9448_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);9449a4_shift = 0;9450}94519452SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);9453pmlmeext->mgnt_seq++;9454set_frame_sub_type(pframe, WIFI_DATA_NULL);94559456pframe += sizeof(struct rtw_ieee80211_hdr_3addr) + a4_shift;9457pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr) + a4_shift;94589459pattrib->last_txcmdsz = pattrib->pktlen;94609461if (wait_ack)9462ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);9463else {9464dump_mgntframe(padapter, pmgntframe);9465ret = _SUCCESS;9466}94679468exit:9469return ret;9470}94719472/*9473* When wait_ms > 0, this function should be called at process context9474* wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT9475* 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 TX9476* try_cnt means the maximal TX count to try9477* da == NULL for station mode9478*/9479int issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)9480{9481int ret = _FAIL;9482int i = 0;9483systime start = rtw_get_current_time();9484struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);9485struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);94869487if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))9488goto exit;94899490/* da == NULL, assum it's null data for sta to ap */9491if (da == NULL)9492da = get_my_bssid(&(pmlmeinfo->network));94939494do {9495ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0 ? _TRUE : _FALSE);94969497i++;94989499if (RTW_CANNOT_RUN(padapter))9500break;95019502if (i < try_cnt && wait_ms > 0 && ret == _FAIL)9503rtw_msleep_os(wait_ms);95049505} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));95069507if (ret != _FAIL) {9508ret = _SUCCESS;9509#ifndef DBG_XMIT_ACK9510goto exit;9511#endif9512}95139514if (try_cnt && wait_ms) {9515if (da)9516RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",9517FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),9518ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));9519else9520RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",9521FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),9522ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));9523}9524exit:9525return ret;9526}95279528/* when wait_ack is ture, this function shoule be called at process context */9529static int _issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, u8 ps, int wait_ack)9530{9531int ret = _FAIL;9532struct xmit_frame *pmgntframe;9533struct pkt_attrib *pattrib;9534unsigned char *pframe;9535struct rtw_ieee80211_hdr *pwlanhdr;9536unsigned short *fctrl, *qc;9537struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);9538struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);9539struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);9540u8 a4_shift;95419542if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))9543goto exit;95449545/* RTW_INFO("%s\n", __FUNCTION__); */95469547pmgntframe = alloc_mgtxmitframe(pxmitpriv);9548if (pmgntframe == NULL)9549goto exit;95509551/* update attribute */9552pattrib = &pmgntframe->attrib;9553update_mgntframe_attrib(padapter, pattrib);95549555pattrib->hdrlen += 2;9556pattrib->qos_en = _TRUE;9557pattrib->eosp = 1;9558pattrib->ack_policy = 0;9559pattrib->mdata = 0;95609561_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);95629563pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;9564pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;95659566fctrl = &(pwlanhdr->frame_ctl);9567*(fctrl) = 0;95689569if (MLME_IS_AP(padapter))9570SetFrDs(fctrl);9571else if (MLME_IS_STA(padapter))9572SetToDs(fctrl);9573else if (MLME_IS_MESH(padapter)) {9574SetToDs(fctrl);9575SetFrDs(fctrl);9576}95779578if (ps)9579SetPwrMgt(fctrl);95809581if (pattrib->mdata)9582SetMData(fctrl);95839584if (get_tofr_ds(fctrl) == 3) {9585_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);9586_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);9587_rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);9588_rtw_memcpy(pwlanhdr->addr4, adapter_mac_addr(padapter), ETH_ALEN);9589a4_shift = ETH_ALEN;9590pattrib->hdrlen += ETH_ALEN;9591} else {9592_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);9593_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);9594_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);9595a4_shift = 0;9596}95979598qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);95999600SetPriority(qc, tid);96019602SetEOSP(qc, pattrib->eosp);96039604SetAckpolicy(qc, pattrib->ack_policy);96059606SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);9607pmlmeext->mgnt_seq++;9608set_frame_sub_type(pframe, WIFI_QOS_DATA_NULL);96099610pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos) + a4_shift;9611pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos) + a4_shift;96129613pattrib->last_txcmdsz = pattrib->pktlen;96149615if (wait_ack)9616ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);9617else {9618dump_mgntframe(padapter, pmgntframe);9619ret = _SUCCESS;9620}96219622exit:9623return ret;9624}96259626/*9627* when wait_ms >0 , this function should be called at process context9628* wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT9629* 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 TX9630* try_cnt means the maximal TX count to try9631* da == NULL for station mode9632*/9633int issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, u8 ps, int try_cnt, int wait_ms)9634{9635int ret = _FAIL;9636int i = 0;9637systime start = rtw_get_current_time();9638struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);9639struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);96409641if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))9642goto exit;96439644/* da == NULL, assum it's null data for sta to ap*/9645if (da == NULL)9646da = get_my_bssid(&(pmlmeinfo->network));96479648do {9649ret = _issue_qos_nulldata(padapter, da, tid, ps, wait_ms > 0 ? _TRUE : _FALSE);96509651i++;96529653if (RTW_CANNOT_RUN(padapter))9654break;96559656if (i < try_cnt && wait_ms > 0 && ret == _FAIL)9657rtw_msleep_os(wait_ms);96589659} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));96609661if (ret != _FAIL) {9662ret = _SUCCESS;9663#ifndef DBG_XMIT_ACK9664goto exit;9665#endif9666}96679668if (try_cnt && wait_ms) {9669if (da)9670RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",9671FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),9672ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));9673else9674RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",9675FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),9676ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));9677}9678exit:9679return ret;9680}96819682static int _issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack, u8 key_type)9683{9684struct xmit_frame *pmgntframe;9685struct pkt_attrib *pattrib;9686unsigned char *pframe;9687struct rtw_ieee80211_hdr *pwlanhdr;9688unsigned short *fctrl;9689struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);9690struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);9691struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);9692int ret = _FAIL;9693#ifdef CONFIG_P2P9694struct wifidirect_info *pwdinfo = &(padapter->wdinfo);9695#endif /* CONFIG_P2P */96969697/* RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */96989699#ifdef CONFIG_P2P9700if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) && (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {9701_cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);9702_set_timer(&pwdinfo->reset_ch_sitesurvey, 10);9703}9704#endif /* CONFIG_P2P */97059706if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))9707goto exit;97089709pmgntframe = alloc_mgtxmitframe(pxmitpriv);9710if (pmgntframe == NULL)9711goto exit;97129713/* update attribute */9714pattrib = &pmgntframe->attrib;9715update_mgntframe_attrib(padapter, pattrib);9716pattrib->retry_ctrl = _FALSE;9717pattrib->key_type = key_type;9718_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);97199720pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;9721pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;97229723fctrl = &(pwlanhdr->frame_ctl);9724*(fctrl) = 0;97259726_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);9727_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);9728_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);97299730SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);9731pmlmeext->mgnt_seq++;9732set_frame_sub_type(pframe, WIFI_DEAUTH);97339734pframe += sizeof(struct rtw_ieee80211_hdr_3addr);9735pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);97369737reason = cpu_to_le16(reason);9738pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_ , (unsigned char *)&reason, &(pattrib->pktlen));97399740pattrib->last_txcmdsz = pattrib->pktlen;974197429743if (wait_ack)9744ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);9745else {9746dump_mgntframe(padapter, pmgntframe);9747ret = _SUCCESS;9748}97499750exit:9751return ret;9752}97539754int issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason)9755{9756RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));9757return _issue_deauth(padapter, da, reason, _FALSE, IEEE80211W_RIGHT_KEY);9758}97599760#ifdef CONFIG_IEEE80211W9761int issue_deauth_11w(_adapter *padapter, unsigned char *da, unsigned short reason, u8 key_type)9762{9763RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));9764return _issue_deauth(padapter, da, reason, _FALSE, key_type);9765}9766#endif /* CONFIG_IEEE80211W */97679768/*9769* wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT9770* 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 TX9771* try_cnt means the maximal TX count to try9772*/9773int issue_deauth_ex(_adapter *padapter, u8 *da, unsigned short reason, int try_cnt,9774int wait_ms)9775{9776int ret = _FAIL;9777int i = 0;9778systime start = rtw_get_current_time();97799780if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))9781goto exit;97829783do {9784ret = _issue_deauth(padapter, da, reason, wait_ms > 0 ? _TRUE : _FALSE, IEEE80211W_RIGHT_KEY);97859786i++;97879788if (RTW_CANNOT_RUN(padapter))9789break;97909791if (i < try_cnt && wait_ms > 0 && ret == _FAIL)9792rtw_msleep_os(wait_ms);97939794} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));97959796if (ret != _FAIL) {9797ret = _SUCCESS;9798#ifndef DBG_XMIT_ACK9799goto exit;9800#endif9801}98029803if (try_cnt && wait_ms) {9804if (da)9805RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",9806FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),9807ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));9808else9809RTW_INFO(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",9810FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),9811ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));9812}9813exit:9814return ret;9815}98169817void issue_action_spct_ch_switch(_adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)9818{9819struct xmit_frame *pmgntframe;9820struct pkt_attrib *pattrib;9821unsigned char *pframe;9822struct rtw_ieee80211_hdr *pwlanhdr;9823unsigned short *fctrl;9824struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);9825struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);98269827if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))9828return;98299830RTW_INFO(FUNC_NDEV_FMT" ra="MAC_FMT", ch:%u, offset:%u\n",9831FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(ra), new_ch, ch_offset);98329833pmgntframe = alloc_mgtxmitframe(pxmitpriv);9834if (pmgntframe == NULL)9835return;98369837/* update attribute */9838pattrib = &pmgntframe->attrib;9839update_mgntframe_attrib(padapter, pattrib);98409841_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);98429843pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;9844pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;98459846fctrl = &(pwlanhdr->frame_ctl);9847*(fctrl) = 0;98489849_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */9850_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); /* TA */9851_rtw_memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */98529853SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);9854pmlmeext->mgnt_seq++;9855set_frame_sub_type(pframe, WIFI_ACTION);98569857pframe += sizeof(struct rtw_ieee80211_hdr_3addr);9858pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);98599860/* category, action */9861{9862u8 category, action;9863category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;9864action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;98659866pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));9867pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));9868}98699870pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0);9871pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen),9872hal_ch_offset_to_secondary_ch_offset(ch_offset));98739874pattrib->last_txcmdsz = pattrib->pktlen;98759876dump_mgntframe(padapter, pmgntframe);98779878}98799880#ifdef CONFIG_IEEE80211W9881void issue_action_SA_Query(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid, u8 key_type)9882{9883u8 category = RTW_WLAN_CATEGORY_SA_QUERY;9884u16 reason_code;9885struct xmit_frame *pmgntframe;9886struct pkt_attrib *pattrib;9887u8 *pframe;9888struct rtw_ieee80211_hdr *pwlanhdr;9889u16 *fctrl;9890struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);9891struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);9892struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);9893struct sta_info *psta;9894struct sta_priv *pstapriv = &padapter->stapriv;9895struct registry_priv *pregpriv = &padapter->registrypriv;9896struct mlme_priv *pmlmepriv = &padapter->mlmepriv;98979898if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))9899return;99009901RTW_INFO("%s, %04x\n", __FUNCTION__, tid);99029903pmgntframe = alloc_mgtxmitframe(pxmitpriv);9904if (pmgntframe == NULL) {9905RTW_INFO("%s: alloc_mgtxmitframe fail\n", __FUNCTION__);9906return;9907}99089909/* update attribute */9910pattrib = &pmgntframe->attrib;9911update_mgntframe_attrib(padapter, pattrib);9912pattrib->key_type = key_type;9913_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);99149915pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;9916pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;99179918fctrl = &(pwlanhdr->frame_ctl);9919*(fctrl) = 0;99209921if (raddr)9922_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);9923else9924_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);9925_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);9926_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);99279928SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);9929pmlmeext->mgnt_seq++;9930set_frame_sub_type(pframe, WIFI_ACTION);99319932pframe += sizeof(struct rtw_ieee80211_hdr_3addr);9933pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);99349935pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);9936pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);99379938switch (action) {9939case 0: /* SA Query req */9940pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);9941pmlmeext->sa_query_seq++;9942/* send sa query request to AP, AP should reply sa query response in 1 second */9943if (pattrib->key_type == IEEE80211W_RIGHT_KEY) {9944psta = rtw_get_stainfo(pstapriv, pwlanhdr->addr1);9945if (psta != NULL) {9946/* RTW_INFO("%s, %d, set dot11w_expire_timer\n", __func__, __LINE__); */9947_set_timer(&psta->dot11w_expire_timer, 1000);9948}9949}9950break;99519952case 1: /* SA Query rsp */9953tid = cpu_to_le16(tid);9954/* RTW_INFO("rtw_set_fixed_ie, %04x\n", tid); */9955pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&tid, &pattrib->pktlen);9956break;9957default:9958break;9959}99609961pattrib->last_txcmdsz = pattrib->pktlen;99629963dump_mgntframe(padapter, pmgntframe);9964}9965#endif /* CONFIG_IEEE80211W */99669967/**9968* issue_action_ba - internal function to TX Block Ack action frame9969* @padapter: the adapter to TX9970* @raddr: receiver address9971* @action: Block Ack Action9972* @tid: tid9973* @size: the announced AMPDU buffer size. used by ADDBA_RESP9974* @status: status/reason code. used by ADDBA_RESP, DELBA9975* @initiator: if we are the initiator of AMPDU association. used by DELBA9976* @wait_ack: used xmit ack9977*9978* Returns:9979* _SUCCESS: No xmit ack is used or acked9980* _FAIL: not acked when using xmit ack9981*/9982static int issue_action_ba(_adapter *padapter, unsigned char *raddr, unsigned char action9983, u8 tid, u8 size, u16 status, u8 initiator, int wait_ack)9984{9985int ret = _FAIL;9986u8 category = RTW_WLAN_CATEGORY_BACK;9987u16 start_seq;9988u16 BA_para_set;9989u16 BA_timeout_value;9990u16 BA_starting_seqctrl;9991struct xmit_frame *pmgntframe;9992struct pkt_attrib *pattrib;9993u8 *pframe;9994struct rtw_ieee80211_hdr *pwlanhdr;9995u16 *fctrl;9996struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);9997struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);9998struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);9999struct sta_info *psta;10000struct sta_priv *pstapriv = &padapter->stapriv;10001struct registry_priv *pregpriv = &padapter->registrypriv;1000210003#ifdef CONFIG_80211N_HT1000410005if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))10006goto exit;1000710008pmgntframe = alloc_mgtxmitframe(pxmitpriv);10009if (pmgntframe == NULL)10010goto exit;1001110012/* update attribute */10013pattrib = &pmgntframe->attrib;10014update_mgntframe_attrib(padapter, pattrib);1001510016_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);1001710018pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;10019pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;1002010021fctrl = &(pwlanhdr->frame_ctl);10022*(fctrl) = 0;1002310024/* _rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */10025_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);10026_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);10027_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);1002810029SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);10030pmlmeext->mgnt_seq++;10031set_frame_sub_type(pframe, WIFI_ACTION);1003210033pframe += sizeof(struct rtw_ieee80211_hdr_3addr);10034pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);1003510036pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));10037pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));1003810039if (category == 3) {10040switch (action) {10041case RTW_WLAN_ACTION_ADDBA_REQ:10042do {10043pmlmeinfo->dialogToken++;10044} while (pmlmeinfo->dialogToken == 0);10045pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));1004610047#if defined(CONFIG_RTL8188E) && defined(CONFIG_SDIO_HCI)10048BA_para_set = (0x0802 | ((tid & 0xf) << 2)); /* immediate ack & 16 buffer size */10049#else10050BA_para_set = (0x1002 | ((tid & 0xf) << 2)); /* immediate ack & 64 buffer size */10051#endif1005210053#ifdef CONFIG_TX_AMSDU10054if (padapter->tx_amsdu >= 1) /* TX AMSDU enabled */10055BA_para_set |= BIT(0);10056else /* TX AMSDU disabled */10057BA_para_set &= ~BIT(0);10058#endif10059BA_para_set = cpu_to_le16(BA_para_set);10060pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));1006110062/* BA_timeout_value = 0xffff; */ /* max: 65535 TUs(~ 65 ms) */10063BA_timeout_value = 5000;/* ~ 5ms */10064BA_timeout_value = cpu_to_le16(BA_timeout_value);10065pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_timeout_value)), &(pattrib->pktlen));1006610067/* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */10068psta = rtw_get_stainfo(pstapriv, raddr);10069if (psta != NULL) {10070start_seq = (psta->sta_xmitpriv.txseq_tid[tid & 0x07] & 0xfff) + 1;1007110072RTW_INFO("BA_starting_seqctrl = %d for TID=%d\n", start_seq, tid & 0x07);1007310074psta->BA_starting_seqctrl[tid & 0x07] = start_seq;1007510076BA_starting_seqctrl = start_seq << 4;10077}1007810079BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl);10080pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_starting_seqctrl)), &(pattrib->pktlen));10081break;1008210083case RTW_WLAN_ACTION_ADDBA_RESP:10084pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));10085status = cpu_to_le16(status);10086pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));1008710088BA_para_set = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set);1008910090BA_para_set &= ~IEEE80211_ADDBA_PARAM_TID_MASK;10091BA_para_set |= (tid << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;1009210093BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;10094BA_para_set |= (size << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;1009510096if (!padapter->registrypriv.wifi_spec) {10097if (pregpriv->rx_ampdu_amsdu == 0) /* disabled */10098BA_para_set &= ~BIT(0);10099else if (pregpriv->rx_ampdu_amsdu == 1) /* enabled */10100BA_para_set |= BIT(0);10101}1010210103BA_para_set = cpu_to_le16(BA_para_set);1010410105pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));10106pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));10107break;1010810109case RTW_WLAN_ACTION_DELBA:10110BA_para_set = 0;10111BA_para_set |= (tid << 12) & IEEE80211_DELBA_PARAM_TID_MASK;10112BA_para_set |= (initiator << 11) & IEEE80211_DELBA_PARAM_INITIATOR_MASK;1011310114BA_para_set = cpu_to_le16(BA_para_set);10115pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));10116status = cpu_to_le16(status);10117pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(status)), &(pattrib->pktlen));10118break;10119default:10120break;10121}10122}1012310124pattrib->last_txcmdsz = pattrib->pktlen;1012510126if (wait_ack)10127ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);10128else {10129dump_mgntframe(padapter, pmgntframe);10130ret = _SUCCESS;10131}1013210133exit:10134#endif /* CONFIG_80211N_HT */10135return ret;10136}1013710138/**10139* issue_addba_req - TX ADDBA_REQ10140* @adapter: the adapter to TX10141* @ra: receiver address10142* @tid: tid10143*/10144inline void issue_addba_req(_adapter *adapter, unsigned char *ra, u8 tid)10145{10146issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_REQ10147, tid10148, 0 /* unused */10149, 0 /* unused */10150, 0 /* unused */10151, _FALSE10152);10153RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" tid=%u\n"10154, FUNC_ADPT_ARG(adapter), MAC_ARG(ra), tid);1015510156}1015710158/**10159* issue_addba_rsp - TX ADDBA_RESP10160* @adapter: the adapter to TX10161* @ra: receiver address10162* @tid: tid10163* @status: status code10164* @size: the announced AMPDU buffer size10165*/10166inline void issue_addba_rsp(_adapter *adapter, unsigned char *ra, u8 tid, u16 status, u8 size)10167{10168issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_RESP10169, tid10170, size10171, status10172, 0 /* unused */10173, _FALSE10174);10175RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" status=%u, tid=%u, size=%u\n"10176, FUNC_ADPT_ARG(adapter), MAC_ARG(ra), status, tid, size);10177}1017810179/**10180* issue_addba_rsp_wait_ack - TX ADDBA_RESP and wait ack10181* @adapter: the adapter to TX10182* @ra: receiver address10183* @tid: tid10184* @status: status code10185* @size: the announced AMPDU buffer size10186* @try_cnt: the maximal TX count to try10187* @wait_ms: == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT10188* > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX10189*/10190inline u8 issue_addba_rsp_wait_ack(_adapter *adapter, unsigned char *ra, u8 tid, u16 status, u8 size, int try_cnt, int wait_ms)10191{10192int ret = _FAIL;10193int i = 0;10194systime start = rtw_get_current_time();1019510196if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(adapter)))10197goto exit;1019810199do {10200ret = issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_RESP10201, tid10202, size10203, status10204, 0 /* unused */10205, _TRUE10206);1020710208i++;1020910210if (RTW_CANNOT_RUN(adapter))10211break;1021210213if (i < try_cnt && wait_ms > 0 && ret == _FAIL)10214rtw_msleep_os(wait_ms);1021510216} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));1021710218if (ret != _FAIL) {10219ret = _SUCCESS;10220#ifndef DBG_XMIT_ACK10221/* goto exit; */10222#endif10223}1022410225if (try_cnt && wait_ms) {10226RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" status:=%u tid=%u size:%u%s, %d/%d in %u ms\n"10227, FUNC_ADPT_ARG(adapter), MAC_ARG(ra), status, tid, size10228, ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));10229}1023010231exit:10232return ret;10233}1023410235/**10236* issue_del_ba - TX DELBA10237* @adapter: the adapter to TX10238* @ra: receiver address10239* @tid: tid10240* @reason: reason code10241* @initiator: if we are the initiator of AMPDU association. used by DELBA10242*/10243inline void issue_del_ba(_adapter *adapter, unsigned char *ra, u8 tid, u16 reason, u8 initiator)10244{10245issue_action_ba(adapter, ra, RTW_WLAN_ACTION_DELBA10246, tid10247, 0 /* unused */10248, reason10249, initiator10250, _FALSE10251);10252RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" reason=%u, tid=%u, initiator=%u\n"10253, FUNC_ADPT_ARG(adapter), MAC_ARG(ra), reason, tid, initiator);10254}1025510256/**10257* issue_del_ba_ex - TX DELBA with xmit ack options10258* @adapter: the adapter to TX10259* @ra: receiver address10260* @tid: tid10261* @reason: reason code10262* @initiator: if we are the initiator of AMPDU association. used by DELBA10263* @try_cnt: the maximal TX count to try10264* @wait_ms: == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT10265* > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX10266*/10267int issue_del_ba_ex(_adapter *adapter, unsigned char *ra, u8 tid, u16 reason, u8 initiator10268, int try_cnt, int wait_ms)10269{10270int ret = _FAIL;10271int i = 0;10272systime start = rtw_get_current_time();1027310274if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(adapter)))10275goto exit;1027610277do {10278ret = issue_action_ba(adapter, ra, RTW_WLAN_ACTION_DELBA10279, tid10280, 0 /* unused */10281, reason10282, initiator10283, wait_ms > 0 ? _TRUE : _FALSE10284);1028510286i++;1028710288if (RTW_CANNOT_RUN(adapter))10289break;1029010291if (i < try_cnt && wait_ms > 0 && ret == _FAIL)10292rtw_msleep_os(wait_ms);1029310294} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));1029510296if (ret != _FAIL) {10297ret = _SUCCESS;10298#ifndef DBG_XMIT_ACK10299/* goto exit; */10300#endif10301}1030210303if (try_cnt && wait_ms) {10304RTW_INFO(FUNC_ADPT_FMT" ra="MAC_FMT" reason=%u, tid=%u, initiator=%u%s, %d/%d in %u ms\n"10305, FUNC_ADPT_ARG(adapter), MAC_ARG(ra), reason, tid, initiator10306, ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));10307}10308exit:10309return ret;10310}1031110312void issue_action_BSSCoexistPacket(_adapter *padapter)10313{10314_irqL irqL;10315_list *plist, *phead;10316unsigned char category, action;10317struct xmit_frame *pmgntframe;10318struct pkt_attrib *pattrib;10319unsigned char *pframe;10320struct rtw_ieee80211_hdr *pwlanhdr;10321unsigned short *fctrl;10322struct wlan_network *pnetwork = NULL;10323struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);10324struct mlme_priv *pmlmepriv = &padapter->mlmepriv;10325struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);10326struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);10327_queue *queue = &(pmlmepriv->scanned_queue);10328u8 InfoContent[16] = {0};10329u8 ICS[8][15];10330#ifdef CONFIG_80211N_HT10331if ((pmlmepriv->num_FortyMHzIntolerant == 0) && (pmlmepriv->num_sta_no_ht == 0))10332return;1033310334if (_TRUE == pmlmeinfo->bwmode_updated)10335return;1033610337if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))10338return;1033910340RTW_INFO("%s\n", __FUNCTION__);103411034210343category = RTW_WLAN_CATEGORY_PUBLIC;10344action = ACT_PUBLIC_BSSCOEXIST;1034510346pmgntframe = alloc_mgtxmitframe(pxmitpriv);10347if (pmgntframe == NULL)10348return;1034910350/* update attribute */10351pattrib = &pmgntframe->attrib;10352update_mgntframe_attrib(padapter, pattrib);1035310354_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);1035510356pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;10357pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;1035810359fctrl = &(pwlanhdr->frame_ctl);10360*(fctrl) = 0;1036110362_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);10363_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);10364_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);1036510366SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);10367pmlmeext->mgnt_seq++;10368set_frame_sub_type(pframe, WIFI_ACTION);1036910370pframe += sizeof(struct rtw_ieee80211_hdr_3addr);10371pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);1037210373pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));10374pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));1037510376/* TODO calculate 40Mhz intolerant via ch and ch offset */10377/* if (pmlmepriv->num_FortyMHzIntolerant > 0) */10378{10379u8 iedata = 0;1038010381iedata |= BIT(2);/* 20 MHz BSS Width Request */10382pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));10383}1038410385/* */10386_rtw_memset(ICS, 0, sizeof(ICS));10387if (pmlmepriv->num_sta_no_ht > 0) {10388int i;1038910390_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);1039110392phead = get_list_head(queue);10393plist = get_next(phead);1039410395while (1) {10396int len;10397u8 *p;10398WLAN_BSSID_EX *pbss_network;1039910400if (rtw_end_of_queue_search(phead, plist) == _TRUE)10401break;1040210403pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);1040410405plist = get_next(plist);1040610407pbss_network = (WLAN_BSSID_EX *)&pnetwork->network;1040810409p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);10410if ((p == NULL) || (len == 0)) { /* non-HT */10411if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))10412continue;1041310414ICS[0][pbss_network->Configuration.DSConfig] = 1;1041510416if (ICS[0][0] == 0)10417ICS[0][0] = 1;10418}1041910420}1042110422_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);104231042410425for (i = 0; i < 8; i++) {10426if (ICS[i][0] == 1) {10427int j, k = 0;1042810429InfoContent[k] = i;10430/* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent,i); */10431k++;1043210433for (j = 1; j <= 14; j++) {10434if (ICS[i][j] == 1) {10435if (k < 16) {10436InfoContent[k] = j; /* channel number */10437/* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */10438k++;10439}10440}10441}1044210443pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));1044410445}1044610447}104481044910450}104511045210453pattrib->last_txcmdsz = pattrib->pktlen;1045410455dump_mgntframe(padapter, pmgntframe);10456#endif /* CONFIG_80211N_HT */10457}1045810459/* Spatial Multiplexing Powersave (SMPS) action frame */10460int _issue_action_SM_PS(_adapter *padapter , unsigned char *raddr , u8 NewMimoPsMode , u8 wait_ack)10461{1046210463int ret = _FAIL;10464unsigned char category = RTW_WLAN_CATEGORY_HT;10465u8 action = RTW_WLAN_ACTION_HT_SM_PS;10466u8 sm_power_control = 0;10467struct xmit_frame *pmgntframe;10468struct pkt_attrib *pattrib;10469unsigned char *pframe;10470struct rtw_ieee80211_hdr *pwlanhdr;10471unsigned short *fctrl;10472struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);10473struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);10474struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);104751047610477if (NewMimoPsMode == WLAN_HT_CAP_SM_PS_DISABLED) {10478sm_power_control = sm_power_control & ~(BIT(0)); /* SM Power Save Enable = 0 SM Power Save Disable */10479} else if (NewMimoPsMode == WLAN_HT_CAP_SM_PS_STATIC) {10480sm_power_control = sm_power_control | BIT(0); /* SM Power Save Enable = 1 SM Power Save Enable */10481sm_power_control = sm_power_control & ~(BIT(1)); /* SM Mode = 0 Static Mode */10482} else if (NewMimoPsMode == WLAN_HT_CAP_SM_PS_DYNAMIC) {10483sm_power_control = sm_power_control | BIT(0); /* SM Power Save Enable = 1 SM Power Save Enable */10484sm_power_control = sm_power_control | BIT(1); /* SM Mode = 1 Dynamic Mode */10485} else10486return ret;1048710488if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))10489return ret;1049010491RTW_INFO("%s, sm_power_control=%u, NewMimoPsMode=%u\n", __FUNCTION__ , sm_power_control , NewMimoPsMode);1049210493pmgntframe = alloc_mgtxmitframe(pxmitpriv);10494if (pmgntframe == NULL)10495return ret;1049610497/* update attribute */10498pattrib = &pmgntframe->attrib;10499update_mgntframe_attrib(padapter, pattrib);1050010501_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);1050210503pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;10504pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;1050510506fctrl = &(pwlanhdr->frame_ctl);10507*(fctrl) = 0;1050810509_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); /* RA */10510_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); /* TA */10511_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); /* DA = RA */1051210513SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);10514pmlmeext->mgnt_seq++;10515set_frame_sub_type(pframe, WIFI_ACTION);1051610517pframe += sizeof(struct rtw_ieee80211_hdr_3addr);10518pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);1051910520/* category, action */10521pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));10522pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));1052310524pframe = rtw_set_fixed_ie(pframe, 1, &(sm_power_control), &(pattrib->pktlen));1052510526pattrib->last_txcmdsz = pattrib->pktlen;1052710528if (wait_ack)10529ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);10530else {10531dump_mgntframe(padapter, pmgntframe);10532ret = _SUCCESS;10533}1053410535if (ret != _SUCCESS)10536RTW_INFO("%s, ack to\n", __func__);1053710538return ret;10539}1054010541/*10542* wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT10543* 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 TX10544* try_cnt means the maximal TX count to try10545*/10546int issue_action_SM_PS_wait_ack(_adapter *padapter, unsigned char *raddr, u8 NewMimoPsMode, int try_cnt, int wait_ms)10547{10548int ret = _FAIL;10549int i = 0;10550systime start = rtw_get_current_time();1055110552if (rtw_rfctl_is_tx_blocked_by_ch_waiting(adapter_to_rfctl(padapter)))10553goto exit;1055410555do {10556ret = _issue_action_SM_PS(padapter, raddr, NewMimoPsMode , wait_ms > 0 ? _TRUE : _FALSE);1055710558i++;1055910560if (RTW_CANNOT_RUN(padapter))10561break;1056210563if (i < try_cnt && wait_ms > 0 && ret == _FAIL)10564rtw_msleep_os(wait_ms);1056510566} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));1056710568if (ret != _FAIL) {10569ret = _SUCCESS;10570#ifndef DBG_XMIT_ACK10571goto exit;10572#endif10573}1057410575if (try_cnt && wait_ms) {10576if (raddr)10577RTW_INFO(FUNC_ADPT_FMT" to "MAC_FMT", %s , %d/%d in %u ms\n",10578FUNC_ADPT_ARG(padapter), MAC_ARG(raddr),10579ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));10580else10581RTW_INFO(FUNC_ADPT_FMT", %s , %d/%d in %u ms\n",10582FUNC_ADPT_ARG(padapter),10583ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));10584}10585exit:1058610587return ret;10588}1058910590int issue_action_SM_PS(_adapter *padapter , unsigned char *raddr , u8 NewMimoPsMode)10591{10592RTW_INFO("%s to "MAC_FMT"\n", __func__, MAC_ARG(raddr));10593return _issue_action_SM_PS(padapter, raddr, NewMimoPsMode , _FALSE);10594}1059510596/**10597* _send_delba_sta_tid - Cancel the AMPDU association for the specific @sta, @tid10598* @adapter: the adapter to which @sta belongs10599* @initiator: if we are the initiator of AMPDU association10600* @sta: the sta to be checked10601* @tid: the tid to be checked10602* @force: cancel and send DELBA even when no AMPDU association is setup10603* @wait_ack: send delba with xmit ack (valid when initiator == 0)10604*10605* Returns:10606* _FAIL if sta is NULL10607* when initiator is 1, always _SUCCESS10608* when initiator is 0, _SUCCESS if DELBA is acked10609*/10610static unsigned int _send_delba_sta_tid(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid10611, u8 force, int wait_ack)10612{10613int ret = _SUCCESS;1061410615if (sta == NULL) {10616ret = _FAIL;10617goto exit;10618}1061910620if (initiator == 0) {10621/* recipient */10622if (force || sta->recvreorder_ctrl[tid].enable == _TRUE) {10623u8 ampdu_size_bak = sta->recvreorder_ctrl[tid].ampdu_size;1062410625sta->recvreorder_ctrl[tid].enable = _FALSE;10626sta->recvreorder_ctrl[tid].ampdu_size = RX_AMPDU_SIZE_INVALID;1062710628if (rtw_del_rx_ampdu_test_trigger_no_tx_fail())10629ret = _FAIL;10630else if (wait_ack)10631ret = issue_del_ba_ex(adapter, sta->cmn.mac_addr, tid, 37, initiator, 3, 1);10632else10633issue_del_ba(adapter, sta->cmn.mac_addr, tid, 37, initiator);1063410635if (ret == _FAIL && sta->recvreorder_ctrl[tid].enable == _FALSE)10636sta->recvreorder_ctrl[tid].ampdu_size = ampdu_size_bak;10637}10638} else if (initiator == 1) {10639/* originator */10640#ifdef CONFIG_80211N_HT10641if (force || sta->htpriv.agg_enable_bitmap & BIT(tid)) {10642sta->htpriv.agg_enable_bitmap &= ~BIT(tid);10643sta->htpriv.candidate_tid_bitmap &= ~BIT(tid);10644issue_del_ba(adapter, sta->cmn.mac_addr, tid, 37, initiator);10645}10646#endif10647}1064810649exit:10650return ret;10651}1065210653inline unsigned int send_delba_sta_tid(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid10654, u8 force)10655{10656return _send_delba_sta_tid(adapter, initiator, sta, tid, force, 0);10657}1065810659inline unsigned int send_delba_sta_tid_wait_ack(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid10660, u8 force)10661{10662return _send_delba_sta_tid(adapter, initiator, sta, tid, force, 1);10663}1066410665unsigned int send_delba(_adapter *padapter, u8 initiator, u8 *addr)10666{10667struct sta_priv *pstapriv = &padapter->stapriv;10668struct sta_info *psta = NULL;10669struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;10670struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);10671u16 tid;1067210673if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)10674if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))10675return _SUCCESS;1067610677psta = rtw_get_stainfo(pstapriv, addr);10678if (psta == NULL)10679return _SUCCESS;1068010681#if 010682RTW_INFO("%s:%s\n", __func__, (initiator == 0) ? "RX_DIR" : "TX_DIR");10683if (initiator == 1) /* originator */10684RTW_INFO("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap);10685#endif1068610687for (tid = 0; tid < TID_NUM; tid++)10688send_delba_sta_tid(padapter, initiator, psta, tid, 0);1068910690return _SUCCESS;10691}1069210693unsigned int send_beacon(_adapter *padapter)10694{10695#if defined(CONFIG_PCI_HCI) && !defined(CONFIG_PCI_BCN_POLLING)10696#ifdef CONFIG_FW_HANDLE_TXBCN10697u8 vap_id = padapter->vap_id;1069810699/* bypass TX BCN because vap_id is invalid*/10700if (vap_id == CONFIG_LIMITED_AP_NUM)10701return _SUCCESS;10702#endif1070310704/* bypass TX BCN queue because op ch is switching/waiting */10705if (check_fwstate(&padapter->mlmepriv, WIFI_OP_CH_SWITCHING)10706|| IS_CH_WAITING(adapter_to_rfctl(padapter))10707)10708return _SUCCESS;1070910710/* RTW_INFO("%s\n", __FUNCTION__); */1071110712rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);1071310714/* 8192EE Port select for Beacon DL */10715rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);10716#ifdef CONFIG_FW_HANDLE_TXBCN10717rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id);10718#endif1071910720issue_beacon(padapter, 0);1072110722#ifdef CONFIG_FW_HANDLE_TXBCN10723vap_id = 0xFF;10724rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id);10725#endif1072610727#ifdef RTL8814AE_SW_BCN10728if (GET_HAL_DATA(padapter)->bCorrectBCN != 0)10729RTW_INFO("%s, line%d, Warnning, pHalData->bCorrectBCN != 0\n", __func__, __LINE__);10730GET_HAL_DATA(padapter)->bCorrectBCN = 1;10731#endif1073210733return _SUCCESS;10734#endif1073510736/* CONFIG_PCI_BCN_POLLING is for pci interface beacon polling mode */10737#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)|| defined(CONFIG_PCI_BCN_POLLING)10738u8 bxmitok = _FALSE;10739int issue = 0;10740int poll = 0;10741systime start = rtw_get_current_time();10742#ifdef CONFIG_FW_HANDLE_TXBCN10743u8 vap_id = padapter->vap_id;1074410745/* bypass TX BCN because vap_id is invalid*/10746if (vap_id == CONFIG_LIMITED_AP_NUM)10747return _SUCCESS;10748#endif1074910750/* bypass TX BCN queue because op ch is switching/waiting */10751if (check_fwstate(&padapter->mlmepriv, WIFI_OP_CH_SWITCHING)10752|| IS_CH_WAITING(adapter_to_rfctl(padapter))10753)10754return _SUCCESS;1075510756#if defined(CONFIG_USB_HCI)10757#if defined(CONFIG_RTL8812A)10758if (IS_FULL_SPEED_USB(padapter)) {10759issue_beacon(padapter, 300);10760bxmitok = _TRUE;10761} else10762#endif10763#endif10764{10765rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);10766rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);10767#ifdef CONFIG_FW_HANDLE_TXBCN10768rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id);10769#endif10770do {10771#if defined(CONFIG_PCI_BCN_POLLING)10772issue_beacon(padapter, 0);10773#else10774issue_beacon(padapter, 100);10775#endif10776issue++;10777do {10778#if defined(CONFIG_PCI_BCN_POLLING)10779rtw_msleep_os(1);10780#else10781rtw_yield_os();10782#endif10783rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));10784poll++;10785} while ((poll % 10) != 0 && _FALSE == bxmitok && !RTW_CANNOT_RUN(padapter));10786#if defined(CONFIG_PCI_BCN_POLLING)10787rtw_hal_unmap_beacon_icf(padapter);10788#endif10789} while (bxmitok == _FALSE && (issue < 100) && !RTW_CANNOT_RUN(padapter));10790#ifdef CONFIG_FW_HANDLE_TXBCN10791vap_id = 0xFF;10792rtw_hal_set_hwreg(padapter, HW_VAR_BCN_HEAD_SEL, &vap_id);10793#endif10794}10795if (RTW_CANNOT_RUN(padapter))10796return _FAIL;107971079810799if (_FALSE == bxmitok) {10800RTW_INFO("%s fail! %u ms\n", __FUNCTION__, rtw_get_passing_time_ms(start));10801#ifdef CONFIG_BCN_RECOVERY10802GET_HAL_DATA(padapter)->issue_bcn_fail++;10803#endif /*CONFIG_BCN_RECOVERY*/10804return _FAIL;10805} else {10806u32 passing_time = rtw_get_passing_time_ms(start);1080710808if (passing_time > 100 || issue > 3)10809RTW_INFO("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));10810else if (0)10811RTW_INFO("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));1081210813#ifdef CONFIG_FW_CORRECT_BCN10814rtw_hal_fw_correct_bcn(padapter);10815#endif10816return _SUCCESS;10817}1081810819#endif /*defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)*/1082010821}1082210823/****************************************************************************1082410825Following are some utitity fuctions for WiFi MLME1082610827*****************************************************************************/1082810829BOOLEAN IsLegal5GChannel(10830PADAPTER Adapter,10831u8 channel)10832{1083310834int i = 0;10835u8 Channel_5G[45] = {36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58,1083660, 62, 64, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,10837124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153, 155, 157, 159,10838161, 163, 16510839};10840for (i = 0; i < sizeof(Channel_5G); i++)10841if (channel == Channel_5G[i])10842return _TRUE;10843return _FALSE;10844}1084510846/* collect bss info from Beacon and Probe request/response frames. */10847u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSID_EX *bssid)10848{10849int i;10850sint len;10851u8 *p;10852u8 rf_path;10853u16 val16, subtype;10854u8 *pframe = precv_frame->u.hdr.rx_data;10855u32 packet_len = precv_frame->u.hdr.len;10856u8 ie_offset;10857HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);10858struct registry_priv *pregistrypriv = &padapter->registrypriv;10859struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;10860struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);108611086210863len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);1086410865if (len > MAX_IE_SZ) {10866/* RTW_INFO("IE too long for survey event\n"); */10867return _FAIL;10868}1086910870_rtw_memset(bssid, 0, sizeof(WLAN_BSSID_EX));1087110872subtype = get_frame_sub_type(pframe);1087310874if (subtype == WIFI_BEACON) {10875bssid->Reserved[0] = BSS_TYPE_BCN;10876ie_offset = _BEACON_IE_OFFSET_;10877} else {10878/* FIXME : more type */10879if (subtype == WIFI_PROBERSP) {10880ie_offset = _PROBERSP_IE_OFFSET_;10881bssid->Reserved[0] = BSS_TYPE_PROB_RSP;10882} else if (subtype == WIFI_PROBEREQ) {10883ie_offset = _PROBEREQ_IE_OFFSET_;10884bssid->Reserved[0] = BSS_TYPE_PROB_REQ;10885} else {10886bssid->Reserved[0] = BSS_TYPE_UNDEF;10887ie_offset = _FIXED_IE_LENGTH_;10888}10889}1089010891bssid->Length = sizeof(WLAN_BSSID_EX) - MAX_IE_SZ + len;1089210893/* below is to copy the information element */10894bssid->IELength = len;10895_rtw_memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);1089610897/* get the signal strength */10898/* bssid->Rssi = precv_frame->u.hdr.attrib.SignalStrength; */ /* 0-100 index. */10899bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.recv_signal_power; /* in dBM.raw data */10900bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.signal_quality;/* in percentage */10901bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.signal_strength;/* in percentage */1090210903/* get rx_snr */10904if (precv_frame->u.hdr.attrib.data_rate >= DESC_RATE11M) {10905bssid->PhyInfo.is_cck_rate = 0;10906for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++)10907bssid->PhyInfo.rx_snr[rf_path] =10908precv_frame->u.hdr.attrib.phy_info.rx_snr[rf_path];10909} else10910bssid->PhyInfo.is_cck_rate = 1;1091110912#ifdef CONFIG_ANTENNA_DIVERSITY10913rtw_hal_get_odm_var(padapter, HAL_ODM_ANTDIV_SELECT, &(bssid->PhyInfo.Optimum_antenna), NULL);10914#endif1091510916/* checking SSID */10917p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);10918if (p == NULL) {10919RTW_INFO("marc: cannot find SSID for survey event\n");10920return _FAIL;10921}1092210923if (*(p + 1)) {10924if (len > NDIS_802_11_LENGTH_SSID) {10925RTW_INFO("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);10926return _FAIL;10927}10928_rtw_memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));10929bssid->Ssid.SsidLength = *(p + 1);10930} else10931bssid->Ssid.SsidLength = 0;1093210933_rtw_memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);1093410935/* checking rate info... */10936i = 0;10937p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);10938if (p != NULL) {10939if (len > NDIS_802_11_LENGTH_RATES_EX) {10940RTW_INFO("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);10941return _FAIL;10942}10943if (rtw_validate_value(_SUPPORTEDRATES_IE_, p+2, len) == _FALSE) {10944rtw_absorb_ssid_ifneed(padapter, bssid, pframe);10945RTW_DBG_DUMP("Invalidated Support Rate IE --", p, len+2);10946return _FAIL;10947}10948_rtw_memcpy(bssid->SupportedRates, (p + 2), len);10949i = len;10950}1095110952p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);10953if (p != NULL) {10954if (len > (NDIS_802_11_LENGTH_RATES_EX - i)) {10955RTW_INFO("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);10956return _FAIL;10957}10958if (rtw_validate_value(_EXT_SUPPORTEDRATES_IE_, p+2, len) == _FALSE) {10959rtw_absorb_ssid_ifneed(padapter, bssid, pframe);10960RTW_DBG_DUMP("Invalidated EXT Support Rate IE --", p, len+2);10961return _FAIL;10962}10963_rtw_memcpy(bssid->SupportedRates + i, (p + 2), len);10964}1096510966#ifdef CONFIG_P2P10967if (subtype == WIFI_PROBEREQ) {10968u8 *p2p_ie;10969u32 p2p_ielen;10970/* Set Listion Channel */10971p2p_ie = rtw_get_p2p_ie(bssid->IEs, bssid->IELength, NULL, &p2p_ielen);10972if (p2p_ie) {10973u32 attr_contentlen = 0;10974u8 listen_ch[5] = { 0x00 };1097510976rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, listen_ch, &attr_contentlen);10977bssid->Configuration.DSConfig = listen_ch[4];10978} else {10979/* use current channel */10980bssid->Configuration.DSConfig = padapter->mlmeextpriv.cur_channel;10981RTW_INFO("%s()-%d: Cannot get p2p_ie. set DSconfig to op_ch(%d)\n", __FUNCTION__, __LINE__, bssid->Configuration.DSConfig);10982}1098310984/* FIXME */10985bssid->InfrastructureMode = Ndis802_11Infrastructure;10986_rtw_memcpy(bssid->MacAddress, get_addr2_ptr(pframe), ETH_ALEN);10987bssid->Privacy = 1;10988return _SUCCESS;10989}10990#endif /* CONFIG_P2P */1099110992if (bssid->IELength < 12)10993return _FAIL;1099410995/* Checking for DSConfig */10996p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);1099710998bssid->Configuration.DSConfig = 0;10999bssid->Configuration.Length = 0;1100011001if (p)11002bssid->Configuration.DSConfig = *(p + 2);11003else {11004/* In 5G, some ap do not have DSSET IE */11005/* checking HT info for channel */11006p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);11007if (p) {11008struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);11009bssid->Configuration.DSConfig = HT_info->primary_channel;11010} else {11011/* use current channel */11012bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);11013}11014}1101511016_rtw_memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);11017bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod);1101811019val16 = rtw_get_capability((WLAN_BSSID_EX *)bssid);1102011021if ((val16 & 0x03) == cap_ESS) {11022bssid->InfrastructureMode = Ndis802_11Infrastructure;11023_rtw_memcpy(bssid->MacAddress, get_addr2_ptr(pframe), ETH_ALEN);11024} else if ((val16 & 0x03) == cap_IBSS){11025bssid->InfrastructureMode = Ndis802_11IBSS;11026_rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);11027} else if ((val16 & 0x03) == 0x00){11028u8 *mesh_id_ie, *mesh_conf_ie;11029sint mesh_id_ie_len, mesh_conf_ie_len;1103011031mesh_id_ie = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_MESH_ID, &mesh_id_ie_len, bssid->IELength - ie_offset);11032mesh_conf_ie = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_MESH_CONFIG, &mesh_conf_ie_len, bssid->IELength - ie_offset);11033if (mesh_id_ie || mesh_conf_ie) {11034if (!mesh_id_ie) {11035RTW_INFO("cannot find Mesh ID for survey event\n");11036return _FAIL;11037}11038if (mesh_id_ie_len) {11039if (mesh_id_ie_len > NDIS_802_11_LENGTH_SSID) {11040RTW_INFO("Mesh ID too long (%d) for survey event\n", mesh_id_ie_len);11041return _FAIL;11042}11043_rtw_memcpy(bssid->mesh_id.Ssid, (mesh_id_ie + 2), mesh_id_ie_len);11044bssid->mesh_id.SsidLength = mesh_id_ie_len;11045} else11046bssid->mesh_id.SsidLength = 0;1104711048if (!mesh_conf_ie) {11049RTW_INFO("cannot find Mesh config for survey event\n");11050return _FAIL;11051}11052if (mesh_conf_ie_len != 7) {11053RTW_INFO("invalid Mesh conf IE len (%d) for survey event\n", mesh_conf_ie_len);11054return _FAIL;11055}1105611057bssid->InfrastructureMode = Ndis802_11_mesh;11058_rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);11059} else {11060/* default cases */11061bssid->InfrastructureMode = Ndis802_11IBSS;11062_rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);11063}11064}1106511066if (val16 & BIT(4))11067bssid->Privacy = 1;11068else11069bssid->Privacy = 0;1107011071bssid->Configuration.ATIMWindow = 0;1107211073/* 20/40 BSS Coexistence check */11074if ((pregistrypriv->wifi_spec == 1) && (_FALSE == pmlmeinfo->bwmode_updated)) {11075struct mlme_priv *pmlmepriv = &padapter->mlmepriv;11076#ifdef CONFIG_80211N_HT11077p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);11078if (p && len > 0) {11079struct HT_caps_element *pHT_caps;11080pHT_caps = (struct HT_caps_element *)(p + 2);1108111082if (pHT_caps->u.HT_cap_element.HT_caps_info & BIT(14))11083pmlmepriv->num_FortyMHzIntolerant++;11084} else11085pmlmepriv->num_sta_no_ht++;11086#endif /* CONFIG_80211N_HT */1108711088}1108911090#if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 111091if (strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {11092RTW_INFO("Receiving %s("MAC_FMT", DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n"11093, bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig11094, rtw_get_oper_ch(padapter)11095, bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi11096);11097}11098#endif1109911100/* mark bss info receving from nearby channel as SignalQuality 101 */11101if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))11102bssid->PhyInfo.SignalQuality = 101;1110311104#ifdef CONFIG_RTW_80211K11105p = rtw_get_ie(bssid->IEs + ie_offset, _EID_RRM_EN_CAP_IE_, &len, bssid->IELength - ie_offset);11106if (p)11107_rtw_memcpy(bssid->PhyInfo.rm_en_cap, (p + 2), *(p + 1));1110811109/* save freerun counter */11110bssid->PhyInfo.free_cnt = precv_frame->u.hdr.attrib.free_cnt;11111#endif11112return _SUCCESS;11113}1111411115void start_create_ibss(_adapter *padapter)11116{11117unsigned short caps;11118u8 val8;11119u8 join_type;11120struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11121struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);11122WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));11123u8 doiqk = _FALSE;11124pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;11125pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);1112611127/* update wireless mode */11128update_wireless_mode(padapter);1112911130/* udpate capability */11131caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);11132update_capinfo(padapter, caps);11133if (caps & cap_IBSS) { /* adhoc master */11134/* set_opmode_cmd(padapter, adhoc); */ /* removed */1113511136val8 = 0xcf;11137rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));1113811139doiqk = _TRUE;11140rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);1114111142/* switch channel */11143set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);1114411145doiqk = _FALSE;11146rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);1114711148beacon_timing_control(padapter);1114911150/* set msr to WIFI_FW_ADHOC_STATE */11151pmlmeinfo->state = WIFI_FW_ADHOC_STATE;11152Set_MSR(padapter, (pmlmeinfo->state & 0x3));1115311154/* issue beacon */11155if (send_beacon(padapter) == _FAIL) {1115611157report_join_res(padapter, -1, WLAN_STATUS_UNSPECIFIED_FAILURE);11158pmlmeinfo->state = WIFI_FW_NULL_STATE;11159} else {11160rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);11161rtw_hal_rcr_set_chk_bssid(padapter, MLME_ADHOC_STARTED);11162join_type = 0;11163rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));1116411165report_join_res(padapter, 1, WLAN_STATUS_SUCCESS);11166pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;11167rtw_indicate_connect(padapter);11168}11169} else {11170RTW_INFO("start_create_ibss, invalid cap:%x\n", caps);11171return;11172}11173/* update bc/mc sta_info */11174update_bmc_sta(padapter);1117511176}1117711178void start_clnt_join(_adapter *padapter)11179{11180unsigned short caps;11181u8 val8;11182struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11183struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);11184WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));11185int beacon_timeout;11186u8 ASIX_ID[] = {0x00, 0x0E, 0xC6};1118711188/* update wireless mode */11189update_wireless_mode(padapter);1119011191/* udpate capability */11192caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);11193update_capinfo(padapter, caps);1119411195/* check if sta is ASIX peer and fix IOT issue if it is. */11196if (_rtw_memcmp(get_my_bssid(&pmlmeinfo->network) , ASIX_ID , 3)) {11197u8 iot_flag = _TRUE;11198rtw_hal_set_hwreg(padapter, HW_VAR_ASIX_IOT, (u8 *)(&iot_flag));11199}1120011201if (caps & cap_ESS) {11202Set_MSR(padapter, WIFI_FW_STATION_STATE);1120311204val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;1120511206#ifdef CONFIG_WAPI_SUPPORT11207if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI) {11208/* Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey. */11209val8 = 0x4c;11210}11211#endif11212rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));1121311214#ifdef CONFIG_DEAUTH_BEFORE_CONNECT11215/* Because of AP's not receiving deauth before */11216/* AP may: 1)not response auth or 2)deauth us after link is complete */11217/* issue deauth before issuing auth to deal with the situation */1121811219/* Commented by Albert 2012/07/21 */11220/* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */11221{11222#ifdef CONFIG_P2P11223_queue *queue = &(padapter->mlmepriv.scanned_queue);11224_list *head = get_list_head(queue);11225_list *pos = get_next(head);11226struct wlan_network *scanned = NULL;11227u8 ie_offset = 0;11228_irqL irqL;11229bool has_p2p_ie = _FALSE;1123011231_enter_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL);1123211233for (pos = get_next(head); !rtw_end_of_queue_search(head, pos); pos = get_next(pos)) {1123411235scanned = LIST_CONTAINOR(pos, struct wlan_network, list);1123611237if (_rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE11238&& _rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE11239) {11240ie_offset = (scanned->network.Reserved[0] == BSS_TYPE_PROB_REQ ? 0 : 12);11241if (rtw_get_p2p_ie(scanned->network.IEs + ie_offset, scanned->network.IELength - ie_offset, NULL, NULL))11242has_p2p_ie = _TRUE;11243break;11244}11245}1124611247_exit_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL);1124811249if (scanned == NULL || rtw_end_of_queue_search(head, pos) || has_p2p_ie == _FALSE)11250#endif /* CONFIG_P2P */11251/* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */11252issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);11253}11254#endif /* CONFIG_DEAUTH_BEFORE_CONNECT */1125511256/* here wait for receiving the beacon to start auth */11257/* and enable a timer */11258beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);11259set_link_timer(pmlmeext, beacon_timeout);11260_set_timer(&padapter->mlmepriv.assoc_timer,11261(REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO * REASSOC_LIMIT) + beacon_timeout);1126211263#ifdef CONFIG_RTW_80211R11264if (rtw_ft_roam(padapter)) {11265rtw_ft_start_clnt_join(padapter);11266} else11267#endif11268{11269rtw_sta_linking_test_set_start();11270pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;11271}11272} else if (caps & cap_IBSS) { /* adhoc client */11273Set_MSR(padapter, WIFI_FW_ADHOC_STATE);1127411275val8 = 0xcf;11276rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));1127711278beacon_timing_control(padapter);1127911280pmlmeinfo->state = WIFI_FW_ADHOC_STATE;1128111282report_join_res(padapter, 1, WLAN_STATUS_SUCCESS);11283} else {11284/* RTW_INFO("marc: invalid cap:%x\n", caps); */11285return;11286}1128711288}1128911290void start_clnt_auth(_adapter *padapter)11291{11292struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11293struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1129411295_cancel_timer_ex(&pmlmeext->link_timer);1129611297pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);11298pmlmeinfo->state |= WIFI_FW_AUTH_STATE;1129911300pmlmeinfo->auth_seq = 1;11301pmlmeinfo->reauth_count = 0;11302pmlmeinfo->reassoc_count = 0;11303pmlmeinfo->link_count = 0;11304pmlmeext->retry = 0;1130511306#ifdef CONFIG_RTW_80211R11307if (rtw_ft_roam(padapter)) {11308rtw_ft_set_status(padapter, RTW_FT_AUTHENTICATING_STA);11309RTW_PRINT("start ft auth\n");11310} else11311#endif11312RTW_PRINT("start auth\n");1131311314#ifdef CONFIG_IOCTL_CFG8021111315if (rtw_sec_chk_auth_type(padapter, NL80211_AUTHTYPE_SAE)) {11316if (rtw_cached_pmkid(padapter, get_my_bssid(&pmlmeinfo->network)) != -1) {11317RTW_INFO("SAE: PMKSA cache entry found\n");11318padapter->securitypriv.auth_alg = WLAN_AUTH_OPEN;11319goto no_external_auth;11320}1132111322RTW_PRINT("SAE: start external auth\n");11323rtw_cfg80211_external_auth_request(padapter, NULL);11324return;11325}11326no_external_auth:11327#endif /* CONFIG_IOCTL_CFG80211 */1132811329issue_auth(padapter, NULL, 0);1133011331set_link_timer(pmlmeext, REAUTH_TO);1133211333}113341133511336void start_clnt_assoc(_adapter *padapter)11337{11338struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11339struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1134011341_cancel_timer_ex(&pmlmeext->link_timer);1134211343pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));11344pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);1134511346#ifdef CONFIG_RTW_80211R11347if (rtw_ft_roam(padapter))11348issue_reassocreq(padapter);11349else11350#endif11351issue_assocreq(padapter);1135211353set_link_timer(pmlmeext, REASSOC_TO);11354}1135511356unsigned int receive_disconnect(_adapter *padapter, unsigned char *MacAddr, unsigned short reason, u8 locally_generated)11357{11358struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11359struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1136011361if (!(_rtw_memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))11362return _SUCCESS;1136311364RTW_INFO("%s\n", __FUNCTION__);1136511366#ifdef CONFIG_RTW_REPEATER_SON11367rtw_rson_do_disconnect(padapter);11368#endif11369if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {11370if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {11371if (report_del_sta_event(padapter, MacAddr, reason, _TRUE, locally_generated) != _FAIL)11372pmlmeinfo->state = WIFI_FW_NULL_STATE;11373} else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {11374if (report_join_res(padapter, -2, reason) != _FAIL)11375pmlmeinfo->state = WIFI_FW_NULL_STATE;11376} else11377RTW_INFO(FUNC_ADPT_FMT" - End to Disconnect\n", FUNC_ADPT_ARG(padapter));11378#ifdef CONFIG_RTW_80211R11379rtw_ft_roam_status_reset(padapter);11380#endif11381#ifdef CONFIG_RTW_WNM11382rtw_wnm_reset_btm_state(padapter);11383#endif11384}1138511386return _SUCCESS;11387}1138811389#ifdef CONFIG_80211D11390static void process_80211d(PADAPTER padapter, WLAN_BSSID_EX *bssid)11391{11392struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);11393struct registry_priv *pregistrypriv;11394struct mlme_ext_priv *pmlmeext;11395RT_CHANNEL_INFO *chplan_new;11396u8 channel;11397u8 i;113981139911400pregistrypriv = &padapter->registrypriv;11401pmlmeext = &padapter->mlmeextpriv;1140211403/* Adjust channel plan by AP Country IE */11404if (pregistrypriv->enable80211d11405&& (!pmlmeext->update_channel_plan_by_ap_done)) {11406u8 *ie, *p;11407u32 len;11408RT_CHANNEL_PLAN chplan_ap;11409RT_CHANNEL_INFO *chplan_sta = NULL;11410u8 country[4];11411u8 fcn; /* first channel number */11412u8 noc; /* number of channel */11413u8 j, k;1141411415ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);11416if (!ie)11417return;11418if (len < 6)11419return;1142011421ie += 2;11422p = ie;11423ie += len;1142411425_rtw_memset(country, 0, 4);11426_rtw_memcpy(country, p, 3);11427p += 3;11428RTW_INFO("%s: 802.11d country=%s\n", __FUNCTION__, country);1142911430i = 0;11431while ((ie - p) >= 3) {11432fcn = *(p++);11433noc = *(p++);11434p++;1143511436for (j = 0; j < noc; j++) {11437if (fcn <= 14)11438channel = fcn + j; /* 2.4 GHz */11439else11440channel = fcn + j * 4; /* 5 GHz */1144111442chplan_ap.Channel[i++] = channel;11443}11444}11445chplan_ap.Len = i;1144611447#ifdef CONFIG_RTW_DEBUG11448i = 0;11449RTW_INFO("%s: AP[%s] channel plan {", __FUNCTION__, bssid->Ssid.Ssid);11450while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0)) {11451_RTW_INFO("%02d,", chplan_ap.Channel[i]);11452i++;11453}11454_RTW_INFO("}\n");11455#endif1145611457chplan_sta = rtw_malloc(sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM);11458if (!chplan_sta)11459goto done_update_chplan_from_ap;1146011461_rtw_memcpy(chplan_sta, rfctl->channel_set, sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM);11462#ifdef CONFIG_RTW_DEBUG11463i = 0;11464RTW_INFO("%s: STA channel plan {", __FUNCTION__);11465while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {11466_RTW_INFO("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType == SCAN_PASSIVE ? 'p' : 'a');11467i++;11468}11469_RTW_INFO("}\n");11470#endif1147111472_rtw_memset(rfctl->channel_set, 0, sizeof(rfctl->channel_set));11473chplan_new = rfctl->channel_set;1147411475i = j = k = 0;11476if (pregistrypriv->wireless_mode & WIRELESS_11G) {11477do {11478if ((i == MAX_CHANNEL_NUM)11479|| (chplan_sta[i].ChannelNum == 0)11480|| (chplan_sta[i].ChannelNum > 14))11481break;1148211483if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))11484break;1148511486if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {11487chplan_new[k].ChannelNum = chplan_ap.Channel[j];11488chplan_new[k].ScanType = SCAN_ACTIVE;11489i++;11490j++;11491k++;11492} else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {11493chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;11494#if 011495chplan_new[k].ScanType = chplan_sta[i].ScanType;11496#else11497chplan_new[k].ScanType = SCAN_PASSIVE;11498#endif11499i++;11500k++;11501} else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {11502chplan_new[k].ChannelNum = chplan_ap.Channel[j];11503chplan_new[k].ScanType = SCAN_ACTIVE;11504j++;11505k++;11506}11507} while (1);1150811509/* change AP not support channel to Passive scan */11510while ((i < MAX_CHANNEL_NUM)11511&& (chplan_sta[i].ChannelNum != 0)11512&& (chplan_sta[i].ChannelNum <= 14)) {11513chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;11514#if 011515chplan_new[k].ScanType = chplan_sta[i].ScanType;11516#else11517chplan_new[k].ScanType = SCAN_PASSIVE;11518#endif11519i++;11520k++;11521}1152211523/* add channel AP supported */11524while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {11525chplan_new[k].ChannelNum = chplan_ap.Channel[j];11526chplan_new[k].ScanType = SCAN_ACTIVE;11527j++;11528k++;11529}11530} else {11531/* keep original STA 2.4G channel plan */11532while ((i < MAX_CHANNEL_NUM)11533&& (chplan_sta[i].ChannelNum != 0)11534&& (chplan_sta[i].ChannelNum <= 14)) {11535chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;11536chplan_new[k].ScanType = chplan_sta[i].ScanType;11537i++;11538k++;11539}1154011541/* skip AP 2.4G channel plan */11542while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))11543j++;11544}1154511546if (pregistrypriv->wireless_mode & WIRELESS_11A) {11547do {11548if ((i >= MAX_CHANNEL_NUM)11549|| (chplan_sta[i].ChannelNum == 0))11550break;1155111552if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))11553break;1155411555if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {11556chplan_new[k].ChannelNum = chplan_ap.Channel[j];11557chplan_new[k].ScanType = SCAN_ACTIVE;11558i++;11559j++;11560k++;11561} else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {11562chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;11563#if 011564chplan_new[k].ScanType = chplan_sta[i].ScanType;11565#else11566chplan_new[k].ScanType = SCAN_PASSIVE;11567#endif11568i++;11569k++;11570} else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {11571chplan_new[k].ChannelNum = chplan_ap.Channel[j];11572chplan_new[k].ScanType = SCAN_ACTIVE;11573j++;11574k++;11575}11576} while (1);1157711578/* change AP not support channel to Passive scan */11579while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {11580chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;11581#if 011582chplan_new[k].ScanType = chplan_sta[i].ScanType;11583#else11584chplan_new[k].ScanType = SCAN_PASSIVE;11585#endif11586i++;11587k++;11588}1158911590/* add channel AP supported */11591while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) {11592chplan_new[k].ChannelNum = chplan_ap.Channel[j];11593chplan_new[k].ScanType = SCAN_ACTIVE;11594j++;11595k++;11596}11597} else {11598/* keep original STA 5G channel plan */11599while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {11600chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;11601chplan_new[k].ScanType = chplan_sta[i].ScanType;11602i++;11603k++;11604}11605}1160611607pmlmeext->update_channel_plan_by_ap_done = 1;1160811609#ifdef CONFIG_RTW_DEBUG11610k = 0;11611RTW_INFO("%s: new STA channel plan {", __FUNCTION__);11612while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) {11613_RTW_INFO("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType == SCAN_PASSIVE ? 'p' : 'c');11614k++;11615}11616_RTW_INFO("}\n");11617#endif1161811619#if 011620/* recover the right channel index */11621channel = chplan_sta[pmlmeext->sitesurvey_res.channel_idx].ChannelNum;11622k = 0;11623while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) {11624if (chplan_new[k].ChannelNum == channel) {11625RTW_INFO("%s: change mlme_ext sitesurvey channel index from %d to %d\n",11626__FUNCTION__, pmlmeext->sitesurvey_res.channel_idx, k);11627pmlmeext->sitesurvey_res.channel_idx = k;11628break;11629}11630k++;11631}11632#endif1163311634done_update_chplan_from_ap:11635if (chplan_sta)11636rtw_mfree(chplan_sta, sizeof(RT_CHANNEL_INFO) * MAX_CHANNEL_NUM);11637}11638}11639#endif1164011641/****************************************************************************1164211643Following are the functions to report events1164411645*****************************************************************************/1164611647void report_survey_event(_adapter *padapter, union recv_frame *precv_frame)11648{11649struct cmd_obj *pcmd_obj;11650u8 *pevtcmd;11651u32 cmdsz;11652struct survey_event *psurvey_evt;11653struct C2HEvent_Header *pc2h_evt_hdr;11654struct mlme_ext_priv *pmlmeext;11655struct cmd_priv *pcmdpriv;11656/* u8 *pframe = precv_frame->u.hdr.rx_data; */11657/* uint len = precv_frame->u.hdr.len; */11658RT_CHANNEL_INFO *chset;11659int ch_set_idx = -1;1166011661if (!padapter)11662return;1166311664pmlmeext = &padapter->mlmeextpriv;11665pcmdpriv = &padapter->cmdpriv;11666chset = adapter_to_chset(padapter);1166711668pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));11669if (pcmd_obj == NULL)11670return;1167111672cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));11673pevtcmd = (u8 *)rtw_zmalloc(cmdsz);11674if (pevtcmd == NULL) {11675rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));11676return;11677}1167811679_rtw_init_listhead(&pcmd_obj->list);1168011681pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);11682pcmd_obj->cmdsz = cmdsz;11683pcmd_obj->parmbuf = pevtcmd;1168411685pcmd_obj->rsp = NULL;11686pcmd_obj->rspsz = 0;1168711688pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);11689pc2h_evt_hdr->len = sizeof(struct survey_event);11690pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);11691pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);1169211693psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));1169411695if (collect_bss_info(padapter, precv_frame, (WLAN_BSSID_EX *)&psurvey_evt->bss) == _FAIL) {11696rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));11697rtw_mfree((u8 *)pevtcmd, cmdsz);11698return;11699}1170011701#ifdef CONFIG_80211D11702process_80211d(padapter, &psurvey_evt->bss);11703#endif1170411705ch_set_idx = rtw_chset_search_ch(chset, psurvey_evt->bss.Configuration.DSConfig);11706if (ch_set_idx >= 0) {11707if (psurvey_evt->bss.InfrastructureMode == Ndis802_11Infrastructure) {11708if (chset[ch_set_idx].ScanType == SCAN_PASSIVE11709&& !rtw_is_dfs_ch(psurvey_evt->bss.Configuration.DSConfig)11710) {11711RTW_INFO("%s: change ch:%d to active\n", __func__, psurvey_evt->bss.Configuration.DSConfig);11712chset[ch_set_idx].ScanType = SCAN_ACTIVE;11713}11714#ifdef CONFIG_DFS11715if (hidden_ssid_ap(&psurvey_evt->bss))11716chset[ch_set_idx].hidden_bss_cnt++;11717#endif11718}11719}1172011721rtw_enqueue_cmd(pcmdpriv, pcmd_obj);1172211723pmlmeext->sitesurvey_res.bss_cnt++;1172411725return;1172611727}1172811729void report_surveydone_event(_adapter *padapter)11730{11731struct cmd_obj *pcmd_obj;11732u8 *pevtcmd;11733u32 cmdsz;11734struct surveydone_event *psurveydone_evt;11735struct C2HEvent_Header *pc2h_evt_hdr;11736struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11737struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1173811739pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));11740if (pcmd_obj == NULL)11741return;1174211743cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));11744pevtcmd = (u8 *)rtw_zmalloc(cmdsz);11745if (pevtcmd == NULL) {11746rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));11747return;11748}1174911750_rtw_init_listhead(&pcmd_obj->list);1175111752pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);11753pcmd_obj->cmdsz = cmdsz;11754pcmd_obj->parmbuf = pevtcmd;1175511756pcmd_obj->rsp = NULL;11757pcmd_obj->rspsz = 0;1175811759pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);11760pc2h_evt_hdr->len = sizeof(struct surveydone_event);11761pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);11762pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);1176311764psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));11765psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;1176611767RTW_INFO("survey done event(%x) band:%d for "ADPT_FMT"\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter));1176811769rtw_enqueue_cmd(pcmdpriv, pcmd_obj);1177011771return;1177211773}1177411775u32 report_join_res(_adapter *padapter, int aid_res, u16 status)11776{11777struct cmd_obj *pcmd_obj;11778u8 *pevtcmd;11779u32 cmdsz;11780struct joinbss_event *pjoinbss_evt;11781struct C2HEvent_Header *pc2h_evt_hdr;11782struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11783struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);11784struct cmd_priv *pcmdpriv = &padapter->cmdpriv;11785u32 ret = _FAIL;1178611787pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));11788if (pcmd_obj == NULL)11789goto exit;1179011791cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));11792pevtcmd = (u8 *)rtw_zmalloc(cmdsz);11793if (pevtcmd == NULL) {11794rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));11795goto exit;11796}1179711798_rtw_init_listhead(&pcmd_obj->list);1179911800pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);11801pcmd_obj->cmdsz = cmdsz;11802pcmd_obj->parmbuf = pevtcmd;1180311804pcmd_obj->rsp = NULL;11805pcmd_obj->rspsz = 0;1180611807pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);11808pc2h_evt_hdr->len = sizeof(struct joinbss_event);11809pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);11810pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);1181111812pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));11813_rtw_memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));11814pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = aid_res;1181511816RTW_INFO("report_join_res(%d, %u)\n", aid_res, status);118171181811819rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network, status);118201182111822ret = rtw_enqueue_cmd(pcmdpriv, pcmd_obj);1182311824exit:11825return ret;11826}1182711828void report_wmm_edca_update(_adapter *padapter)11829{11830struct cmd_obj *pcmd_obj;11831u8 *pevtcmd;11832u32 cmdsz;11833struct wmm_event *pwmm_event;11834struct C2HEvent_Header *pc2h_evt_hdr;11835struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11836struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1183711838pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));11839if (pcmd_obj == NULL)11840return;1184111842cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));11843pevtcmd = (u8 *)rtw_zmalloc(cmdsz);11844if (pevtcmd == NULL) {11845rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));11846return;11847}1184811849_rtw_init_listhead(&pcmd_obj->list);1185011851pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);11852pcmd_obj->cmdsz = cmdsz;11853pcmd_obj->parmbuf = pevtcmd;1185411855pcmd_obj->rsp = NULL;11856pcmd_obj->rspsz = 0;1185711858pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);11859pc2h_evt_hdr->len = sizeof(struct wmm_event);11860pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM);11861pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);1186211863pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header));11864pwmm_event->wmm = 0;1186511866rtw_enqueue_cmd(pcmdpriv, pcmd_obj);1186711868return;1186911870}1187111872u32 report_del_sta_event(_adapter *padapter, unsigned char *MacAddr, unsigned short reason, bool enqueue, u8 locally_generated)11873{11874struct cmd_obj *pcmd_obj;11875u8 *pevtcmd;11876u32 cmdsz;11877struct sta_info *psta;11878int mac_id = -1;11879struct stadel_event *pdel_sta_evt;11880struct C2HEvent_Header *pc2h_evt_hdr;11881struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11882struct cmd_priv *pcmdpriv = &padapter->cmdpriv;11883u8 res = _SUCCESS;1188411885/* prepare cmd parameter */11886cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));11887pevtcmd = (u8 *)rtw_zmalloc(cmdsz);11888if (pevtcmd == NULL) {11889res = _FAIL;11890goto exit;11891}1189211893pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);11894pc2h_evt_hdr->len = sizeof(struct stadel_event);11895pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);11896pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);1189711898pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));11899_rtw_memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);11900_rtw_memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);11901psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);11902if (psta)11903mac_id = (int)psta->cmn.mac_id;11904else11905mac_id = (-1);11906pdel_sta_evt->mac_id = mac_id;11907pdel_sta_evt->locally_generated = locally_generated;1190811909if (!enqueue) {11910/* do directly */11911rtw_stadel_event_callback(padapter, (u8 *)pdel_sta_evt);11912rtw_mfree(pevtcmd, cmdsz);11913} else {11914pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));11915if (pcmd_obj == NULL) {11916rtw_mfree(pevtcmd, cmdsz);11917res = _FAIL;11918goto exit;11919}1192011921_rtw_init_listhead(&pcmd_obj->list);11922pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);11923pcmd_obj->cmdsz = cmdsz;11924pcmd_obj->parmbuf = pevtcmd;1192511926pcmd_obj->rsp = NULL;11927pcmd_obj->rspsz = 0;1192811929res = rtw_enqueue_cmd(pcmdpriv, pcmd_obj);11930}1193111932exit:1193311934RTW_INFO(FUNC_ADPT_FMT" "MAC_FMT" mac_id=%d, enqueue:%d, res:%u\n"11935, FUNC_ADPT_ARG(padapter), MAC_ARG(MacAddr), mac_id, enqueue, res);1193611937return res;11938}1193911940void report_add_sta_event(_adapter *padapter, unsigned char *MacAddr)11941{11942struct cmd_obj *pcmd_obj;11943u8 *pevtcmd;11944u32 cmdsz;11945struct stassoc_event *padd_sta_evt;11946struct C2HEvent_Header *pc2h_evt_hdr;11947struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;11948struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1194911950pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));11951if (pcmd_obj == NULL)11952return;1195311954cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));11955pevtcmd = (u8 *)rtw_zmalloc(cmdsz);11956if (pevtcmd == NULL) {11957rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));11958return;11959}1196011961_rtw_init_listhead(&pcmd_obj->list);1196211963pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);11964pcmd_obj->cmdsz = cmdsz;11965pcmd_obj->parmbuf = pevtcmd;1196611967pcmd_obj->rsp = NULL;11968pcmd_obj->rspsz = 0;1196911970pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);11971pc2h_evt_hdr->len = sizeof(struct stassoc_event);11972pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);11973pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);1197411975padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));11976_rtw_memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);1197711978RTW_INFO("report_add_sta_event: add STA\n");1197911980rtw_enqueue_cmd(pcmdpriv, pcmd_obj);1198111982return;11983}119841198511986bool rtw_port_switch_chk(_adapter *adapter)11987{11988bool switch_needed = _FALSE;11989#ifdef CONFIG_CONCURRENT_MODE11990#ifdef CONFIG_RUNTIME_PORT_SWITCH11991struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);11992struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(dvobj);11993_adapter *if_port0 = NULL;11994_adapter *if_port1 = NULL;11995struct mlme_ext_info *if_port0_mlmeinfo = NULL;11996struct mlme_ext_info *if_port1_mlmeinfo = NULL;11997int i;1199811999for (i = 0; i < dvobj->iface_nums; i++) {12000if (get_hw_port(dvobj->padapters[i]) == HW_PORT0) {12001if_port0 = dvobj->padapters[i];12002if_port0_mlmeinfo = &(if_port0->mlmeextpriv.mlmext_info);12003} else if (get_hw_port(dvobj->padapters[i]) == HW_PORT1) {12004if_port1 = dvobj->padapters[i];12005if_port1_mlmeinfo = &(if_port1->mlmeextpriv.mlmext_info);12006}12007}1200812009if (if_port0 == NULL) {12010rtw_warn_on(1);12011goto exit;12012}1201312014if (if_port1 == NULL) {12015rtw_warn_on(1);12016goto exit;12017}1201812019#ifdef DBG_RUNTIME_PORT_SWITCH12020RTW_INFO(FUNC_ADPT_FMT" wowlan_mode:%u\n"12021ADPT_FMT", port0, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n"12022ADPT_FMT", port1, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n",12023FUNC_ADPT_ARG(adapter), pwrctl->wowlan_mode,12024ADPT_ARG(if_port0), if_port0_mlmeinfo->state, rtw_p2p_state(&if_port0->wdinfo), rtw_p2p_chk_state(&if_port0->wdinfo, P2P_STATE_NONE),12025ADPT_ARG(if_port1), if_port1_mlmeinfo->state, rtw_p2p_state(&if_port1->wdinfo), rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE));12026#endif /* DBG_RUNTIME_PORT_SWITCH */1202712028#ifdef CONFIG_WOWLAN12029/* WOWLAN interface(primary, for now) should be port0 */12030if (pwrctl->wowlan_mode == _TRUE) {12031if (!is_primary_adapter(if_port0)) {12032RTW_INFO("%s "ADPT_FMT" enable WOWLAN\n", __func__, ADPT_ARG(if_port1));12033switch_needed = _TRUE;12034}12035goto exit;12036}12037#endif /* CONFIG_WOWLAN */1203812039/* AP/Mesh should use port0 for ctl frame's ack */12040if ((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {12041RTW_INFO("%s "ADPT_FMT" is AP/GO/Mesh\n", __func__, ADPT_ARG(if_port1));12042switch_needed = _TRUE;12043goto exit;12044}1204512046/* GC should use port0 for p2p ps */12047if (((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)12048&& (if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)12049#ifdef CONFIG_P2P12050&& !rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE)12051#endif12052&& !check_fwstate(&if_port1->mlmepriv, WIFI_UNDER_WPS)12053) {12054RTW_INFO("%s "ADPT_FMT" is GC\n", __func__, ADPT_ARG(if_port1));12055switch_needed = _TRUE;12056goto exit;12057}1205812059/* port1 linked, but port0 not linked */12060if ((if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)12061&& !(if_port0_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)12062&& ((if_port0_mlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)12063) {12064RTW_INFO("%s "ADPT_FMT" is SINGLE_LINK\n", __func__, ADPT_ARG(if_port1));12065switch_needed = _TRUE;12066goto exit;12067}1206812069exit:12070#ifdef DBG_RUNTIME_PORT_SWITCH12071RTW_INFO(FUNC_ADPT_FMT" ret:%d\n", FUNC_ADPT_ARG(adapter), switch_needed);12072#endif /* DBG_RUNTIME_PORT_SWITCH */12073#endif /* CONFIG_RUNTIME_PORT_SWITCH */12074#endif /* CONFIG_CONCURRENT_MODE */12075return switch_needed;12076}1207712078/****************************************************************************1207912080Following are the event callback functions1208112082*****************************************************************************/1208312084/* for sta/adhoc mode */12085void update_sta_info(_adapter *padapter, struct sta_info *psta)12086{12087_irqL irqL;12088struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);12089struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;12090struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1209112092/* ERP */12093VCS_update(padapter, psta);1209412095#ifdef CONFIG_80211N_HT12096/* HT */12097if (pmlmepriv->htpriv.ht_option) {12098psta->htpriv.ht_option = _TRUE;1209912100psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;1210112102psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2;1210312104if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))12105psta->htpriv.sgi_20m = _TRUE;1210612107if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))12108psta->htpriv.sgi_40m = _TRUE;1210912110psta->qos_option = _TRUE;1211112112psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;12113psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;12114psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;1211512116_rtw_memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct rtw_ieee80211_ht_cap));12117#ifdef CONFIG_BEAMFORMING12118psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;12119psta->cmn.bf_info.ht_beamform_cap = pmlmepriv->htpriv.beamform_cap;12120#endif12121} else12122#endif /* CONFIG_80211N_HT */12123{12124#ifdef CONFIG_80211N_HT12125psta->htpriv.ht_option = _FALSE;12126psta->htpriv.ampdu_enable = _FALSE;12127psta->htpriv.tx_amsdu_enable = _FALSE;12128psta->htpriv.sgi_20m = _FALSE;12129psta->htpriv.sgi_40m = _FALSE;12130#endif /* CONFIG_80211N_HT */12131psta->qos_option = _FALSE;1213212133}1213412135#ifdef CONFIG_80211N_HT12136psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;1213712138psta->htpriv.agg_enable_bitmap = 0x0;/* reset */12139psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */12140#endif /* CONFIG_80211N_HT */1214112142psta->cmn.bw_mode = pmlmeext->cur_bwmode;1214312144/* QoS */12145if (pmlmepriv->qospriv.qos_option)12146psta->qos_option = _TRUE;1214712148#ifdef CONFIG_80211AC_VHT12149_rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));12150if (psta->vhtpriv.vht_option) {12151psta->cmn.ra_info.is_vht_enable = _TRUE;12152#ifdef CONFIG_BEAMFORMING12153psta->vhtpriv.beamform_cap = pmlmepriv->vhtpriv.beamform_cap;12154psta->cmn.bf_info.vht_beamform_cap = pmlmepriv->vhtpriv.beamform_cap;12155#endif /*CONFIG_BEAMFORMING*/12156}12157#endif /* CONFIG_80211AC_VHT */12158psta->cmn.ra_info.is_support_sgi = query_ra_short_GI(psta, rtw_get_tx_bw_mode(padapter, psta));12159update_ldpc_stbc_cap(psta);1216012161_enter_critical_bh(&psta->lock, &irqL);12162psta->state = _FW_LINKED;12163_exit_critical_bh(&psta->lock, &irqL);1216412165}1216612167static void rtw_mlmeext_disconnect(_adapter *padapter)12168{12169struct mlme_priv *pmlmepriv = &padapter->mlmepriv;12170struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;12171struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);12172u8 self_action = MLME_ACTION_UNKNOWN;12173u8 state_backup = (pmlmeinfo->state & 0x03);12174u8 ASIX_ID[] = {0x00, 0x0E, 0xC6};1217512176if (MLME_IS_AP(padapter))12177self_action = MLME_AP_STOPPED;12178else if (MLME_IS_MESH(padapter))12179self_action = MLME_MESH_STOPPED;12180else if (MLME_IS_STA(padapter))12181self_action = MLME_STA_DISCONNECTED;12182else if (MLME_IS_ADHOC(padapter) || MLME_IS_ADHOC_MASTER(padapter))12183self_action = MLME_ADHOC_STOPPED;12184else {12185RTW_INFO("state:0x%x\n", MLME_STATE(padapter));12186rtw_warn_on(1);12187}1218812189/* set_opmode_cmd(padapter, infra_client_with_mlme); */12190#ifdef CONFIG_HW_P0_TSF_SYNC12191if (self_action == MLME_STA_DISCONNECTED)12192correct_TSF(padapter, self_action);12193#endif12194rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);12195rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);12196if (self_action == MLME_STA_DISCONNECTED)12197rtw_hal_rcr_set_chk_bssid(padapter, self_action);1219812199/* set MSR to no link state->infra. mode */12200Set_MSR(padapter, _HW_STATE_STATION_);1220112202/* check if sta is ASIX peer and fix IOT issue if it is. */12203if (_rtw_memcmp(get_my_bssid(&pmlmeinfo->network) , ASIX_ID , 3)) {12204u8 iot_flag = _FALSE;12205rtw_hal_set_hwreg(padapter, HW_VAR_ASIX_IOT, (u8 *)(&iot_flag));12206}12207pmlmeinfo->state = WIFI_FW_NULL_STATE;1220812209#ifdef CONFIG_MCC_MODE12210/* mcc disconnect setting before download LPS rsvd page */12211rtw_hal_set_mcc_setting_disconnect(padapter);12212#endif /* CONFIG_MCC_MODE */1221312214if (state_backup == WIFI_FW_STATION_STATE) {12215if (rtw_port_switch_chk(padapter) == _TRUE) {12216rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);12217#ifdef CONFIG_LPS12218{12219_adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));12220if (port0_iface)12221rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, RTW_CMDF_DIRECTLY);12222}12223#endif12224}12225}1222612227/* switch to the 20M Hz mode after disconnect */12228pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;12229pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;12230#ifdef CONFIG_CTRL_TXSS_BY_TP12231pmlmeext->txss_1ss = _FALSE;12232#endif1223312234#ifdef CONFIG_FCS_MODE12235if (EN_FCS(padapter))12236rtw_hal_set_hwreg(padapter, HW_VAR_STOP_FCS_MODE, NULL);12237#endif1223812239if (!(MLME_IS_STA(padapter) && MLME_IS_OPCH_SW(padapter))) {12240/* DFS and channel status no need to check here for STA under OPCH_SW */12241u8 ch, bw, offset;1224212243#ifdef CONFIG_DFS_MASTER12244rtw_dfs_rd_en_decision(padapter, self_action, 0);12245#endif1224612247if (rtw_mi_get_ch_setting_union_no_self(padapter, &ch, &bw, &offset) != 0) {12248set_channel_bwmode(padapter, ch, offset, bw);12249rtw_mi_update_union_chan_inf(padapter, ch, offset, bw);12250}12251}1225212253flush_all_cam_entry(padapter);1225412255_cancel_timer_ex(&pmlmeext->link_timer);1225612257/* pmlmepriv->LinkDetectInfo.TrafficBusyState = _FALSE; */12258pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;12259pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;1226012261#ifdef CONFIG_TDLS12262padapter->tdlsinfo.ap_prohibited = _FALSE;1226312264/* For TDLS channel switch, currently we only allow it to work in wifi logo test mode */12265if (padapter->registrypriv.wifi_spec == 1)12266padapter->tdlsinfo.ch_switch_prohibited = _FALSE;12267#endif /* CONFIG_TDLS */1226812269#ifdef CONFIG_WMMPS_STA12270if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {12271/* reset currently related uapsd setting when the connection has broken */12272pmlmepriv->qospriv.uapsd_max_sp_len = 0;12273pmlmepriv->qospriv.uapsd_tid = 0;12274pmlmepriv->qospriv.uapsd_tid_delivery_enabled = 0;12275pmlmepriv->qospriv.uapsd_tid_trigger_enabled = 0;12276pmlmepriv->qospriv.uapsd_ap_supported = 0;12277}12278#endif /* CONFIG_WMMPS_STA */12279#ifdef CONFIG_RTS_FULL_BW12280rtw_set_rts_bw(padapter);12281#endif/*CONFIG_RTS_FULL_BW*/1228212283}1228412285void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res)12286{12287struct sta_info *psta;12288struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;12289struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);12290WLAN_BSSID_EX *cur_network = &(pmlmeinfo->network);12291struct sta_priv *pstapriv = &padapter->stapriv;12292u8 join_type;12293struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1229412295#ifndef CONFIG_IOCTL_CFG8021112296struct security_priv *psecuritypriv = &padapter->securitypriv;12297#endif1229812299if (pmlmepriv->wpa_phase == _TRUE)12300pmlmepriv->wpa_phase = _FALSE;1230112302if (join_res < 0) {12303join_type = 1;12304rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));12305rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);12306if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)12307rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_DISCONNECTED);1230812309goto exit_mlmeext_joinbss_event_callback;12310}1231112312#ifdef CONFIG_ARP_KEEP_ALIVE12313pmlmepriv->bGetGateway = 1;12314pmlmepriv->GetGatewayTryCnt = 0;12315#endif1231612317if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {12318/* update bc/mc sta_info */12319update_bmc_sta(padapter);12320}123211232212323/* turn on dynamic functions */12324/* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE); */1232512326/* update IOT-releated issue */12327update_IOT_info(padapter);1232812329#ifdef CONFIG_RTS_FULL_BW12330rtw_set_rts_bw(padapter);12331#endif/*CONFIG_RTS_FULL_BW*/1233212333rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);1233412335/* BCN interval */12336rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));1233712338/* udpate capability */12339update_capinfo(padapter, pmlmeinfo->capability);1234012341/* WMM, Update EDCA param */12342WMMOnAssocRsp(padapter);12343#ifdef CONFIG_80211N_HT12344/* HT */12345HTOnAssocRsp(padapter);12346#endif /* CONFIG_80211N_HT */12347#ifdef CONFIG_80211AC_VHT12348/* VHT */12349VHTOnAssocRsp(padapter);12350#endif1235112352psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);12353if (psta) { /* only for infra. mode */12354psta->wireless_mode = pmlmeext->cur_wireless_mode;1235512356/* set per sta rate after updating HT cap. */12357set_sta_rate(padapter, psta);1235812359rtw_sta_media_status_rpt(padapter, psta, 1);1236012361/* wakeup macid after join bss successfully to ensure12362the subsequent data frames can be sent out normally */12363rtw_hal_macid_wakeup(padapter, psta->cmn.mac_id);1236412365rtw_xmit_queue_clear(psta);12366}1236712368#ifndef CONFIG_IOCTL_CFG8021112369if (is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm))12370rtw_sec_restore_wep_key(padapter);12371#endif /* CONFIG_IOCTL_CFG80211 */1237212373if (rtw_port_switch_chk(padapter) == _TRUE)12374rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);1237512376join_type = 2;12377rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));1237812379if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {12380rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_CONNECTED);1238112382/* correcting TSF */12383correct_TSF(padapter, MLME_STA_CONNECTED);1238412385/* set_link_timer(pmlmeext, DISCONNECT_TO); */12386}1238712388#ifdef CONFIG_LPS12389#ifndef CONFIG_FW_MULTI_PORT_SUPPORT12390if (get_hw_port(padapter) == HW_PORT0)12391#endif12392rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, RTW_CMDF_DIRECTLY);12393#endif1239412395#ifdef CONFIG_BEAMFORMING12396if (psta)12397beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_ENTER, (u8 *)psta, sizeof(struct sta_info), 0);12398#endif/*CONFIG_BEAMFORMING*/1239912400exit_mlmeext_joinbss_event_callback:1240112402rtw_join_done_chk_ch(padapter, join_res);12403#ifdef CONFIG_RTW_REPEATER_SON12404rtw_rson_join_done(padapter);12405#endif1240612407#ifdef CONFIG_PCI_DYNAMIC_ASPM12408rtw_pci_dynamic_aspm_set_mode(padapter, ASPM_MODE_PERF);12409#endif1241012411RTW_INFO("=>%s - End to Connection without 4-way\n", __FUNCTION__);12412}1241312414/* currently only adhoc mode will go here */12415void mlmeext_sta_add_event_callback(_adapter *padapter, struct sta_info *psta)12416{12417struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);12418struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);12419u8 join_type;1242012421RTW_INFO("%s\n", __FUNCTION__);1242212423if ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) {12424if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */12425/* nothing to do */12426} else { /* adhoc client */12427/* update TSF Value */12428/* update_TSF(pmlmeext, pframe, len); */1242912430/* correcting TSF */12431correct_TSF(padapter, MLME_ADHOC_STARTED);1243212433/* start beacon */12434if (send_beacon(padapter) == _FAIL)12435rtw_warn_on(1);1243612437pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;12438}1243912440join_type = 2;12441rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));12442}1244312444/* update adhoc sta_info */12445update_sta_info(padapter, psta);1244612447rtw_hal_update_sta_ra_info(padapter, psta);1244812449/* ToDo: HT for Ad-hoc */12450psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);12451rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);1245212453/* rate radaptive */12454Update_RA_Entry(padapter, psta);12455}1245612457void mlmeext_sta_del_event_callback(_adapter *padapter)12458{12459if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))12460rtw_mlmeext_disconnect(padapter);12461}1246212463/****************************************************************************1246412465Following are the functions for the timer handlers1246612467*****************************************************************************/12468void _linked_info_dump(_adapter *padapter)12469{12470if (padapter->bLinkInfoDump) {12471rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, RTW_DBGDUMP);12472rtw_hal_set_odm_var(padapter, HAL_ODM_RX_INFO_DUMP, RTW_DBGDUMP, _FALSE);12473}12474}12475/********************************************************************1247612477When station does not receive any packet in MAX_CONTINUAL_NORXPACKET_COUNT*2 seconds,12478recipient station will teardown the block ack by issuing DELBA frame.1247912480*********************************************************************/12481void rtw_delba_check(_adapter *padapter, struct sta_info *psta, u8 from_timer)12482{12483int i = 0;12484int ret = _SUCCESS;12485struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;12486struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1248712488/*12489IOT issue,occur Broadcom ap(Buffalo WZR-D1800H,Netgear R6300).12490AP is originator.AP does not transmit unicast packets when STA response its BAR.12491This case probably occur ap issue BAR after AP builds BA.1249212493Follow 802.11 spec, STA shall maintain an inactivity timer for every negotiated Block Ack setup.12494The inactivity timer is not reset when MPDUs corresponding to other TIDs are received.12495*/12496if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM) {12497for (i = 0; i < TID_NUM ; i++) {12498if ((psta->recvreorder_ctrl[i].enable) &&12499(sta_rx_data_qos_pkts(psta, i) == sta_last_rx_data_qos_pkts(psta, i)) ) {12500if (_TRUE == rtw_inc_and_chk_continual_no_rx_packet(psta, i)) {12501/* send a DELBA frame to the peer STA with the Reason Code field set to TIMEOUT */12502if (!from_timer)12503ret = issue_del_ba_ex(padapter, psta->cmn.mac_addr, i, 39, 0, 3, 1);12504else12505issue_del_ba(padapter, psta->cmn.mac_addr, i, 39, 0);12506psta->recvreorder_ctrl[i].enable = _FALSE;12507if (ret != _FAIL)12508psta->recvreorder_ctrl[i].ampdu_size = RX_AMPDU_SIZE_INVALID;12509rtw_reset_continual_no_rx_packet(psta, i);12510}12511} else {12512/* The inactivity timer is reset when MPDUs to the TID is received. */12513rtw_reset_continual_no_rx_packet(psta, i);12514}12515}12516}12517}1251812519u8 chk_ap_is_alive(_adapter *padapter, struct sta_info *psta)12520{12521u8 ret = _FALSE;12522#ifdef DBG_EXPIRATION_CHK12523struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;12524struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1252512526RTW_INFO(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"12527/*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/12528", retry:%u\n"12529, FUNC_ADPT_ARG(padapter)12530, STA_RX_PKTS_DIFF_ARG(psta)12531, psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts12532, psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts12533/*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts12534, psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts12535, psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts12536, pmlmeinfo->bcn_interval*/12537, pmlmeext->retry12538);1253912540RTW_INFO(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter)12541, sta_tx_pkts(psta)12542, pmlmeinfo->link_count12543);12544#endif1254512546if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))12547&& sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)12548&& sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)12549)12550ret = _FALSE;12551else12552ret = _TRUE;1255312554sta_update_last_rx_pkts(psta);1255512556return ret;12557}1255812559u8 chk_adhoc_peer_is_alive(struct sta_info *psta)12560{12561u8 ret = _TRUE;1256212563#ifdef DBG_EXPIRATION_CHK12564RTW_INFO("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"12565/*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/12566", expire_to:%u\n"12567, MAC_ARG(psta->cmn.mac_addr)12568, psta->cmn.rssi_stat.rssi12569, STA_RX_PKTS_DIFF_ARG(psta)12570, psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts12571, psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts12572/*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts12573, psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts12574, psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts12575, pmlmeinfo->bcn_interval*/12576, psta->expire_to12577);12578#endif1257912580if (sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)12581&& sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)12582&& sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))12583ret = _FALSE;1258412585sta_update_last_rx_pkts(psta);1258612587return ret;12588}1258912590#ifdef CONFIG_TDLS12591u8 chk_tdls_peer_sta_is_alive(_adapter *padapter, struct sta_info *psta)12592{12593if ((psta->sta_stats.rx_data_pkts == psta->sta_stats.last_rx_data_pkts)12594&& (psta->sta_stats.rx_tdls_disc_rsp_pkts == psta->sta_stats.last_rx_tdls_disc_rsp_pkts))12595return _FALSE;1259612597return _TRUE;12598}1259912600void linked_status_chk_tdls(_adapter *padapter)12601{12602struct candidate_pool {12603struct sta_info *psta;12604u8 addr[ETH_ALEN];12605};12606struct sta_priv *pstapriv = &padapter->stapriv;12607_irqL irqL;12608u8 ack_chk;12609struct sta_info *psta;12610int i, num_teardown = 0, num_checkalive = 0;12611_list *plist, *phead;12612struct tdls_txmgmt txmgmt;12613struct candidate_pool checkalive[MAX_ALLOWED_TDLS_STA_NUM];12614struct candidate_pool teardown[MAX_ALLOWED_TDLS_STA_NUM];12615u8 tdls_sta_max = _FALSE;1261612617#define ALIVE_MIN 212618#define ALIVE_MAX 51261912620_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));12621_rtw_memset(checkalive, 0x00, sizeof(checkalive));12622_rtw_memset(teardown, 0x00, sizeof(teardown));1262312624if ((padapter->tdlsinfo.link_established == _TRUE)) {12625_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);12626for (i = 0; i < NUM_STA; i++) {12627phead = &(pstapriv->sta_hash[i]);12628plist = get_next(phead);1262912630while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {12631psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);12632plist = get_next(plist);1263312634if (psta->tdls_sta_state & TDLS_LINKED_STATE) {12635psta->alive_count++;12636if (psta->alive_count >= ALIVE_MIN) {12637if (chk_tdls_peer_sta_is_alive(padapter, psta) == _FALSE) {12638if (psta->alive_count < ALIVE_MAX) {12639_rtw_memcpy(checkalive[num_checkalive].addr, psta->cmn.mac_addr, ETH_ALEN);12640checkalive[num_checkalive].psta = psta;12641num_checkalive++;12642} else {12643_rtw_memcpy(teardown[num_teardown].addr, psta->cmn.mac_addr, ETH_ALEN);12644teardown[num_teardown].psta = psta;12645num_teardown++;12646}12647} else12648psta->alive_count = 0;12649}12650psta->sta_stats.last_rx_data_pkts = psta->sta_stats.rx_data_pkts;12651psta->sta_stats.last_rx_tdls_disc_rsp_pkts = psta->sta_stats.rx_tdls_disc_rsp_pkts;1265212653if ((num_checkalive >= MAX_ALLOWED_TDLS_STA_NUM) || (num_teardown >= MAX_ALLOWED_TDLS_STA_NUM)) {12654tdls_sta_max = _TRUE;12655break;12656}12657}12658}1265912660if (tdls_sta_max == _TRUE)12661break;12662}12663_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);1266412665if (num_checkalive > 0) {12666for (i = 0; i < num_checkalive; i++) {12667_rtw_memcpy(txmgmt.peer, checkalive[i].addr, ETH_ALEN);12668issue_tdls_dis_req(padapter, &txmgmt);12669issue_tdls_dis_req(padapter, &txmgmt);12670issue_tdls_dis_req(padapter, &txmgmt);12671}12672}1267312674if (num_teardown > 0) {12675for (i = 0; i < num_teardown; i++) {12676RTW_INFO("[%s %d] Send teardown to "MAC_FMT"\n", __FUNCTION__, __LINE__, MAC_ARG(teardown[i].addr));12677txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_;12678_rtw_memcpy(txmgmt.peer, teardown[i].addr, ETH_ALEN);12679issue_tdls_teardown(padapter, &txmgmt, _FALSE);12680}12681}12682}1268312684}12685#endif /* CONFIG_TDLS */1268612687inline int rtw_get_rx_chk_limit(_adapter *adapter)12688{12689return adapter->stapriv.rx_chk_limit;12690}1269112692inline void rtw_set_rx_chk_limit(_adapter *adapter, int limit)12693{12694adapter->stapriv.rx_chk_limit = limit;12695}1269612697/* from_timer == 1 means driver is in LPS */12698void linked_status_chk(_adapter *padapter, u8 from_timer)12699{12700u32 i;12701struct sta_info *psta;12702struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;12703struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);12704struct sta_priv *pstapriv = &padapter->stapriv;12705#if defined(CONFIG_ARP_KEEP_ALIVE) || defined(CONFIG_LAYER2_ROAMING)12706struct mlme_priv *pmlmepriv = &padapter->mlmepriv;12707#endif12708#ifdef CONFIG_LAYER2_ROAMING12709struct recv_priv *precvpriv = &padapter->recvpriv;12710#endif1271112712if (padapter->registrypriv.mp_mode == _TRUE)12713return;1271412715if (is_client_associated_to_ap(padapter)) {12716/* linked infrastructure client mode */1271712718int tx_chk = _SUCCESS, rx_chk = _SUCCESS;12719int rx_chk_limit;12720int link_count_limit;1272112722#if defined(CONFIG_RTW_REPEATER_SON)12723rtw_rson_scan_wk_cmd(padapter, RSON_SCAN_PROCESS);12724#elif defined(CONFIG_LAYER2_ROAMING)12725if (rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE)) {12726RTW_INFO("signal_strength_data.avg_val = %d\n", precvpriv->signal_strength_data.avg_val);12727if ((precvpriv->signal_strength_data.avg_val < pmlmepriv->roam_rssi_threshold)12728&& (rtw_get_passing_time_ms(pmlmepriv->last_roaming) >= pmlmepriv->roam_scan_int*2000)) {12729#ifdef CONFIG_RTW_80211K12730rtw_roam_nb_discover(padapter, _FALSE);12731#endif12732pmlmepriv->need_to_roam = _TRUE;12733rtw_drv_scan_by_self(padapter, RTW_AUTO_SCAN_REASON_ROAM);12734pmlmepriv->last_roaming = rtw_get_current_time();12735} else12736pmlmepriv->need_to_roam = _FALSE;12737}12738#endif12739#ifdef CONFIG_MCC_MODE12740/*12741* due to tx ps null date to ao, so ap doest not tx pkt to driver12742* we may check chk_ap_is_alive fail, and may issue_probereq to wrong channel under sitesurvey12743* don't keep alive check under MCC12744*/12745if (rtw_hal_mcc_link_status_chk(padapter, __func__) == _FALSE)12746return;12747#endif1274812749rx_chk_limit = rtw_get_rx_chk_limit(padapter);1275012751#ifdef CONFIG_ARP_KEEP_ALIVE12752if (!from_timer && pmlmepriv->bGetGateway == 1 && pmlmepriv->GetGatewayTryCnt < 3) {12753RTW_INFO("do rtw_gw_addr_query() : %d\n", pmlmepriv->GetGatewayTryCnt);12754pmlmepriv->GetGatewayTryCnt++;12755if (rtw_gw_addr_query(padapter) == 0)12756pmlmepriv->bGetGateway = 0;12757else {12758_rtw_memset(pmlmepriv->gw_ip, 0, 4);12759_rtw_memset(pmlmepriv->gw_mac_addr, 0, ETH_ALEN);12760}12761}12762#endif12763#ifdef CONFIG_P2P12764if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) {12765if (!from_timer)12766link_count_limit = 3; /* 8 sec */12767else12768link_count_limit = 15; /* 32 sec */12769} else12770#endif /* CONFIG_P2P */12771{12772if (!from_timer)12773link_count_limit = 7; /* 16 sec */12774else12775link_count_limit = 29; /* 60 sec */12776}1277712778#ifdef CONFIG_TDLS12779#ifdef CONFIG_TDLS_CH_SW12780if (ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on) == _TRUE)12781return;12782#endif /* CONFIG_TDLS_CH_SW */1278312784#ifdef CONFIG_TDLS_AUTOCHECKALIVE12785linked_status_chk_tdls(padapter);12786#endif /* CONFIG_TDLS_AUTOCHECKALIVE */12787#endif /* CONFIG_TDLS */1278812789psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);12790if (psta != NULL) {12791bool is_p2p_enable = _FALSE;12792#ifdef CONFIG_P2P12793is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);12794#endif1279512796#ifdef CONFIG_ISSUE_DELBA_WHEN_NO_TRAFFIC12797/*issue delba when ap does not tx data packet that is Broadcom ap */12798rtw_delba_check(padapter, psta, from_timer);12799#endif12800if (chk_ap_is_alive(padapter, psta) == _FALSE)12801rx_chk = _FAIL;1280212803if (sta_last_tx_pkts(psta) == sta_tx_pkts(psta))12804tx_chk = _FAIL;1280512806#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK12807if (!from_timer && pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)12808) {12809u8 backup_ch = 0, backup_bw = 0, backup_offset = 0;12810u8 union_ch = 0, union_bw = 0, union_offset = 0;12811u8 switch_channel_by_drv = _TRUE;128121281312814#ifdef CONFIG_MCC_MODE12815if (MCC_EN(padapter)) {12816/* driver doesn't switch channel under MCC */12817if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))12818switch_channel_by_drv = _FALSE;12819}12820#endif12821if (switch_channel_by_drv) {12822if (!rtw_mi_get_ch_setting_union(padapter, &union_ch, &union_bw, &union_offset)12823|| pmlmeext->cur_channel != union_ch)12824goto bypass_active_keep_alive;1282512826/* switch to correct channel of current network before issue keep-alive frames */12827if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {12828backup_ch = rtw_get_oper_ch(padapter);12829backup_bw = rtw_get_oper_bw(padapter);12830backup_offset = rtw_get_oper_choffset(padapter);12831set_channel_bwmode(padapter, union_ch, union_offset, union_bw);12832}12833}1283412835if (rx_chk != _SUCCESS)12836issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->cmn.mac_addr, 0, 0, 3, 1);1283712838if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) || rx_chk != _SUCCESS) {12839if (rtw_mi_check_fwstate(padapter, _FW_UNDER_SURVEY))12840tx_chk = issue_nulldata(padapter, psta->cmn.mac_addr, 1, 3, 1);12841else12842tx_chk = issue_nulldata(padapter, psta->cmn.mac_addr, 0, 3, 1);12843/* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */12844if (tx_chk == _SUCCESS && !is_p2p_enable)12845rx_chk = _SUCCESS;12846}1284712848/* back to the original operation channel */12849if (backup_ch > 0 && switch_channel_by_drv)12850set_channel_bwmode(padapter, backup_ch, backup_offset, backup_bw);1285112852bypass_active_keep_alive:12853;12854} else12855#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */12856{12857if (rx_chk != _SUCCESS) {12858if (pmlmeext->retry == 0) {12859#ifdef DBG_EXPIRATION_CHK12860RTW_INFO("issue_probereq to trigger probersp, retry=%d\n", pmlmeext->retry);12861#endif12862issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, (from_timer ? 0 : 1));12863issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, (from_timer ? 0 : 1));12864issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, (from_timer ? 0 : 1));12865}12866}1286712868if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit12869#ifdef CONFIG_MCC_MODE12870/* FW tx nulldata under MCC mode, we just check ap is alive */12871&& (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC))12872#endif /* CONFIG_MCC_MODE */12873) {12874#ifdef DBG_EXPIRATION_CHK12875RTW_INFO("%s issue_nulldata(%d)\n", __FUNCTION__, from_timer ? 1 : 0);12876#endif12877if (from_timer || rtw_mi_check_fwstate(padapter, _FW_UNDER_SURVEY))12878tx_chk = issue_nulldata(padapter, NULL, 1, 0, 0);12879else12880tx_chk = issue_nulldata(padapter, NULL, 0, 1, 1);12881}12882}1288312884if (rx_chk == _FAIL) {12885pmlmeext->retry++;12886if (pmlmeext->retry > rx_chk_limit) {12887RTW_PRINT(FUNC_ADPT_FMT" disconnect or roaming\n",12888FUNC_ADPT_ARG(padapter));12889receive_disconnect(padapter, pmlmeinfo->network.MacAddress12890, WLAN_REASON_EXPIRATION_CHK, _FALSE);12891return;12892}12893} else12894pmlmeext->retry = 0;1289512896if (tx_chk == _FAIL)12897pmlmeinfo->link_count %= (link_count_limit + 1);12898else {12899psta->sta_stats.last_tx_pkts = psta->sta_stats.tx_pkts;12900pmlmeinfo->link_count = 0;12901}1290212903} /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */1290412905} else if (is_client_associated_to_ibss(padapter)) {12906_irqL irqL;12907_list *phead, *plist, dlist;1290812909_rtw_init_listhead(&dlist);1291012911_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);1291212913for (i = 0; i < NUM_STA; i++) {1291412915phead = &(pstapriv->sta_hash[i]);12916plist = get_next(phead);12917while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {12918psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);12919plist = get_next(plist);1292012921if (is_broadcast_mac_addr(psta->cmn.mac_addr))12922continue;1292312924if (chk_adhoc_peer_is_alive(psta) || !psta->expire_to)12925psta->expire_to = pstapriv->adhoc_expire_to;12926else12927psta->expire_to--;1292812929if (psta->expire_to <= 0) {12930rtw_list_delete(&psta->list);12931rtw_list_insert_tail(&psta->list, &dlist);12932}12933}12934}1293512936_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);1293712938plist = get_next(&dlist);12939while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) {12940psta = LIST_CONTAINOR(plist, struct sta_info, list);12941plist = get_next(plist);12942rtw_list_delete(&psta->list);12943RTW_INFO(FUNC_ADPT_FMT" ibss expire "MAC_FMT"\n"12944, FUNC_ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr));12945report_del_sta_event(padapter, psta->cmn.mac_addr, WLAN_REASON_EXPIRATION_CHK, from_timer ? _TRUE : _FALSE, _FALSE);12946}12947}1294812949}1295012951void survey_timer_hdl(void *ctx)12952{12953_adapter *padapter = (_adapter *)ctx;12954struct cmd_obj *cmd;12955struct sitesurvey_parm *psurveyPara;12956struct cmd_priv *pcmdpriv = &padapter->cmdpriv;12957struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1295812959if (mlmeext_scan_state(pmlmeext) > SCAN_DISABLE) {12960cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));12961if (cmd == NULL) {12962rtw_warn_on(1);12963goto exit;12964}1296512966psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));12967if (psurveyPara == NULL) {12968rtw_warn_on(1);12969rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));12970goto exit;12971}1297212973init_h2fwcmd_w_parm_no_rsp(cmd, psurveyPara, GEN_CMD_CODE(_SiteSurvey));12974rtw_enqueue_cmd(pcmdpriv, cmd);12975}1297612977exit:12978return;12979}1298012981#ifdef CONFIG_RTW_REPEATER_SON12982/* 100ms pass, stop rson_scan */12983void rson_timer_hdl(void *ctx)12984{12985_adapter *padapter = (_adapter *)ctx;1298612987rtw_rson_scan_wk_cmd(padapter, RSON_SCAN_DISABLE);12988}1298912990#endif1299112992void link_timer_hdl(void *ctx)12993{12994_adapter *padapter = (_adapter *)ctx;12995/* static unsigned int rx_pkt = 0; */12996/* static u64 tx_cnt = 0; */12997/* struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); */12998struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;12999struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);13000/* struct sta_priv *pstapriv = &padapter->stapriv; */13001#ifdef CONFIG_RTW_80211R13002struct sta_priv *pstapriv = &padapter->stapriv;13003struct sta_info *psta = NULL;13004WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));13005#endif1300613007if (rtw_sta_linking_test_force_fail())13008RTW_INFO("rtw_sta_linking_test_force_fail\n");1300913010if (pmlmeext->join_abort && pmlmeinfo->state != WIFI_FW_NULL_STATE) {13011RTW_INFO(FUNC_ADPT_FMT" join abort\n", FUNC_ADPT_ARG(padapter));13012pmlmeinfo->state = WIFI_FW_NULL_STATE;13013report_join_res(padapter, -4, WLAN_STATUS_UNSPECIFIED_FAILURE);13014goto exit;13015}1301613017if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {13018RTW_INFO("link_timer_hdl:no beacon while connecting\n");13019pmlmeinfo->state = WIFI_FW_NULL_STATE;13020report_join_res(padapter, -3, WLAN_STATUS_UNSPECIFIED_FAILURE);13021} else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {1302213023#ifdef CONFIG_IOCTL_CFG8021113024if (rtw_sec_chk_auth_type(padapter, NL80211_AUTHTYPE_SAE))13025return;13026#endif /* CONFIG_IOCTL_CFG80211 */1302713028/* re-auth timer */13029if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {13030/* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */13031/* { */13032pmlmeinfo->state = 0;13033if (pmlmeinfo->auth_status) {13034report_join_res(padapter, -1, pmlmeinfo->auth_status);13035pmlmeinfo->auth_status = 0; /* reset */13036} else13037report_join_res(padapter, -1, WLAN_STATUS_UNSPECIFIED_FAILURE);13038return;13039/* } */13040/* else */13041/* { */13042/* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */13043/* pmlmeinfo->reauth_count = 0; */13044/* } */13045}1304613047RTW_INFO("link_timer_hdl: auth timeout and try again\n");13048pmlmeinfo->auth_seq = 1;13049issue_auth(padapter, NULL, 0);13050set_link_timer(pmlmeext, REAUTH_TO);13051} else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {13052/* re-assoc timer */13053if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {13054pmlmeinfo->state = WIFI_FW_NULL_STATE;13055#ifdef CONFIG_RTW_80211R13056if (rtw_ft_roam(padapter)) {13057psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);13058if (psta)13059rtw_free_stainfo(padapter, psta);13060}13061#endif13062report_join_res(padapter, -2, WLAN_STATUS_UNSPECIFIED_FAILURE);13063return;13064}1306513066#ifdef CONFIG_RTW_80211R13067if (rtw_ft_roam(padapter)) {13068RTW_INFO("link_timer_hdl: reassoc timeout and try again\n");13069issue_reassocreq(padapter);13070} else13071#endif13072{13073RTW_INFO("link_timer_hdl: assoc timeout and try again\n");13074issue_assocreq(padapter);13075}1307613077set_link_timer(pmlmeext, REASSOC_TO);13078}1307913080exit:13081return;13082}1308313084void addba_timer_hdl(void *ctx)13085{13086struct sta_info *psta = (struct sta_info *)ctx;1308713088#ifdef CONFIG_80211N_HT13089struct ht_priv *phtpriv;1309013091if (!psta)13092return;1309313094phtpriv = &psta->htpriv;1309513096if ((phtpriv->ht_option == _TRUE) && (phtpriv->ampdu_enable == _TRUE)) {13097if (phtpriv->candidate_tid_bitmap)13098phtpriv->candidate_tid_bitmap = 0x0;1309913100}13101#endif /* CONFIG_80211N_HT */13102}1310313104#ifdef CONFIG_IEEE80211W13105void report_sta_timeout_event(_adapter *padapter, u8 *MacAddr, unsigned short reason)13106{13107struct cmd_obj *pcmd_obj;13108u8 *pevtcmd;13109u32 cmdsz;13110struct sta_info *psta;13111int mac_id;13112struct stadel_event *pdel_sta_evt;13113struct C2HEvent_Header *pc2h_evt_hdr;13114struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;13115struct cmd_priv *pcmdpriv = &padapter->cmdpriv;1311613117pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));13118if (pcmd_obj == NULL)13119return;1312013121cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));13122pevtcmd = (u8 *)rtw_zmalloc(cmdsz);13123if (pevtcmd == NULL) {13124rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));13125return;13126}1312713128_rtw_init_listhead(&pcmd_obj->list);1312913130pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);13131pcmd_obj->cmdsz = cmdsz;13132pcmd_obj->parmbuf = pevtcmd;1313313134pcmd_obj->rsp = NULL;13135pcmd_obj->rspsz = 0;1313613137pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);13138pc2h_evt_hdr->len = sizeof(struct stadel_event);13139pc2h_evt_hdr->ID = GEN_EVT_CODE(_TimeoutSTA);13140pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);1314113142pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));13143_rtw_memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);13144_rtw_memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);131451314613147psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);13148if (psta)13149mac_id = (int)psta->cmn.mac_id;13150else13151mac_id = (-1);1315213153pdel_sta_evt->mac_id = mac_id;1315413155RTW_INFO("report_del_sta_event: delete STA, mac_id=%d\n", mac_id);1315613157rtw_enqueue_cmd(pcmdpriv, pcmd_obj);1315813159return;13160}1316113162void clnt_sa_query_timeout(_adapter *padapter)13163{13164struct mlme_ext_priv *mlmeext = &(padapter->mlmeextpriv);13165struct mlme_ext_info *mlmeinfo = &(mlmeext->mlmext_info);1316613167RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));13168receive_disconnect(padapter, get_my_bssid(&(mlmeinfo->network)), WLAN_REASON_SA_QUERY_TIMEOUT, _FALSE);13169}1317013171void sa_query_timer_hdl(void *ctx)13172{13173struct sta_info *psta = (struct sta_info *)ctx;13174_adapter *padapter = psta->padapter;13175_irqL irqL;13176struct sta_priv *pstapriv = &padapter->stapriv;13177struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1317813179if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE &&13180check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)13181clnt_sa_query_timeout(padapter);13182else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)13183report_sta_timeout_event(padapter, psta->cmn.mac_addr, WLAN_REASON_PREV_AUTH_NOT_VALID);13184}1318513186#endif /* CONFIG_IEEE80211W */1318713188#ifdef CONFIG_RTW_80211R13189void rtw_ft_update_bcn(_adapter *padapter, union recv_frame *precv_frame)13190{13191struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;13192struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);13193struct mlme_priv *pmlmepriv = &padapter->mlmepriv;13194u8 *pframe = precv_frame->u.hdr.rx_data;13195uint len = precv_frame->u.hdr.len;13196WLAN_BSSID_EX *pbss;1319713198if (rtw_ft_chk_status(padapter,RTW_FT_ASSOCIATED_STA)13199&& (pmlmepriv->ft_roam.ft_updated_bcn == _FALSE)) {13200pbss = (WLAN_BSSID_EX*)rtw_malloc(sizeof(WLAN_BSSID_EX));13201if (pbss) {13202if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {13203struct beacon_keys recv_beacon;1320413205update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE);1320613207/* update bcn keys */13208if (rtw_get_bcn_keys(padapter, pframe, len, &recv_beacon) == _TRUE) {13209RTW_INFO("%s: beacon keys ready\n", __func__);13210_rtw_memcpy(&pmlmepriv->cur_beacon_keys,13211&recv_beacon, sizeof(recv_beacon));13212} else {13213RTW_ERR("%s: get beacon keys failed\n", __func__);13214_rtw_memset(&pmlmepriv->cur_beacon_keys, 0, sizeof(recv_beacon));13215}13216#ifdef CONFIG_BCN_CNT_CONFIRM_HDL13217pmlmepriv->new_beacon_cnts = 0;13218#endif13219}13220rtw_mfree((u8*)pbss, sizeof(WLAN_BSSID_EX));13221}1322213223/* check the vendor of the assoc AP */13224pmlmeinfo->assoc_AP_vendor =13225check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr),13226(len - sizeof(struct rtw_ieee80211_hdr_3addr)));1322713228/* update TSF Value */13229update_TSF(pmlmeext, pframe, len);13230pmlmeext->bcn_cnt = 0;13231pmlmeext->last_bcn_cnt = 0;13232pmlmepriv->ft_roam.ft_updated_bcn = _TRUE;13233}13234}1323513236void rtw_ft_start_clnt_join(_adapter *padapter)13237{13238struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);13239struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);13240struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);13241struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);1324213243if (rtw_ft_otd_roam(padapter)) {13244pmlmeinfo->state = WIFI_FW_AUTH_SUCCESS | WIFI_FW_STATION_STATE;13245pft_roam->ft_event.ies =13246(pft_roam->ft_action + sizeof(struct rtw_ieee80211_hdr_3addr) + 16);13247pft_roam->ft_event.ies_len =13248(pft_roam->ft_action_len - sizeof(struct rtw_ieee80211_hdr_3addr));1324913250/*Not support RIC*/13251pft_roam->ft_event.ric_ies = NULL;13252pft_roam->ft_event.ric_ies_len = 0;13253rtw_ft_report_evt(padapter);13254return;13255}1325613257pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;13258start_clnt_auth(padapter);13259}1326013261u8 rtw_ft_update_rsnie(13262_adapter *padapter, u8 bwrite,13263struct pkt_attrib *pattrib, u8 **pframe)13264{13265struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);13266u8 *pie;13267u32 len;1326813269pie = rtw_get_ie(pft_roam->updated_ft_ies, EID_WPA2, &len,13270pft_roam->updated_ft_ies_len);1327113272if (!bwrite)13273return (pie)?_SUCCESS:_FAIL;1327413275if (pie) {13276*pframe = rtw_set_ie(((u8 *)*pframe), EID_WPA2, len,13277pie+2, &(pattrib->pktlen));13278} else13279return _FAIL;1328013281return _SUCCESS;13282}1328313284static u8 rtw_ft_update_mdie(13285_adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe)13286{13287struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);13288u8 *pie, mdie[3];13289u32 len = 3;1329013291if (rtw_ft_roam(padapter)) {13292if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _MDIE_,13293&len, pft_roam->updated_ft_ies_len))) {13294pie = (pie + 2); /* ignore md-id & length */13295} else13296return _FAIL;13297} else {13298*((u16 *)&mdie[0]) = pft_roam->mdid;13299mdie[2] = pft_roam->ft_cap;13300pie = &mdie[0];13301}1330213303*pframe = rtw_set_ie(((u8 *)*pframe), _MDIE_, len , pie, &(pattrib->pktlen));13304return _SUCCESS;13305}1330613307static u8 rtw_ft_update_ftie(13308_adapter *padapter, struct pkt_attrib *pattrib, u8 **pframe)13309{13310struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);13311u8 *pie;13312u32 len;1331313314if ((pie = rtw_get_ie(pft_roam->updated_ft_ies, _FTIE_, &len,13315pft_roam->updated_ft_ies_len)) != NULL) {13316*pframe = rtw_set_ie(*pframe, _FTIE_, len ,13317(pie+2), &(pattrib->pktlen));13318} else13319return _FAIL;1332013321return _SUCCESS;13322}1332313324void rtw_ft_build_auth_req_ies(_adapter *padapter,13325struct pkt_attrib *pattrib, u8 **pframe)13326{13327u8 ftie_append = _TRUE;1332813329if (!pattrib || !(*pframe))13330return;1333113332if (!rtw_ft_roam(padapter))13333return;1333413335ftie_append = rtw_ft_update_rsnie(padapter, _TRUE, pattrib, pframe);13336rtw_ft_update_mdie(padapter, pattrib, pframe);13337if (ftie_append)13338rtw_ft_update_ftie(padapter, pattrib, pframe);13339}1334013341void rtw_ft_build_assoc_req_ies(_adapter *padapter,13342u8 is_reassoc, struct pkt_attrib *pattrib, u8 **pframe)13343{13344if (!pattrib || !(*pframe))13345return;1334613347if (rtw_ft_chk_flags(padapter, RTW_FT_PEER_EN))13348rtw_ft_update_mdie(padapter, pattrib, pframe);1334913350if ((!is_reassoc) || (!rtw_ft_roam(padapter)))13351return;1335213353if (rtw_ft_update_rsnie(padapter, _FALSE, pattrib, pframe))13354rtw_ft_update_ftie(padapter, pattrib, pframe);13355}1335613357u8 rtw_ft_update_auth_rsp_ies(_adapter *padapter, u8 *pframe, u32 len)13358{13359u8 ret = _SUCCESS;13360u8 target_ap_addr[ETH_ALEN] = {0};13361struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);13362struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);1336313364if (!rtw_ft_roam(padapter))13365return _FAIL;1336613367/*rtw_ft_report_reassoc_evt already,13368* and waiting for cfg80211_rtw_update_ft_ies */13369if (rtw_ft_authed_sta(padapter))13370return ret;1337113372if (!pframe || !len)13373return _FAIL;1337413375rtw_buf_update(&pmlmepriv->auth_rsp,13376&pmlmepriv->auth_rsp_len, pframe, len);13377pft_roam->ft_event.ies =13378(pmlmepriv->auth_rsp + sizeof(struct rtw_ieee80211_hdr_3addr) + 6);13379pft_roam->ft_event.ies_len =13380(pmlmepriv->auth_rsp_len - sizeof(struct rtw_ieee80211_hdr_3addr) - 6);1338113382/*Not support RIC*/13383pft_roam->ft_event.ric_ies = NULL;13384pft_roam->ft_event.ric_ies_len = 0;13385_rtw_memcpy(target_ap_addr, pmlmepriv->assoc_bssid, ETH_ALEN);13386rtw_ft_report_reassoc_evt(padapter, target_ap_addr);1338713388return ret;13389}1339013391static void rtw_ft_start_clnt_action(_adapter *padapter, u8 *pTargetAddr)13392{13393struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1339413395rtw_ft_set_status(padapter, RTW_FT_REQUESTING_STA);13396rtw_ft_issue_action_req(padapter, pTargetAddr);13397_set_timer(&pmlmeext->ft_link_timer, REASSOC_TO);13398}1339913400void rtw_ft_start_roam(_adapter *padapter, u8 *pTargetAddr)13401{13402struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1340313404if (rtw_ft_otd_roam(padapter)) {13405rtw_ft_start_clnt_action(padapter, pTargetAddr);13406} else {13407/*wait a little time to retrieve packets buffered in the current ap while scan*/13408_set_timer(&pmlmeext->ft_roam_timer, 30);13409}13410}1341113412void rtw_ft_issue_action_req(_adapter *padapter, u8 *pTargetAddr)13413{13414struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);13415struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);13416struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);13417struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);13418struct xmit_frame *pmgntframe;13419struct rtw_ieee80211_hdr *pwlanhdr;13420struct pkt_attrib *pattrib;13421u8 *pframe;13422u8 category = RTW_WLAN_CATEGORY_FT;13423u8 action = RTW_WLAN_ACTION_FT_REQ;1342413425pmgntframe = alloc_mgtxmitframe(pxmitpriv);13426if (pmgntframe == NULL)13427return;1342813429pattrib = &pmgntframe->attrib;13430update_mgntframe_attrib(padapter, pattrib);13431_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);1343213433pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;13434pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;13435pwlanhdr->frame_ctl = 0;1343613437_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);13438_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);13439_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);1344013441SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);13442pmlmeext->mgnt_seq++;13443set_frame_sub_type(pframe, WIFI_ACTION);1344413445pframe += sizeof(struct rtw_ieee80211_hdr_3addr);13446pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);1344713448pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));13449pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));1345013451_rtw_memcpy(pframe, adapter_mac_addr(padapter), ETH_ALEN);13452pframe += ETH_ALEN;13453pattrib->pktlen += ETH_ALEN;1345413455_rtw_memcpy(pframe, pTargetAddr, ETH_ALEN);13456pframe += ETH_ALEN;13457pattrib->pktlen += ETH_ALEN;1345813459rtw_ft_update_mdie(padapter, pattrib, &pframe);13460if (rtw_ft_update_rsnie(padapter, _TRUE, pattrib, &pframe))13461rtw_ft_update_ftie(padapter, pattrib, &pframe);1346213463pattrib->last_txcmdsz = pattrib->pktlen;13464dump_mgntframe(padapter, pmgntframe);13465}1346613467void rtw_ft_report_evt(_adapter *padapter)13468{13469struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);13470struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);13471struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);13472struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);13473WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&(pmlmeinfo->network);13474struct cfg80211_ft_event_params ft_evt_parms;13475_irqL irqL;1347613477_rtw_memset(&ft_evt_parms, 0, sizeof(ft_evt_parms));13478rtw_ft_update_stainfo(padapter, pnetwork);1347913480if (!pnetwork)13481goto err_2;1348213483ft_evt_parms.ies_len = pft_roam->ft_event.ies_len;13484ft_evt_parms.ies = rtw_zmalloc(ft_evt_parms.ies_len);13485if (ft_evt_parms.ies)13486_rtw_memcpy((void *)ft_evt_parms.ies, pft_roam->ft_event.ies, ft_evt_parms.ies_len);13487else13488goto err_2;1348913490ft_evt_parms.target_ap = rtw_zmalloc(ETH_ALEN);13491if (ft_evt_parms.target_ap)13492_rtw_memcpy((void *)ft_evt_parms.target_ap, pnetwork->MacAddress, ETH_ALEN);13493else13494goto err_1;1349513496ft_evt_parms.ric_ies = pft_roam->ft_event.ric_ies;13497ft_evt_parms.ric_ies_len = pft_roam->ft_event.ric_ies_len;1349813499rtw_ft_lock_set_status(padapter, RTW_FT_AUTHENTICATED_STA, &irqL);13500rtw_cfg80211_ft_event(padapter, &ft_evt_parms);13501RTW_INFO("FT: rtw_ft_report_evt\n");13502rtw_mfree((u8 *)pft_roam->ft_event.target_ap, ETH_ALEN);13503err_1:13504rtw_mfree((u8 *)ft_evt_parms.ies, ft_evt_parms.ies_len);13505err_2:13506return;13507}1350813509void rtw_ft_report_reassoc_evt(_adapter *padapter, u8 *pMacAddr)13510{13511struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);13512struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);13513struct cmd_obj *pcmd_obj = NULL;13514struct stassoc_event *passoc_sta_evt = NULL;13515struct C2HEvent_Header *pc2h_evt_hdr = NULL;13516u8 *pevtcmd = NULL;13517u32 cmdsz = 0;1351813519pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));13520if (pcmd_obj == NULL)13521return;1352213523cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));13524pevtcmd = (u8 *)rtw_zmalloc(cmdsz);13525if (pevtcmd == NULL) {13526rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));13527return;13528}1352913530_rtw_init_listhead(&pcmd_obj->list);13531pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);13532pcmd_obj->cmdsz = cmdsz;13533pcmd_obj->parmbuf = pevtcmd;13534pcmd_obj->rsp = NULL;13535pcmd_obj->rspsz = 0;1353613537pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);13538pc2h_evt_hdr->len = sizeof(struct stassoc_event);13539pc2h_evt_hdr->ID = GEN_EVT_CODE(_FT_REASSOC);13540pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);1354113542passoc_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));13543_rtw_memcpy((unsigned char *)(&(passoc_sta_evt->macaddr)), pMacAddr, ETH_ALEN);13544rtw_enqueue_cmd(pcmdpriv, pcmd_obj);13545}1354613547void rtw_ft_link_timer_hdl(void *ctx)13548{13549_adapter *padapter = (_adapter *)ctx;13550struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);13551struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);13552struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);13553struct ft_roam_info *pft_roam = &(pmlmepriv->ft_roam);1355413555if (rtw_ft_chk_status(padapter, RTW_FT_REQUESTING_STA)) {13556if (pft_roam->ft_req_retry_cnt < RTW_FT_ACTION_REQ_LMT) {13557pft_roam->ft_req_retry_cnt++;13558rtw_ft_issue_action_req(padapter, (u8 *)pmlmepriv->roam_network->network.MacAddress);13559_set_timer(&pmlmeext->ft_link_timer, REASSOC_TO);13560} else {13561pft_roam->ft_req_retry_cnt = 0;13562if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)13563rtw_ft_set_status(padapter, RTW_FT_ASSOCIATED_STA);13564else13565rtw_ft_reset_status(padapter);13566}13567}13568}1356913570void rtw_ft_roam_timer_hdl(void *ctx)13571{13572_adapter *padapter = (_adapter *)ctx;13573struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);1357413575receive_disconnect(padapter, pmlmepriv->cur_network.network.MacAddress13576, WLAN_REASON_ACTIVE_ROAM, _FALSE);13577}1357813579void rtw_ft_roam_status_reset(_adapter *padapter)13580{13581struct ft_roam_info *pft_roam = &(padapter->mlmepriv.ft_roam);1358213583if ((rtw_to_roam(padapter) > 0) &&13584(!rtw_ft_chk_status(padapter, RTW_FT_REQUESTED_STA))) {13585rtw_ft_reset_status(padapter);13586}1358713588padapter->mlmepriv.ft_roam.ft_updated_bcn = _FALSE;13589}13590#endif1359113592u8 NULL_hdl(_adapter *padapter, u8 *pbuf)13593{13594return H2C_SUCCESS;13595}1359613597#ifdef CONFIG_AUTO_AP_MODE13598void rtw_auto_ap_rx_msg_dump(_adapter *padapter, union recv_frame *precv_frame, u8 *ehdr_pos)13599{13600struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;13601struct sta_info *psta = precv_frame->u.hdr.psta;13602struct ethhdr *ehdr = (struct ethhdr *)ehdr_pos;1360313604RTW_INFO("eth rx: got eth_type=0x%x\n", ntohs(ehdr->h_proto));1360513606if (psta && psta->isrc && psta->pid > 0) {13607u16 rx_pid;1360813609rx_pid = *(u16 *)(ehdr_pos + ETH_HLEN);1361013611RTW_INFO("eth rx(pid=0x%x): sta("MAC_FMT") pid=0x%x\n",13612rx_pid, MAC_ARG(psta->cmn.mac_addr), psta->pid);1361313614if (rx_pid == psta->pid) {13615int i;13616u16 len = *(u16 *)(ehdr_pos + ETH_HLEN + 2);13617/* u16 ctrl_type = *(u16 *)(ehdr_pos + ETH_HLEN + 4); */1361813619/* RTW_INFO("eth, RC: len=0x%x, ctrl_type=0x%x\n", len, ctrl_type); */13620RTW_INFO("eth, RC: len=0x%x\n", len);1362113622for (i = 0; i < len; i++)13623RTW_INFO("0x%x\n", *(ehdr_pos + ETH_HLEN + 4 + i));13624/* RTW_INFO("0x%x\n", *(ehdr_pos + ETH_HLEN + 6 + i)); */1362513626RTW_INFO("eth, RC-end\n");13627}13628}1362913630}1363113632void rtw_start_auto_ap(_adapter *adapter)13633{13634RTW_INFO("%s\n", __FUNCTION__);1363513636rtw_set_802_11_infrastructure_mode(adapter, Ndis802_11APMode, 0);1363713638rtw_setopmode_cmd(adapter, Ndis802_11APMode, RTW_CMDF_WAIT_ACK);13639}1364013641static int rtw_auto_ap_start_beacon(_adapter *adapter)13642{13643int ret = 0;13644u8 *pbuf = NULL;13645uint len;13646u8 supportRate[16];13647int sz = 0, rateLen;13648u8 *ie;13649u8 wireless_mode, oper_channel;13650u8 ssid[3] = {0}; /* hidden ssid */13651u32 ssid_len = sizeof(ssid);13652struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);1365313654if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)13655return -EINVAL;136561365713658len = 128;13659pbuf = rtw_zmalloc(len);13660if (!pbuf)13661return -ENOMEM;136621366313664/* generate beacon */13665ie = pbuf;1366613667/* timestamp will be inserted by hardware */13668sz += 8;13669ie += sz;1367013671/* beacon interval : 2bytes */13672*(u16 *)ie = cpu_to_le16((u16)100); /* BCN_INTERVAL=100; */13673sz += 2;13674ie += 2;1367513676/* capability info */13677*(u16 *)ie = 0;13678*(u16 *)ie |= cpu_to_le16(cap_ESS);13679*(u16 *)ie |= cpu_to_le16(cap_ShortPremble);13680/* *(u16*)ie |= cpu_to_le16(cap_Privacy); */13681sz += 2;13682ie += 2;1368313684/* SSID */13685ie = rtw_set_ie(ie, _SSID_IE_, ssid_len, ssid, &sz);1368613687/* supported rates */13688wireless_mode = (WIRELESS_11BG_24N & padapter->registrypriv.wireless_mode);13689rtw_set_supported_rate(supportRate, wireless_mode);13690rateLen = rtw_get_rateset_len(supportRate);13691if (rateLen > 8)13692ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, supportRate, &sz);13693else13694ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, supportRate, &sz);136951369613697/* DS parameter set */13698if (rtw_mi_check_status(adapter, MI_LINKED))13699oper_channel = rtw_mi_get_union_chan(adapter);13700else13701oper_channel = adapter_to_dvobj(adapter)->oper_channel;1370213703ie = rtw_set_ie(ie, _DSSET_IE_, 1, &oper_channel, &sz);1370413705/* ext supported rates */13706if (rateLen > 8)13707ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz);1370813709RTW_INFO("%s, start auto ap beacon sz=%d\n", __FUNCTION__, sz);1371013711/* lunch ap mode & start to issue beacon */13712if (rtw_check_beacon_data(adapter, pbuf, sz) == _SUCCESS) {1371313714} else13715ret = -EINVAL;137161371713718rtw_mfree(pbuf, len);1371913720return ret;1372113722}13723#endif/* CONFIG_AUTO_AP_MODE */1372413725#ifdef CONFIG_AP_MODE13726u8 stop_ap_hdl(_adapter *adapter)13727{13728RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));1372913730rtw_set_802_11_infrastructure_mode(adapter, Ndis802_11Infrastructure, RTW_CMDF_DIRECTLY);13731rtw_setopmode_cmd(adapter, Ndis802_11Infrastructure, RTW_CMDF_DIRECTLY);1373213733return H2C_SUCCESS;13734}13735#endif1373613737u8 setopmode_hdl(_adapter *padapter, u8 *pbuf)13738{13739u8 type;13740struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;13741struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);13742struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;1374313744if (psetop->mode == Ndis802_11APMode13745|| psetop->mode == Ndis802_11_mesh13746) {13747pmlmeinfo->state = WIFI_FW_AP_STATE;13748type = _HW_STATE_AP_;13749} else if (psetop->mode == Ndis802_11Infrastructure) {13750pmlmeinfo->state &= ~(BIT(0) | BIT(1)); /* clear state */13751pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */13752type = _HW_STATE_STATION_;13753} else if (psetop->mode == Ndis802_11IBSS)13754type = _HW_STATE_ADHOC_;13755else if (psetop->mode == Ndis802_11Monitor)13756type = _HW_STATE_MONITOR_;13757else13758type = _HW_STATE_NOLINK_;1375913760#ifdef CONFIG_AP_PORT_SWAP13761rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, (u8 *)(&type));13762#endif1376313764rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));1376513766#ifdef CONFIG_AUTO_AP_MODE13767if (psetop->mode == Ndis802_11APMode)13768rtw_auto_ap_start_beacon(padapter);13769#endif1377013771if (rtw_port_switch_chk(padapter) == _TRUE) {13772rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);1377313774if (psetop->mode == Ndis802_11APMode)13775adapter_to_pwrctl(padapter)->fw_psmode_iface_id = 0xff; /* ap mode won't dowload rsvd pages */13776else if (psetop->mode == Ndis802_11Infrastructure) {13777#ifdef CONFIG_LPS13778_adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));13779if (port0_iface)13780rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, RTW_CMDF_DIRECTLY);13781#endif13782}13783}1378413785#ifdef CONFIG_BT_COEXIST13786if (psetop->mode == Ndis802_11APMode13787|| psetop->mode == Ndis802_11_mesh13788|| psetop->mode == Ndis802_11Monitor13789) {13790/* Do this after port switch to */13791/* prevent from downloading rsvd page to wrong port */13792rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */13793}13794#endif /* CONFIG_BT_COEXIST */1379513796return H2C_SUCCESS;1379713798}1379913800u8 createbss_hdl(_adapter *padapter, u8 *pbuf)13801{13802struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;13803struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);13804WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));13805WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network;13806struct createbss_parm *parm = (struct createbss_parm *)pbuf;13807u8 ret = H2C_SUCCESS;13808/* u8 initialgain; */1380913810#ifdef CONFIG_AP_MODE13811if ((parm->req_ch == 0 && pmlmeinfo->state == WIFI_FW_AP_STATE)13812|| parm->req_ch != 013813) {13814start_bss_network(padapter, parm);13815goto exit;13816}13817#endif1381813819/* below is for ad-hoc master */13820if (parm->adhoc) {13821rtw_warn_on(pdev_network->InfrastructureMode != Ndis802_11IBSS);13822rtw_joinbss_reset(padapter);1382313824pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;13825pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;13826pmlmeinfo->ERP_enable = 0;13827pmlmeinfo->WMM_enable = 0;13828pmlmeinfo->HT_enable = 0;13829pmlmeinfo->HT_caps_enable = 0;13830pmlmeinfo->HT_info_enable = 0;13831pmlmeinfo->agg_enable_bitmap = 0;13832pmlmeinfo->candidate_tid_bitmap = 0;1383313834/* cancel link timer */13835_cancel_timer_ex(&pmlmeext->link_timer);1383613837/* clear CAM */13838flush_all_cam_entry(padapter);1383913840pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);13841_rtw_memcpy(pnetwork, pdev_network, FIELD_OFFSET(WLAN_BSSID_EX, IELength));13842pnetwork->IELength = pdev_network->IELength;1384313844if (pnetwork->IELength > MAX_IE_SZ) {13845ret = H2C_PARAMETERS_ERROR;13846goto ibss_post_hdl;13847}1384813849_rtw_memcpy(pnetwork->IEs, pdev_network->IEs, pnetwork->IELength);13850start_create_ibss(padapter);13851} else {13852rtw_warn_on(1);13853ret = H2C_PARAMETERS_ERROR;13854}1385513856ibss_post_hdl:13857rtw_create_ibss_post_hdl(padapter, ret);1385813859exit:13860return ret;13861}1386213863u8 join_cmd_hdl(_adapter *padapter, u8 *pbuf)13864{13865u8 join_type;13866PNDIS_802_11_VARIABLE_IEs pIE;13867struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;13868struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);13869WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));13870#ifdef CONFIG_ANTENNA_DIVERSITY13871struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;13872#endif /* CONFIG_ANTENNA_DIVERSITY */13873u32 i;13874/* u8 initialgain; */13875/* u32 acparm; */13876u8 u_ch, u_bw, u_offset;13877u8 doiqk = _FALSE;1387813879/* check already connecting to AP or not */13880if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {13881if (pmlmeinfo->state & WIFI_FW_STATION_STATE)13882issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);13883pmlmeinfo->state = WIFI_FW_NULL_STATE;1388413885/* clear CAM */13886flush_all_cam_entry(padapter);1388713888_cancel_timer_ex(&pmlmeext->link_timer);1388913890/* set MSR to nolink->infra. mode */13891/* Set_MSR(padapter, _HW_STATE_NOLINK_); */13892Set_MSR(padapter, _HW_STATE_STATION_);138931389413895rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);13896if (pmlmeinfo->state & WIFI_FW_STATION_STATE)13897rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_DISCONNECTED);13898}1389913900#ifdef CONFIG_ANTENNA_DIVERSITY13901rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, _FALSE);13902#endif1390313904#ifdef CONFIG_WAPI_SUPPORT13905rtw_wapi_clear_all_cam_entry(padapter);13906#endif1390713908rtw_joinbss_reset(padapter);1390913910pmlmeinfo->ERP_enable = 0;13911pmlmeinfo->WMM_enable = 0;13912pmlmeinfo->HT_enable = 0;13913pmlmeinfo->HT_caps_enable = 0;13914pmlmeinfo->HT_info_enable = 0;13915pmlmeinfo->agg_enable_bitmap = 0;13916pmlmeinfo->candidate_tid_bitmap = 0;13917pmlmeinfo->bwmode_updated = _FALSE;13918/* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */13919pmlmeinfo->VHT_enable = 0;13920#ifdef ROKU_PRIVATE13921pmlmeinfo->ht_vht_received = 0;13922_rtw_memset(pmlmeinfo->SupportedRates_infra_ap, 0, NDIS_802_11_LENGTH_RATES_EX);13923#endif /* ROKU_PRIVATE */13924_rtw_memcpy(pnetwork, pbuf, FIELD_OFFSET(WLAN_BSSID_EX, IELength));13925pnetwork->IELength = ((WLAN_BSSID_EX *)pbuf)->IELength;1392613927if (pnetwork->IELength > MAX_IE_SZ) /* Check pbuf->IELength */13928return H2C_PARAMETERS_ERROR;1392913930if (pnetwork->IELength < 2) {13931report_join_res(padapter, (-4), WLAN_STATUS_UNSPECIFIED_FAILURE);13932return H2C_SUCCESS;13933}13934_rtw_memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength);1393513936pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);1393713938/* Check AP vendor to move rtw_joinbss_cmd() */13939/* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */1394013941/* sizeof(NDIS_802_11_FIXED_IEs) */13942for (i = _FIXED_IE_LENGTH_ ; i < pnetwork->IELength - 2 ;) {13943pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);1394413945switch (pIE->ElementID) {13946case _VENDOR_SPECIFIC_IE_: /* Get WMM IE. */13947if (_rtw_memcmp(pIE->data, WMM_OUI, 4))13948WMM_param_handler(padapter, pIE);13949break;1395013951#ifdef CONFIG_80211N_HT13952case _HT_CAPABILITY_IE_: /* Get HT Cap IE. */13953pmlmeinfo->HT_caps_enable = 1;13954break;1395513956case _HT_EXTRA_INFO_IE_: /* Get HT Info IE. */13957pmlmeinfo->HT_info_enable = 1;13958break;13959#endif /* CONFIG_80211N_HT */1396013961#ifdef CONFIG_80211AC_VHT13962case EID_VHTCapability: /* Get VHT Cap IE. */13963pmlmeinfo->VHT_enable = 1;13964break;1396513966case EID_VHTOperation: /* Get VHT Operation IE. */13967break;13968#endif /* CONFIG_80211AC_VHT */13969default:13970break;13971}1397213973i += (pIE->Length + 2);13974}1397513976rtw_bss_get_chbw(pnetwork13977, &pmlmeext->cur_channel, &pmlmeext->cur_bwmode, &pmlmeext->cur_ch_offset, 1, 1);1397813979rtw_adjust_chbw(padapter, pmlmeext->cur_channel, &pmlmeext->cur_bwmode, &pmlmeext->cur_ch_offset);1398013981#if 013982if (padapter->registrypriv.wifi_spec) {13983/* for WiFi test, follow WMM test plan spec */13984acparm = 0x002F431C; /* VO */13985rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));13986acparm = 0x005E541C; /* VI */13987rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));13988acparm = 0x0000A525; /* BE */13989rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));13990acparm = 0x0000A549; /* BK */13991rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));1399213993/* for WiFi test, mixed mode with intel STA under bg mode throughput issue */13994if (padapter->mlmepriv.htpriv.ht_option == _FALSE) {13995acparm = 0x00004320;13996rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));13997}13998} else {13999acparm = 0x002F3217; /* VO */14000rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));14001acparm = 0x005E4317; /* VI */14002rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));14003acparm = 0x00105320; /* BE */14004rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));14005acparm = 0x0000A444; /* BK */14006rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));14007}14008#endif1400914010/* check channel, bandwidth, offset and switch */14011if (rtw_chk_start_clnt_join(padapter, &u_ch, &u_bw, &u_offset) == _FAIL) {14012report_join_res(padapter, (-4), WLAN_STATUS_UNSPECIFIED_FAILURE);14013return H2C_SUCCESS;14014}1401514016/* disable dynamic functions, such as high power, DIG */14017/*rtw_phydm_func_disable_all(padapter);*/1401814019/* config the initial gain under linking, need to write the BB registers */14020/* initialgain = 0x1E; */14021/*rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, _FALSE);*/1402214023rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);14024if (MLME_IS_STA(padapter))14025rtw_hal_rcr_set_chk_bssid(padapter, MLME_STA_CONNECTING);14026else14027rtw_hal_rcr_set_chk_bssid(padapter, MLME_ADHOC_STARTED);1402814029join_type = 0;14030rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));1403114032doiqk = _TRUE;14033rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);1403414035set_channel_bwmode(padapter, u_ch, u_offset, u_bw);14036rtw_mi_update_union_chan_inf(padapter, u_ch, u_offset, u_bw);1403714038doiqk = _FALSE;14039rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);1404014041/* cancel link timer */14042_cancel_timer_ex(&pmlmeext->link_timer);1404314044start_clnt_join(padapter);1404514046return H2C_SUCCESS;1404714048}1404914050u8 disconnect_hdl(_adapter *padapter, unsigned char *pbuf)14051{14052#ifdef CONFIG_DFS14053struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);14054#endif14055struct disconnect_parm *param = (struct disconnect_parm *)pbuf;14056struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;14057struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);14058WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)(&(pmlmeinfo->network));14059u8 val8;1406014061if (is_client_associated_to_ap(padapter)14062#ifdef CONFIG_DFS14063&& !IS_RADAR_DETECTED(rfctl) && !rfctl->csa_ch14064#endif14065) {14066#ifdef CONFIG_PLATFORM_ROCKCHIPS14067/* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */14068issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);14069#else14070issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms / 100, 100);14071#endif /* CONFIG_PLATFORM_ROCKCHIPS */14072}1407314074#ifndef CONFIG_SUPPORT_MULTI_BCN14075if (((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {14076/* Stop BCN */14077val8 = 0;14078rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));14079}14080#endif1408114082rtw_mlmeext_disconnect(padapter);1408314084rtw_free_uc_swdec_pending_queue(padapter);1408514086rtw_sta_mstatus_report(padapter);1408714088return H2C_SUCCESS;14089}1409014091static const char *const _scan_state_str[] = {14092"SCAN_DISABLE",14093"SCAN_START",14094"SCAN_PS_ANNC_WAIT",14095"SCAN_ENTER",14096"SCAN_PROCESS",14097"SCAN_BACKING_OP",14098"SCAN_BACK_OP",14099"SCAN_LEAVING_OP",14100"SCAN_LEAVE_OP",14101"SCAN_SW_ANTDIV_BL",14102"SCAN_TO_P2P_LISTEN",14103"SCAN_P2P_LISTEN",14104"SCAN_COMPLETE",14105"SCAN_STATE_MAX",14106};1410714108const char *scan_state_str(u8 state)14109{14110state = (state >= SCAN_STATE_MAX) ? SCAN_STATE_MAX : state;14111return _scan_state_str[state];14112}1411314114static bool scan_abort_hdl(_adapter *adapter)14115{14116struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;14117struct ss_res *ss = &pmlmeext->sitesurvey_res;14118#ifdef CONFIG_P2P14119struct wifidirect_info *pwdinfo = &adapter->wdinfo;14120#endif14121bool ret = _FALSE;1412214123if (pmlmeext->scan_abort == _TRUE) {14124#ifdef CONFIG_P2P14125if (!rtw_p2p_chk_state(&adapter->wdinfo, P2P_STATE_NONE)) {14126rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);14127ss->channel_idx = 3;14128RTW_INFO("%s idx:%d, cnt:%u\n", __FUNCTION__14129, ss->channel_idx14130, pwdinfo->find_phase_state_exchange_cnt14131);14132} else14133#endif14134{14135ss->channel_idx = ss->ch_num;14136RTW_INFO("%s idx:%d\n", __FUNCTION__14137, ss->channel_idx14138);14139}14140pmlmeext->scan_abort = _FALSE;14141ret = _TRUE;14142}1414314144return ret;14145}1414614147u8 rtw_scan_sparse(_adapter *adapter, struct rtw_ieee80211_channel *ch, u8 ch_num)14148{14149/* interval larger than this is treated as backgroud scan */14150#ifndef RTW_SCAN_SPARSE_BG_INTERVAL_MS14151#define RTW_SCAN_SPARSE_BG_INTERVAL_MS 1200014152#endif1415314154#ifndef RTW_SCAN_SPARSE_CH_NUM_MIRACAST14155#define RTW_SCAN_SPARSE_CH_NUM_MIRACAST 114156#endif14157#ifndef RTW_SCAN_SPARSE_CH_NUM_BG14158#define RTW_SCAN_SPARSE_CH_NUM_BG 414159#endif14160#ifdef CONFIG_LAYER2_ROAMING14161#ifndef RTW_SCAN_SPARSE_CH_NUM_ROAMING_ACTIVE14162#define RTW_SCAN_SPARSE_CH_NUM_ROAMING_ACTIVE 114163#endif14164#endif1416514166#define SCAN_SPARSE_CH_NUM_INVALID 2551416714168static u8 token = 255;14169u32 interval;14170bool busy_traffic = _FALSE;14171bool miracast_enabled = _FALSE;14172bool bg_scan = _FALSE;14173u8 max_allow_ch = SCAN_SPARSE_CH_NUM_INVALID;14174u8 scan_division_num;14175u8 ret_num = ch_num;14176struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter));14177struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;1417814179if (regsty->wifi_spec)14180goto exit;1418114182/* assume ch_num > 6 is normal scan */14183if (ch_num <= 6)14184goto exit;1418514186if (mlmeext->last_scan_time == 0)14187mlmeext->last_scan_time = rtw_get_current_time();1418814189interval = rtw_get_passing_time_ms(mlmeext->last_scan_time);141901419114192if (rtw_mi_busy_traffic_check(adapter, _FALSE))14193busy_traffic = _TRUE;1419414195if (rtw_mi_check_miracast_enabled(adapter))14196miracast_enabled = _TRUE;1419714198if (interval > RTW_SCAN_SPARSE_BG_INTERVAL_MS)14199bg_scan = _TRUE;1420014201/* max_allow_ch by conditions*/1420214203#if RTW_SCAN_SPARSE_MIRACAST14204if (miracast_enabled == _TRUE && busy_traffic == _TRUE)14205max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_MIRACAST);14206#endif1420714208#if RTW_SCAN_SPARSE_BG14209if (bg_scan == _TRUE)14210max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_BG);14211#endif1421214213#if defined(CONFIG_LAYER2_ROAMING) && defined(RTW_SCAN_SPARSE_ROAMING_ACTIVE)14214if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {14215if (busy_traffic == _TRUE && adapter->mlmepriv.need_to_roam == _TRUE)14216max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_ROAMING_ACTIVE);14217}14218#endif142191422014221if (max_allow_ch != SCAN_SPARSE_CH_NUM_INVALID) {14222int i;14223int k = 0;1422414225scan_division_num = (ch_num / max_allow_ch) + ((ch_num % max_allow_ch) ? 1 : 0);14226token = (token + 1) % scan_division_num;1422714228if (0)14229RTW_INFO("scan_division_num:%u, token:%u\n", scan_division_num, token);1423014231for (i = 0; i < ch_num; i++) {14232if (ch[i].hw_value && (i % scan_division_num) == token14233) {14234if (i != k)14235_rtw_memcpy(&ch[k], &ch[i], sizeof(struct rtw_ieee80211_channel));14236k++;14237}14238}1423914240_rtw_memset(&ch[k], 0, sizeof(struct rtw_ieee80211_channel));1424114242ret_num = k;14243mlmeext->last_scan_time = rtw_get_current_time();14244}1424514246exit:14247return ret_num;14248}1424914250#ifdef CONFIG_SCAN_BACKOP14251u8 rtw_scan_backop_decision(_adapter *adapter)14252{14253struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;14254struct mi_state mstate;14255u8 backop_flags = 0;1425614257rtw_mi_status(adapter, &mstate);1425814259if ((MSTATE_STA_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_sta(mlmeext, SS_BACKOP_EN))14260|| (MSTATE_STA_NUM(&mstate) && mlmeext_chk_scan_backop_flags_sta(mlmeext, SS_BACKOP_EN_NL)))14261backop_flags |= mlmeext_scan_backop_flags_sta(mlmeext);1426214263#ifdef CONFIG_AP_MODE14264if ((MSTATE_AP_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_ap(mlmeext, SS_BACKOP_EN))14265|| (MSTATE_AP_NUM(&mstate) && mlmeext_chk_scan_backop_flags_ap(mlmeext, SS_BACKOP_EN_NL)))14266backop_flags |= mlmeext_scan_backop_flags_ap(mlmeext);14267#endif1426814269#ifdef CONFIG_RTW_MESH14270if ((MSTATE_MESH_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_mesh(mlmeext, SS_BACKOP_EN))14271|| (MSTATE_MESH_NUM(&mstate) && mlmeext_chk_scan_backop_flags_mesh(mlmeext, SS_BACKOP_EN_NL)))14272backop_flags |= mlmeext_scan_backop_flags_mesh(mlmeext);14273#endif1427414275return backop_flags;14276}14277#endif1427814279#define SCANNING_TIMEOUT_EX 200014280u32 rtw_scan_timeout_decision(_adapter *padapter)14281{14282u32 back_op_times= 0;14283u8 max_chan_num;14284u16 scan_ms;14285struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;14286struct ss_res *ss = &pmlmeext->sitesurvey_res;1428714288if (is_supported_5g(padapter->registrypriv.wireless_mode)14289&& IsSupported24G(padapter->registrypriv.wireless_mode))14290max_chan_num = MAX_CHANNEL_NUM;/* dual band */14291else14292max_chan_num = MAX_CHANNEL_NUM_2G;/*single band*/1429314294#ifdef CONFIG_SCAN_BACKOP14295if (rtw_scan_backop_decision(padapter))14296back_op_times = (max_chan_num / ss->scan_cnt_max) * ss->backop_ms;14297#endif1429814299if (ss->duration)14300scan_ms = ss->duration;14301else14302#if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)14303if (IS_ACS_ENABLE(padapter) && rtw_is_acs_st_valid(padapter))14304scan_ms = rtw_acs_get_adv_st(padapter);14305else14306#endif /*CONFIG_RTW_ACS*/14307scan_ms = ss->scan_ch_ms;1430814309ss->scan_timeout_ms = (scan_ms * max_chan_num) + back_op_times + SCANNING_TIMEOUT_EX;14310#ifdef DBG_SITESURVEY14311RTW_INFO("%s , scan_timeout_ms = %d (ms)\n", __func__, ss->scan_timeout_ms);14312#endif /*DBG_SITESURVEY*/14313return ss->scan_timeout_ms;14314}1431514316static int rtw_scan_ch_decision(_adapter *padapter, struct rtw_ieee80211_channel *out,14317u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)14318{14319int i, j;14320int set_idx;14321u8 chan;14322struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);1432314324/* clear first */14325_rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel) * out_num);1432614327/* acquire channels from in */14328j = 0;14329for (i = 0; i < in_num; i++) {1433014331if (0)14332RTW_INFO(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));1433314334if (!in[i].hw_value || (in[i].flags & RTW_IEEE80211_CHAN_DISABLED))14335continue;14336if (rtw_mlme_band_check(padapter, in[i].hw_value) == _FALSE)14337continue;1433814339set_idx = rtw_chset_search_ch(rfctl->channel_set, in[i].hw_value);14340if (set_idx >= 0) {14341if (j >= out_num) {14342RTW_PRINT(FUNC_ADPT_FMT" out_num:%u not enough\n",14343FUNC_ADPT_ARG(padapter), out_num);14344break;14345}1434614347_rtw_memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));1434814349if (rfctl->channel_set[set_idx].ScanType == SCAN_PASSIVE)14350out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;1435114352j++;14353}14354if (j >= out_num)14355break;14356}1435714358/* if out is empty, use channel_set as default */14359if (j == 0) {14360for (i = 0; i < rfctl->max_chan_nums; i++) {14361chan = rfctl->channel_set[i].ChannelNum;14362if (rtw_mlme_band_check(padapter, chan) == _TRUE) {14363if (rtw_mlme_ignore_chan(padapter, chan) == _TRUE)14364continue;1436514366if (0)14367RTW_INFO(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), chan);1436814369if (j >= out_num) {14370RTW_PRINT(FUNC_ADPT_FMT" out_num:%u not enough\n",14371FUNC_ADPT_ARG(padapter), out_num);14372break;14373}1437414375out[j].hw_value = chan;1437614377if (rfctl->channel_set[i].ScanType == SCAN_PASSIVE)14378out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;1437914380j++;14381}14382}14383}1438414385/* scan_sparse */14386j = rtw_scan_sparse(padapter, out, j);1438714388return j;14389}1439014391static void sitesurvey_res_reset(_adapter *adapter, struct sitesurvey_parm *parm)14392{14393struct ss_res *ss = &adapter->mlmeextpriv.sitesurvey_res;14394RT_CHANNEL_INFO *chset = adapter_to_chset(adapter);14395int i;1439614397ss->bss_cnt = 0;14398ss->channel_idx = 0;14399#ifdef CONFIG_DFS14400ss->dfs_ch_ssid_scan = 0;14401#endif14402ss->igi_scan = 0;14403ss->igi_before_scan = 0;14404#ifdef CONFIG_SCAN_BACKOP14405ss->scan_cnt = 0;14406#endif14407#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)14408ss->is_sw_antdiv_bl_scan = 0;14409#endif14410ss->ssid_num = 0;14411for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {14412if (parm->ssid[i].SsidLength) {14413_rtw_memcpy(ss->ssid[i].Ssid, parm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);14414ss->ssid[i].SsidLength = parm->ssid[i].SsidLength;14415ss->ssid_num++;14416} else14417ss->ssid[i].SsidLength = 0;14418}1441914420ss->ch_num = rtw_scan_ch_decision(adapter14421, ss->ch, RTW_CHANNEL_SCAN_AMOUNT14422, parm->ch, parm->ch_num14423);1442414425#ifdef CONFIG_DFS14426for (i = 0; i < MAX_CHANNEL_NUM; i++)14427chset[i].hidden_bss_cnt = 0;14428#endif1442914430ss->bw = parm->bw;14431ss->igi = parm->igi;14432ss->token = parm->token;14433ss->duration = parm->duration;14434ss->scan_mode = parm->scan_mode;14435ss->token = parm->token;14436}1443714438static u8 sitesurvey_pick_ch_behavior(_adapter *padapter, u8 *ch, RT_SCAN_TYPE *type)14439{14440u8 next_state;14441u8 scan_ch = 0;14442RT_SCAN_TYPE scan_type = SCAN_PASSIVE;14443struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;14444struct ss_res *ss = &pmlmeext->sitesurvey_res;14445struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);14446int ch_set_idx;14447#ifdef CONFIG_P2P14448struct wifidirect_info *pwdinfo = &padapter->wdinfo;14449#endif14450#ifdef CONFIG_SCAN_BACKOP14451u8 backop_flags = 0;14452#endif1445314454/* handle scan abort request */14455scan_abort_hdl(padapter);1445614457#ifdef CONFIG_P2P14458if (pwdinfo->rx_invitereq_info.scan_op_ch_only || pwdinfo->p2p_info.scan_op_ch_only) {14459if (pwdinfo->rx_invitereq_info.scan_op_ch_only)14460scan_ch = pwdinfo->rx_invitereq_info.operation_ch[ss->channel_idx];14461else14462scan_ch = pwdinfo->p2p_info.operation_ch[ss->channel_idx];14463scan_type = SCAN_ACTIVE;14464} else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {14465/*14466* Commented by Albert 2011/06/0314467* The driver is in the find phase, it should go through the social channel.14468*/14469scan_ch = pwdinfo->social_chan[ss->channel_idx];14470ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, scan_ch);14471if (ch_set_idx >= 0)14472scan_type = rfctl->channel_set[ch_set_idx].ScanType;14473else14474scan_type = SCAN_ACTIVE;14475} else14476#endif /* CONFIG_P2P */14477{14478struct rtw_ieee80211_channel *ch;1447914480#ifdef CONFIG_SCAN_BACKOP14481backop_flags = rtw_scan_backop_decision(padapter);14482#endif1448314484#ifdef CONFIG_DFS14485#ifdef CONFIG_SCAN_BACKOP14486if (!(backop_flags && ss->scan_cnt >= ss->scan_cnt_max))14487#endif14488{14489#ifdef CONFIG_RTW_WIFI_HAL14490if (adapter_to_dvobj(padapter)->nodfs) {14491while ( ss->channel_idx < ss->ch_num && rtw_is_dfs_ch(ss->ch[ss->channel_idx].hw_value))14492ss->channel_idx++;14493} else14494#endif14495if (ss->channel_idx != 0 && ss->dfs_ch_ssid_scan == 014496&& pmlmeext->sitesurvey_res.ssid_num14497&& rtw_is_dfs_ch(ss->ch[ss->channel_idx - 1].hw_value)14498) {14499ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, ss->ch[ss->channel_idx - 1].hw_value);14500if (ch_set_idx != -1 && rfctl->channel_set[ch_set_idx].hidden_bss_cnt14501&& (!IS_DFS_SLAVE_WITH_RD(rfctl)14502|| rtw_odm_dfs_domain_unknown(rfctl_to_dvobj(rfctl))14503|| !CH_IS_NON_OCP(&rfctl->channel_set[ch_set_idx]))14504) {14505ss->channel_idx--;14506ss->dfs_ch_ssid_scan = 1;14507}14508} else14509ss->dfs_ch_ssid_scan = 0;14510}14511#endif /* CONFIG_DFS */1451214513if (ss->channel_idx < ss->ch_num) {14514ch = &ss->ch[ss->channel_idx];14515scan_ch = ch->hw_value;1451614517#if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)14518if (IS_ACS_ENABLE(padapter) && rtw_is_acs_passiv_scan(padapter))14519scan_type = SCAN_PASSIVE;14520else14521#endif /*CONFIG_RTW_ACS*/14522scan_type = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;14523}14524}1452514526if (scan_ch != 0) {14527next_state = SCAN_PROCESS;1452814529#ifdef CONFIG_SCAN_BACKOP14530if (backop_flags) {14531if (ss->scan_cnt < ss->scan_cnt_max)14532ss->scan_cnt++;14533else {14534mlmeext_assign_scan_backop_flags(pmlmeext, backop_flags);14535next_state = SCAN_BACKING_OP;14536}14537}14538#endif1453914540} else if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) {14541/* go p2p listen */14542next_state = SCAN_TO_P2P_LISTEN;1454314544#ifdef CONFIG_ANTENNA_DIVERSITY14545} else if (rtw_hal_antdiv_before_linked(padapter)) {14546/* go sw antdiv before link */14547next_state = SCAN_SW_ANTDIV_BL;14548#endif14549} else {14550next_state = SCAN_COMPLETE;1455114552#if defined(DBG_SCAN_SW_ANTDIV_BL)14553{14554/* for SCAN_SW_ANTDIV_BL state testing */14555struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);14556int i;14557bool is_linked = _FALSE;1455814559for (i = 0; i < dvobj->iface_nums; i++) {14560if (rtw_linked_check(dvobj->padapters[i]))14561is_linked = _TRUE;14562}1456314564if (!is_linked) {14565static bool fake_sw_antdiv_bl_state = 0;1456614567if (fake_sw_antdiv_bl_state == 0) {14568next_state = SCAN_SW_ANTDIV_BL;14569fake_sw_antdiv_bl_state = 1;14570} else14571fake_sw_antdiv_bl_state = 0;14572}14573}14574#endif /* defined(DBG_SCAN_SW_ANTDIV_BL) */14575}1457614577#ifdef CONFIG_SCAN_BACKOP14578if (next_state != SCAN_PROCESS)14579ss->scan_cnt = 0;14580#endif145811458214583#ifdef DBG_FIXED_CHAN14584if (pmlmeext->fixed_chan != 0xff && next_state == SCAN_PROCESS)14585scan_ch = pmlmeext->fixed_chan;14586#endif1458714588if (ch)14589*ch = scan_ch;14590if (type)14591*type = scan_type;1459214593return next_state;14594}1459514596void site_survey(_adapter *padapter, u8 survey_channel, RT_SCAN_TYPE ScanType)14597{14598struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;14599struct ss_res *ss = &pmlmeext->sitesurvey_res;14600u8 ssid_scan = 0;1460114602#ifdef CONFIG_P2P14603#ifndef CONFIG_IOCTL_CFG8021114604struct wifidirect_info *pwdinfo = &(padapter->wdinfo);14605#endif14606#endif1460714608if (survey_channel != 0) {14609set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);1461014611#ifdef CONFIG_DFS14612if (ScanType == SCAN_PASSIVE && ss->dfs_ch_ssid_scan)14613ssid_scan = 1;14614else14615#endif14616if (ScanType == SCAN_ACTIVE) {14617#ifdef CONFIG_P2P14618#ifdef CONFIG_IOCTL_CFG8021114619if (rtw_cfg80211_is_p2p_scan(padapter))14620#else14621if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)14622|| rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))14623#endif14624{14625issue_probereq_p2p(padapter, NULL);14626issue_probereq_p2p(padapter, NULL);14627issue_probereq_p2p(padapter, NULL);14628} else14629#endif /* CONFIG_P2P */14630{14631if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {14632/* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */14633if (padapter->registrypriv.wifi_spec)14634issue_probereq(padapter, NULL, NULL);14635else14636issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);14637issue_probereq(padapter, NULL, NULL);14638}1463914640ssid_scan = 1;14641}14642}1464314644if (ssid_scan) {14645int i;1464614647for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {14648if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {14649/* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */14650if (padapter->registrypriv.wifi_spec)14651issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);14652else14653issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);14654issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);14655}14656}14657}14658} else {14659/* channel number is 0 or this channel is not valid. */14660rtw_warn_on(1);14661}1466214663return;14664}1466514666void survey_done_set_ch_bw(_adapter *padapter)14667{14668struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;14669u8 cur_channel = 0;14670u8 cur_bwmode;14671u8 cur_ch_offset;1467214673#ifdef CONFIG_MCC_MODE14674if (!rtw_hal_mcc_change_scan_flag(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset)) {14675if (0)14676RTW_INFO(FUNC_ADPT_FMT" back to AP channel - ch:%u, bw:%u, offset:%u\n",14677FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);14678goto exit;14679}14680#endif1468114682if (rtw_mi_get_ch_setting_union(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset) != 0) {14683if (0)14684RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",14685FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);14686} else {14687#ifdef CONFIG_P2P14688struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);14689_adapter *iface;14690int i;1469114692for (i = 0; i < dvobj->iface_nums; i++) {14693iface = dvobj->padapters[i];14694if (!iface)14695continue;1469614697#ifdef CONFIG_IOCTL_CFG8021114698if (iface->wdinfo.driver_interface == DRIVER_CFG80211 && !adapter_wdev_data(iface)->p2p_enabled)14699continue;14700#endif1470114702if (rtw_p2p_chk_state(&iface->wdinfo, P2P_STATE_LISTEN)) {14703cur_channel = iface->wdinfo.listen_channel;14704cur_bwmode = CHANNEL_WIDTH_20;14705cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;14706if (0)14707RTW_INFO(FUNC_ADPT_FMT" back to "ADPT_FMT"'s listen ch - ch:%u, bw:%u, offset:%u\n",14708FUNC_ADPT_ARG(padapter), ADPT_ARG(iface), cur_channel, cur_bwmode, cur_ch_offset);14709break;14710}14711}14712#endif /* CONFIG_P2P */1471314714if (cur_channel == 0) {14715cur_channel = pmlmeext->cur_channel;14716cur_bwmode = pmlmeext->cur_bwmode;14717cur_ch_offset = pmlmeext->cur_ch_offset;14718if (0)14719RTW_INFO(FUNC_ADPT_FMT" back to ch:%u, bw:%u, offset:%u\n",14720FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);14721}14722}14723#ifdef CONFIG_MCC_MODE14724exit:14725#endif14726set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);14727}1472814729/**14730* rtw_ps_annc - check and doing ps announcement for all the adapters14731* @adapter: the requesting adapter14732* @ps: power saving or not14733*14734* Returns: 0: no ps announcement is doing. 1: ps announcement is doing14735*/14736u8 rtw_ps_annc(_adapter *adapter, bool ps)14737{14738struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);14739_adapter *iface;14740int i;14741u8 ps_anc = 0;1474214743for (i = 0; i < dvobj->iface_nums; i++) {14744iface = dvobj->padapters[i];14745if (!iface)14746continue;1474714748if (MLME_IS_STA(iface)) {14749if (is_client_associated_to_ap(iface) == _TRUE) {14750/* TODO: TDLS peers */14751#ifdef CONFIG_MCC_MODE14752/* for two station case */14753if (MCC_EN(adapter) && rtw_hal_check_mcc_status(adapter, MCC_STATUS_NEED_MCC)) {14754u8 ch = iface->mlmeextpriv.cur_channel;14755u8 offset = iface->mlmeextpriv.cur_ch_offset;14756u8 bw = iface->mlmeextpriv.cur_bwmode;1475714758set_channel_bwmode(iface, ch, offset, bw);14759}14760#endif /* CONFIG_MCC_MODE */14761issue_nulldata(iface, NULL, ps, 3, 500);14762ps_anc = 1;14763}14764#ifdef CONFIG_RTW_MESH14765} else if (MLME_IS_MESH(iface)) {14766if (rtw_mesh_ps_annc(iface, ps))14767ps_anc = 1;14768#endif14769}14770}14771return ps_anc;14772}1477314774void rtw_leave_opch(_adapter *adapter)14775{14776struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);1477714778#ifdef CONFIG_MCC_MODE14779if (MCC_EN(adapter) && rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC))14780return;14781#endif1478214783_enter_critical_mutex(&rfctl->offch_mutex, NULL);1478414785if (rfctl->offch_state == OFFCHS_NONE) {14786/* prepare to leave operating channel */14787rfctl->offch_state = OFFCHS_LEAVING_OP;1478814789/* clear HW TX queue */14790rtw_hal_set_hwreg(adapter, HW_VAR_CHECK_TXBUF, 0);1479114792rtw_hal_macid_sleep_all_used(adapter);1479314794rtw_ps_annc(adapter, 1);1479514796rfctl->offch_state = OFFCHS_LEAVE_OP;14797}1479814799_exit_critical_mutex(&rfctl->offch_mutex, NULL);14800}1480114802void rtw_back_opch(_adapter *adapter)14803{14804struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);1480514806#ifdef CONFIG_MCC_MODE14807if (MCC_EN(adapter) && rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC))14808return;14809#endif1481014811_enter_critical_mutex(&rfctl->offch_mutex, NULL);1481214813if (rfctl->offch_state != OFFCHS_NONE) {14814rfctl->offch_state = OFFCHS_BACKING_OP;14815rtw_hal_macid_wakeup_all_used(adapter);14816rtw_ps_annc(adapter, 0);1481714818rfctl->offch_state = OFFCHS_NONE;14819rtw_mi_os_xmit_schedule(adapter);14820}1482114822_exit_critical_mutex(&rfctl->offch_mutex, NULL);14823}1482414825void sitesurvey_set_igi(_adapter *adapter)14826{14827struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;14828struct ss_res *ss = &mlmeext->sitesurvey_res;14829u8 igi;14830#ifdef CONFIG_P2P14831struct wifidirect_info *pwdinfo = &adapter->wdinfo;14832#endif1483314834switch (mlmeext_scan_state(mlmeext)) {14835case SCAN_ENTER:14836#ifdef CONFIG_P2P14837#ifdef CONFIG_IOCTL_CFG8021114838if (pwdinfo->driver_interface == DRIVER_CFG80211 && rtw_cfg80211_is_p2p_scan(adapter))14839igi = 0x30;14840else14841#endif /* CONFIG_IOCTL_CFG80211 */14842if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))14843igi = 0x28;14844else14845#endif /* CONFIG_P2P */1484614847if (ss->igi)14848igi = ss->igi;14849else14850#if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)14851if (IS_ACS_ENABLE(adapter) && rtw_is_acs_igi_valid(adapter))14852igi = rtw_acs_get_adv_igi(adapter);14853else14854#endif /*CONFIG_RTW_ACS*/14855igi = 0x1e;1485614857/* record IGI status */14858ss->igi_scan = igi;14859rtw_hal_get_odm_var(adapter, HAL_ODM_INITIAL_GAIN, &ss->igi_before_scan, NULL);1486014861/* disable DIG and set IGI for scan */14862rtw_hal_set_odm_var(adapter, HAL_ODM_INITIAL_GAIN, &igi, _FALSE);14863break;14864case SCAN_COMPLETE:14865case SCAN_TO_P2P_LISTEN:14866/* enable DIG and restore IGI */14867igi = 0xff;14868rtw_hal_set_odm_var(adapter, HAL_ODM_INITIAL_GAIN, &igi, _FALSE);14869break;14870#ifdef CONFIG_SCAN_BACKOP14871case SCAN_BACKING_OP:14872/* write IGI for op channel when DIG is not enabled */14873odm_write_dig(adapter_to_phydm(adapter), ss->igi_before_scan);14874break;14875case SCAN_LEAVE_OP:14876/* write IGI for scan when DIG is not enabled */14877odm_write_dig(adapter_to_phydm(adapter), ss->igi_scan);14878break;14879#endif /* CONFIG_SCAN_BACKOP */14880default:14881rtw_warn_on(1);14882break;14883}14884}14885void sitesurvey_set_msr(_adapter *adapter, bool enter)14886{14887u8 network_type;14888struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;14889struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1489014891if (enter) {14892#ifdef CONFIG_MI_WITH_MBSSID_CAM14893rtw_hal_get_hwreg(adapter, HW_VAR_MEDIA_STATUS, (u8 *)(&pmlmeinfo->hw_media_state));14894#endif14895/* set MSR to no link state */14896network_type = _HW_STATE_NOLINK_;14897} else {14898#ifdef CONFIG_MI_WITH_MBSSID_CAM14899network_type = pmlmeinfo->hw_media_state;14900#else14901network_type = pmlmeinfo->state & 0x3;14902#endif14903}14904Set_MSR(adapter, network_type);14905}1490614907void sitesurvey_set_offch_state(_adapter *adapter, u8 scan_state)14908{14909struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);1491014911_enter_critical_mutex(&rfctl->offch_mutex, NULL);1491214913switch (scan_state) {14914case SCAN_DISABLE:14915case SCAN_BACK_OP:14916rfctl->offch_state = OFFCHS_NONE;14917break;14918case SCAN_START:14919case SCAN_LEAVING_OP:14920rfctl->offch_state = OFFCHS_LEAVING_OP;14921break;14922case SCAN_ENTER:14923case SCAN_LEAVE_OP:14924rfctl->offch_state = OFFCHS_LEAVE_OP;14925break;14926case SCAN_COMPLETE:14927case SCAN_BACKING_OP:14928rfctl->offch_state = OFFCHS_BACKING_OP;14929break;14930default:14931break;14932}1493314934_exit_critical_mutex(&rfctl->offch_mutex, NULL);14935}1493614937u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf)14938{14939struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf;14940#ifdef DBG_CHECK_FW_PS_STATE14941struct dvobj_priv *dvobj = padapter->dvobj;14942struct debug_priv *pdbgpriv = &dvobj->drv_dbg;14943#endif14944struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;14945struct ss_res *ss = &pmlmeext->sitesurvey_res;14946#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI14947struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);14948#endif14949u8 val8;1495014951#ifdef CONFIG_P2P14952struct wifidirect_info *pwdinfo = &padapter->wdinfo;14953#endif1495414955#ifdef DBG_CHECK_FW_PS_STATE14956if (rtw_fw_ps_state(padapter) == _FAIL) {14957RTW_INFO("scan without leave 32k\n");14958pdbgpriv->dbg_scan_pwr_state_cnt++;14959}14960#endif /* DBG_CHECK_FW_PS_STATE */1496114962/* increase channel idx */14963if (mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS))14964ss->channel_idx++;1496514966/* update scan state to next state (assigned by previous cmd hdl) */14967if (mlmeext_scan_state(pmlmeext) != mlmeext_scan_next_state(pmlmeext))14968mlmeext_set_scan_state(pmlmeext, mlmeext_scan_next_state(pmlmeext));1496914970operation_by_state:14971switch (mlmeext_scan_state(pmlmeext)) {1497214973case SCAN_DISABLE:14974/*14975* SW parameter initialization14976*/1497714978sitesurvey_res_reset(padapter, pparm);14979mlmeext_set_scan_state(pmlmeext, SCAN_START);14980goto operation_by_state;1498114982case SCAN_START:14983#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI14984if ((pwdev_priv->pno_mac_addr[0] != 0xFF)14985&& (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == _TRUE)14986&& (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _FALSE)) {14987u16 seq_num;1498814989rtw_hal_pno_random_gen_mac_addr(padapter);14990rtw_hal_set_hw_mac_addr(padapter, pwdev_priv->pno_mac_addr);14991get_random_bytes(&seq_num, 2);14992pwdev_priv->pno_scan_seq_num = seq_num & 0xFFF;14993RTW_INFO("%s pno_scan_seq_num %d\n", __func__,14994pwdev_priv->pno_scan_seq_num);14995}14996#endif1499714998/*14999* prepare to leave operating channel15000*/1500115002#ifdef CONFIG_MCC_MODE15003rtw_hal_set_mcc_setting_scan_start(padapter);15004#endif /* CONFIG_MCC_MODE */1500515006/* apply rx ampdu setting */15007if (ss->rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID15008|| ss->rx_ampdu_size != RX_AMPDU_SIZE_INVALID)15009rtw_rx_ampdu_apply(padapter);1501015011/* clear HW TX queue before scan */15012rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);1501315014rtw_hal_macid_sleep_all_used(padapter);1501515016/* power save state announcement */15017if (rtw_ps_annc(padapter, 1)) {15018mlmeext_set_scan_state(pmlmeext, SCAN_PS_ANNC_WAIT);15019mlmeext_set_scan_next_state(pmlmeext, SCAN_ENTER);15020set_survey_timer(pmlmeext, 50); /* delay 50ms to protect nulldata(1) */15021} else {15022mlmeext_set_scan_state(pmlmeext, SCAN_ENTER);15023goto operation_by_state;15024}1502515026break;1502715028case SCAN_ENTER:15029/*15030* HW register and DM setting for enter scan15031*/1503215033rtw_phydm_ability_backup(padapter);1503415035sitesurvey_set_igi(padapter);1503615037/* config dynamic functions for off channel */15038rtw_phydm_func_for_offchannel(padapter);15039/* set MSR to no link state */15040sitesurvey_set_msr(padapter, _TRUE);1504115042val8 = 1; /* under site survey */15043rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));1504415045mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);15046goto operation_by_state;1504715048case SCAN_PROCESS: {15049u8 scan_ch;15050RT_SCAN_TYPE scan_type;15051u8 next_state;15052u32 scan_ms;1505315054#ifdef CONFIG_RTW_ACS15055if (IS_ACS_ENABLE(padapter))15056rtw_acs_get_rst(padapter);15057#endif1505815059next_state = sitesurvey_pick_ch_behavior(padapter, &scan_ch, &scan_type);1506015061if (next_state != SCAN_PROCESS) {15062mlmeext_set_scan_state(pmlmeext, next_state);15063goto operation_by_state;15064}1506515066/* still SCAN_PROCESS state */15067#ifdef DBG_SITESURVEY15068#ifdef CONFIG_P2P15069RTW_INFO(FUNC_ADPT_FMT" %s ch:%u (cnt:%u,idx:%d) at %dms, %c%c%c%c\n"15070, FUNC_ADPT_ARG(padapter)15071, mlmeext_scan_state_str(pmlmeext)15072, scan_ch15073, pwdinfo->find_phase_state_exchange_cnt, ss->channel_idx15074, rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)15075, scan_type ? 'A' : 'P', ss->scan_mode ? 'A' : 'P'15076, ss->ssid[0].SsidLength ? 'S' : ' '15077, ss->dfs_ch_ssid_scan ? 'D' : ' '15078);15079#else15080RTW_INFO(FUNC_ADPT_FMT" %s ch:%u (idx:%d) at %dms, %c%c%c%c\n"15081, FUNC_ADPT_ARG(padapter)15082, mlmeext_scan_state_str(pmlmeext)15083, scan_ch15084, ss->channel_idx15085, rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)15086, scan_type ? 'A' : 'P', ss->scan_mode ? 'A' : 'P'15087, ss->ssid[0].SsidLength ? 'S' : ' '15088, ss->dfs_ch_ssid_scan ? 'D' : ' '15089);15090#endif /* CONFIG_P2P */15091#endif /*DBG_SITESURVEY*/15092#ifdef DBG_FIXED_CHAN15093if (pmlmeext->fixed_chan != 0xff)15094RTW_INFO(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan);15095#endif1509615097site_survey(padapter, scan_ch, scan_type);1509815099#if defined(CONFIG_ATMEL_RC_PATCH)15100if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)15101scan_ms = 20;15102else15103scan_ms = 40;15104#else15105#if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)15106if (IS_ACS_ENABLE(padapter) && rtw_is_acs_st_valid(padapter))15107scan_ms = rtw_acs_get_adv_st(padapter);15108else15109#endif /*CONFIG_RTW_ACS*/15110scan_ms = ss->scan_ch_ms;15111#endif1511215113#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)15114if (ss->is_sw_antdiv_bl_scan)15115scan_ms = scan_ms / 2;15116#endif1511715118#ifdef CONFIG_RTW_ACS15119if (IS_ACS_ENABLE(padapter)) {15120if (pparm->token)15121rtw_acs_trigger(padapter, scan_ms, scan_ch, NHM_PID_IEEE_11K_HIGH);15122else15123rtw_acs_trigger(padapter, scan_ms, scan_ch, NHM_PID_ACS);15124}15125#endif1512615127#ifdef CONFIG_BACKGROUND_NOISE_MONITOR15128if (IS_NM_ENABLE(padapter))15129rtw_noise_measure(padapter, scan_ch, _FALSE, 0, scan_ms / 2);15130#endif15131set_survey_timer(pmlmeext, scan_ms);15132break;15133}1513415135#ifdef CONFIG_SCAN_BACKOP15136case SCAN_BACKING_OP: {15137u8 back_ch, back_bw, back_ch_offset;15138u8 need_ch_setting_union = _TRUE;1513915140#ifdef CONFIG_MCC_MODE15141need_ch_setting_union = rtw_hal_mcc_change_scan_flag(padapter,15142&back_ch, &back_bw, &back_ch_offset);15143#endif /* CONFIG_MCC_MODE */1514415145if (need_ch_setting_union) {15146if (rtw_mi_get_ch_setting_union(padapter, &back_ch, &back_bw, &back_ch_offset) == 0)15147rtw_warn_on(1);15148}1514915150#ifdef DBG_SITESURVEY15151RTW_INFO(FUNC_ADPT_FMT" %s ch:%u, bw:%u, offset:%u at %dms\n"15152, FUNC_ADPT_ARG(padapter)15153, mlmeext_scan_state_str(pmlmeext)15154, back_ch, back_bw, back_ch_offset15155, rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)15156);15157#endif /*DBG_SITESURVEY*/15158set_channel_bwmode(padapter, back_ch, back_ch_offset, back_bw);1515915160sitesurvey_set_msr(padapter, _FALSE);1516115162val8 = 0; /* survey done */15163rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));1516415165if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)) {15166sitesurvey_set_igi(padapter);15167rtw_hal_macid_wakeup_all_used(padapter);15168rtw_ps_annc(padapter, 0);15169}1517015171mlmeext_set_scan_state(pmlmeext, SCAN_BACK_OP);15172ss->backop_time = rtw_get_current_time();1517315174if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_TX_RESUME))15175rtw_mi_os_xmit_schedule(padapter);151761517715178goto operation_by_state;15179}1518015181case SCAN_BACK_OP:15182if (rtw_get_passing_time_ms(ss->backop_time) >= ss->backop_ms15183|| pmlmeext->scan_abort15184) {15185mlmeext_set_scan_state(pmlmeext, SCAN_LEAVING_OP);15186goto operation_by_state;15187}15188set_survey_timer(pmlmeext, 50);15189break;1519015191case SCAN_LEAVING_OP:15192/*15193* prepare to leave operating channel15194*/1519515196/* clear HW TX queue before scan */15197rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);1519815199rtw_hal_macid_sleep_all_used(padapter);15200if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)15201&& rtw_ps_annc(padapter, 1)15202) {15203mlmeext_set_scan_state(pmlmeext, SCAN_PS_ANNC_WAIT);15204mlmeext_set_scan_next_state(pmlmeext, SCAN_LEAVE_OP);15205set_survey_timer(pmlmeext, 50); /* delay 50ms to protect nulldata(1) */15206} else {15207mlmeext_set_scan_state(pmlmeext, SCAN_LEAVE_OP);15208goto operation_by_state;15209}1521015211break;1521215213case SCAN_LEAVE_OP:15214/*15215* HW register and DM setting for enter scan15216*/1521715218if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC))15219sitesurvey_set_igi(padapter);1522015221sitesurvey_set_msr(padapter, _TRUE);1522215223val8 = 1; /* under site survey */15224rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));1522515226mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);15227goto operation_by_state;1522815229#endif /* CONFIG_SCAN_BACKOP */1523015231#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)15232case SCAN_SW_ANTDIV_BL:15233/*15234* 2010072115235* For SW antenna diversity before link, it needs to switch to another antenna and scan again.15236* It compares the scan result and select better one to do connection.15237*/15238ss->bss_cnt = 0;15239ss->channel_idx = 0;15240ss->is_sw_antdiv_bl_scan = 1;1524115242mlmeext_set_scan_next_state(pmlmeext, SCAN_PROCESS);15243set_survey_timer(pmlmeext, ss->scan_ch_ms);15244break;15245#endif1524615247#ifdef CONFIG_P2P15248case SCAN_TO_P2P_LISTEN:15249/*15250* Set the P2P State to the listen state of find phase15251* and set the current channel to the listen channel15252*/15253set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);15254rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);1525515256/* turn on phy-dynamic functions */15257rtw_phydm_ability_restore(padapter);1525815259sitesurvey_set_igi(padapter);1526015261mlmeext_set_scan_state(pmlmeext, SCAN_P2P_LISTEN);15262_set_timer(&pwdinfo->find_phase_timer, (u32)((u32)pwdinfo->listen_dwell * 100));15263break;1526415265case SCAN_P2P_LISTEN:15266mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);15267ss->channel_idx = 0;15268goto operation_by_state;15269#endif /* CONFIG_P2P */1527015271case SCAN_COMPLETE:15272#ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI15273rtw_hal_set_hw_mac_addr(padapter, adapter_mac_addr(padapter));15274#endif15275#ifdef CONFIG_P2P15276if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)15277|| rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)15278) {15279#ifdef CONFIG_CONCURRENT_MODE15280if (pwdinfo->driver_interface == DRIVER_WEXT) {15281if (rtw_mi_check_status(padapter, MI_LINKED))15282_set_timer(&pwdinfo->ap_p2p_switch_timer, 500);15283}15284#endif1528515286rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));15287}15288rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);15289#endif /* CONFIG_P2P */1529015291/* switch channel */15292survey_done_set_ch_bw(padapter);1529315294sitesurvey_set_msr(padapter, _FALSE);1529515296val8 = 0; /* survey done */15297rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));1529815299/* turn on phy-dynamic functions */15300rtw_phydm_ability_restore(padapter);1530115302sitesurvey_set_igi(padapter);1530315304#ifdef CONFIG_MCC_MODE15305/* start MCC fail, then tx null data */15306if (!rtw_hal_set_mcc_setting_scan_complete(padapter))15307#endif15308{15309rtw_hal_macid_wakeup_all_used(padapter);15310rtw_ps_annc(padapter, 0);15311}1531215313/* apply rx ampdu setting */15314rtw_rx_ampdu_apply(padapter);1531515316mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE);1531715318report_surveydone_event(padapter);15319#ifdef CONFIG_RTW_ACS15320if (IS_ACS_ENABLE(padapter))15321rtw_acs_select_best_chan(padapter);15322#endif1532315324#if defined(CONFIG_BACKGROUND_NOISE_MONITOR) && defined(DBG_NOISE_MONITOR)15325if (IS_NM_ENABLE(padapter))15326rtw_noise_info_dump(RTW_DBGDUMP, padapter);15327#endif15328issue_action_BSSCoexistPacket(padapter);15329issue_action_BSSCoexistPacket(padapter);15330issue_action_BSSCoexistPacket(padapter);1533115332#ifdef CONFIG_RTW_80211K15333if (ss->token)15334rm_post_event(padapter, ss->token, RM_EV_survey_done);15335#endif /* CONFIG_RTW_80211K */1533615337break;15338}1533915340return H2C_SUCCESS;15341}1534215343u8 setauth_hdl(_adapter *padapter, unsigned char *pbuf)15344{15345struct setauth_parm *pparm = (struct setauth_parm *)pbuf;15346struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;15347struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1534815349if (pparm->mode < 4)15350pmlmeinfo->auth_algo = pparm->mode;1535115352return H2C_SUCCESS;15353}1535415355/*15356SEC CAM Entry format (32 bytes)15357DW0 - MAC_ADDR[15:0] | Valid[15] | MFB[14:8] | RSVD[7] | GK[6] | MIC_KEY[5] | SEC_TYPE[4:2] | KID[1:0]15358DW0 - MAC_ADDR[15:0] | Valid[15] |RSVD[14:9] | RPT_MODE[8] | SPP_MODE[7] | GK[6] | MIC_KEY[5] | SEC_TYPE[4:2] | KID[1:0] (92E/8812A/8814A)15359DW1 - MAC_ADDR[47:16]15360DW2 - KEY[31:0]15361DW3 - KEY[63:32]15362DW4 - KEY[95:64]15363DW5 - KEY[127:96]15364DW6 - RSVD15365DW7 - RSVD15366*/1536715368/*Set WEP key or Group Key*/15369u8 setkey_hdl(_adapter *padapter, u8 *pbuf)15370{15371u16 ctrl = 0;15372s16 cam_id = 0;15373struct setkey_parm *pparm = (struct setkey_parm *)pbuf;15374struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;15375struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);15376unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};15377u8 *addr;15378bool used = _FALSE;1537915380/* main tx key for wep. */15381if (pparm->set_tx)15382pmlmeinfo->key_index = pparm->keyid;1538315384#ifdef CONFIG_CONCURRENT_MODE15385if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE))15386cam_id = rtw_iface_bcmc_id_get(padapter);15387else15388#endif15389cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid, 1, &used);1539015391if (cam_id < 0)15392goto enable_mc;1539315394#ifndef CONFIG_CONCURRENT_MODE15395if (cam_id >= 0 && cam_id <= 3) {15396/* default key camid */15397addr = null_addr;15398} else15399#endif15400{15401/* not default key camid */15402if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) {15403/* group TX, force sec cam entry_id */15404addr = adapter_mac_addr(padapter);15405} else {15406/* group RX, searched by A2 (TA) */15407addr = get_bssid(&padapter->mlmepriv);15408}15409}1541015411#ifdef CONFIG_LPS_PG15412if (adapter_to_pwrctl(padapter)->lps_level == LPS_PG)15413LPS_Leave(padapter, "SET_KEY");15414#endif1541515416/* cam entry searched is pairwise key */15417if (used == _TRUE && rtw_camid_is_gk(padapter, cam_id) == _FALSE) {15418s16 camid_clr;1541915420RTW_PRINT(FUNC_ADPT_FMT" group key with "MAC_FMT" id:%u the same key id as pairwise key\n"15421, FUNC_ADPT_ARG(padapter), MAC_ARG(addr), pparm->keyid);1542215423/* HW has problem to distinguish this group key with existing pairwise key, stop HW enc and dec for BMC */15424rtw_camctl_set_flags(padapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH);15425rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, NULL);1542615427/* clear group key */15428while ((camid_clr = rtw_camid_search(padapter, addr, -1, 1)) >= 0) {15429RTW_PRINT("clear group key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(addr), camid_clr);15430clear_cam_entry(padapter, camid_clr);15431rtw_camid_free(padapter, camid_clr);15432}1543315434goto enable_mc;15435}1543615437ctrl = BIT(15) | BIT(6) | ((pparm->algorithm) << 2) | pparm->keyid;1543815439RTW_PRINT("set group key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n"15440, cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm));1544115442write_cam(padapter, cam_id, ctrl, addr, pparm->key);1544315444/* if ((cam_id > 3) && (((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)))*/15445#ifdef CONFIG_CONCURRENT_MODE15446if (((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) || ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE)) {15447if (is_wep_enc(pparm->algorithm)) {15448padapter->securitypriv.dot11Def_camid[pparm->keyid] = cam_id;15449padapter->securitypriv.dot118021x_bmc_cam_id =15450padapter->securitypriv.dot11Def_camid[padapter->securitypriv.dot11PrivacyKeyIndex];15451RTW_PRINT("wep group key - force camid:%d\n", padapter->securitypriv.dot118021x_bmc_cam_id);15452} else {15453/*u8 org_cam_id = padapter->securitypriv.dot118021x_bmc_cam_id;*/1545415455/*force GK's cam id*/15456padapter->securitypriv.dot118021x_bmc_cam_id = cam_id;1545715458/* for GTK rekey15459if ((org_cam_id != INVALID_SEC_MAC_CAM_ID) &&15460(org_cam_id != cam_id)) {15461RTW_PRINT("clear group key for addr:"MAC_FMT", org_camid:%d new_camid:%d\n", MAC_ARG(addr), org_cam_id, cam_id);15462clear_cam_entry(padapter, org_cam_id);15463rtw_camid_free(padapter, org_cam_id);15464}*/15465}15466}15467#endif154681546915470#ifndef CONFIG_CONCURRENT_MODE15471if (cam_id >= 0 && cam_id <= 3)15472rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)_TRUE);15473#endif1547415475/* 8814au should set both broadcast and unicast CAM entry for WEP key in STA mode */15476if (is_wep_enc(pparm->algorithm) && check_mlmeinfo_state(pmlmeext, WIFI_FW_STATION_STATE) &&15477_rtw_camctl_chk_cap(padapter, SEC_CAP_CHK_BMC)) {15478struct set_stakey_parm sta_pparm;1547915480_rtw_memset(&sta_pparm, 0, sizeof(struct set_stakey_parm));15481sta_pparm.algorithm = pparm->algorithm;15482sta_pparm.keyid = pparm->keyid;15483_rtw_memcpy(sta_pparm.key, pparm->key, 16);15484_rtw_memcpy(sta_pparm.addr, get_bssid(&padapter->mlmepriv), ETH_ALEN);15485set_stakey_hdl(padapter, (u8 *)&sta_pparm);15486}1548715488enable_mc:15489/* allow multicast packets to driver */15490rtw_hal_set_hwreg(padapter, HW_VAR_ON_RCR_AM, null_addr);1549115492return H2C_SUCCESS;15493}1549415495void rtw_ap_wep_pk_setting(_adapter *adapter, struct sta_info *psta)15496{15497struct security_priv *psecuritypriv = &(adapter->securitypriv);15498struct set_stakey_parm sta_pparm;15499sint keyid;1550015501if (!is_wep_enc(psecuritypriv->dot11PrivacyAlgrthm))15502return;1550315504for (keyid = 0; keyid < 4; keyid++) {15505if ((psecuritypriv->key_mask & BIT(keyid)) && (keyid == psecuritypriv->dot11PrivacyKeyIndex)) {15506sta_pparm.algorithm = psecuritypriv->dot11PrivacyAlgrthm;15507sta_pparm.keyid = keyid;15508sta_pparm.gk = 0;15509_rtw_memcpy(sta_pparm.key, &(psecuritypriv->dot11DefKey[keyid].skey[0]), 16);15510_rtw_memcpy(sta_pparm.addr, psta->cmn.mac_addr, ETH_ALEN);1551115512RTW_PRINT(FUNC_ADPT_FMT"set WEP - PK with "MAC_FMT" keyid:%u\n"15513, FUNC_ADPT_ARG(adapter), MAC_ARG(psta->cmn.mac_addr), keyid);1551415515set_stakey_hdl(adapter, (u8 *)&sta_pparm);15516}15517}15518}1551915520u8 set_stakey_hdl(_adapter *padapter, u8 *pbuf)15521{15522u16 ctrl = 0;15523s16 cam_id = 0;15524bool used;15525u8 ret = H2C_SUCCESS;15526struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;15527struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);15528struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf;15529struct sta_priv *pstapriv = &padapter->stapriv;15530struct sta_info *psta;1553115532if (pparm->algorithm == _NO_PRIVACY_)15533goto write_to_cam;1553415535psta = rtw_get_stainfo(pstapriv, pparm->addr);15536if (!psta) {15537RTW_PRINT("%s sta:"MAC_FMT" not found\n", __func__, MAC_ARG(pparm->addr));15538ret = H2C_REJECTED;15539goto exit;15540}1554115542pmlmeinfo->enc_algo = pparm->algorithm;1554315544cam_id = rtw_camid_alloc(padapter, psta, pparm->keyid, pparm->gk, &used);15545if (cam_id < 0)15546goto exit;1554715548#ifdef CONFIG_LPS_PG15549if (adapter_to_pwrctl(padapter)->lps_level == LPS_PG)15550LPS_Leave(padapter, "SET_KEY");15551#endif1555215553/* cam entry searched is group key when setting pariwise key */15554if (!pparm->gk && used == _TRUE && rtw_camid_is_gk(padapter, cam_id) == _TRUE) {15555s16 camid_clr;1555615557RTW_PRINT(FUNC_ADPT_FMT" pairwise key with "MAC_FMT" id:%u the same key id as group key\n"15558, FUNC_ADPT_ARG(padapter), MAC_ARG(pparm->addr), pparm->keyid);1555915560/* HW has problem to distinguish this pairwise key with existing group key, stop HW enc and dec for BMC */15561rtw_camctl_set_flags(padapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH);15562rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, NULL);1556315564/* clear group key */15565while ((camid_clr = rtw_camid_search(padapter, pparm->addr, -1, 1)) >= 0) {15566RTW_PRINT("clear group key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), camid_clr);15567clear_cam_entry(padapter, camid_clr);15568rtw_camid_free(padapter, camid_clr);15569}15570}1557115572write_to_cam:15573if (pparm->algorithm == _NO_PRIVACY_) {15574while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1, -1)) >= 0) {15575RTW_PRINT("clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), cam_id);15576clear_cam_entry(padapter, cam_id);15577rtw_camid_free(padapter, cam_id);15578}15579} else {15580RTW_PRINT("set %s key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n"15581, pparm->gk ? "group" : "pairwise"15582, cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm));15583ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;15584if (pparm->gk)15585ctrl |= BIT(6);15586write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);15587}15588ret = H2C_SUCCESS_RSP;1558915590exit:15591return ret;15592}1559315594u8 add_ba_hdl(_adapter *padapter, unsigned char *pbuf)15595{15596struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf;15597struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;15598struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);1559915600struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);1560115602if (!psta)15603return H2C_SUCCESS;1560415605#ifdef CONFIG_80211N_HT15606if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||15607((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {15608/* pmlmeinfo->ADDBA_retry_count = 0; */15609/* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */15610/* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */15611issue_addba_req(padapter, pparm->addr, (u8)pparm->tid);15612_set_timer(&psta->addba_retry_timer, ADDBA_TO);15613}15614#ifdef CONFIG_TDLS15615else if ((psta->tdls_sta_state & TDLS_LINKED_STATE) &&15616(psta->htpriv.ht_option == _TRUE) &&15617(psta->htpriv.ampdu_enable == _TRUE)) {15618issue_addba_req(padapter, pparm->addr, (u8)pparm->tid);15619_set_timer(&psta->addba_retry_timer, ADDBA_TO);15620}15621#endif /* CONFIG */15622else15623psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);15624#endif /* CONFIG_80211N_HT */15625return H2C_SUCCESS;15626}156271562815629u8 add_ba_rsp_hdl(_adapter *padapter, unsigned char *pbuf)15630{15631struct addBaRsp_parm *pparm = (struct addBaRsp_parm *)pbuf;15632struct recv_reorder_ctrl *preorder_ctrl;15633struct sta_priv *pstapriv = &padapter->stapriv;15634struct sta_info *psta;15635u8 ret = _TRUE;1563615637psta = rtw_get_stainfo(pstapriv, pparm->addr);15638if (!psta)15639goto exit;1564015641preorder_ctrl = &psta->recvreorder_ctrl[pparm->tid];15642ret = issue_addba_rsp_wait_ack(padapter, pparm->addr, pparm->tid, pparm->status, pparm->size, 3, 50);1564315644#ifdef CONFIG_UPDATE_INDICATE_SEQ_WHILE_PROCESS_ADDBA_REQ15645/* status = 0 means accept this addba req, so update indicate seq = start_seq under this compile flag */15646if (pparm->status == 0) {15647preorder_ctrl->indicate_seq = pparm->start_seq;15648#ifdef DBG_RX_SEQ15649RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u SN_UPDATE indicate_seq:%d, start_seq:%d\n"15650, FUNC_ADPT_ARG(padapter), preorder_ctrl->tid, preorder_ctrl->indicate_seq, pparm->start_seq);15651#endif15652}15653#else15654rtw_set_bit(RTW_RECV_ACK_OR_TIMEOUT, &preorder_ctrl->rec_abba_rsp_ack);15655#ifdef DBG_RX_SEQ15656RTW_INFO("DBG_RX_SEQ "FUNC_ADPT_FMT" tid:%u SN_CLEAR indicate_seq:%d, start_seq:%d preorder_ctrl->rec_abba_rsp_ack =%lu \n"15657, FUNC_ADPT_ARG(padapter)15658, preorder_ctrl->tid15659, preorder_ctrl->indicate_seq15660, pparm->start_seq15661,preorder_ctrl->rec_abba_rsp_ack15662);15663#endif15664#endif1566515666/*15667* status = 0 means accept this addba req15668* status = 37 means reject this addba req15669*/15670if (pparm->status == 0) {15671preorder_ctrl->enable = _TRUE;15672preorder_ctrl->ampdu_size = pparm->size;15673} else if (pparm->status == 37)15674preorder_ctrl->enable = _FALSE;1567515676exit:15677return H2C_SUCCESS;15678}1567915680u8 chk_bmc_sleepq_cmd(_adapter *padapter)15681{15682struct cmd_obj *ph2c;15683struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);15684u8 res = _SUCCESS;156851568615687ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));15688if (ph2c == NULL) {15689res = _FAIL;15690goto exit;15691}1569215693init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));1569415695res = rtw_enqueue_cmd(pcmdpriv, ph2c);1569615697exit:156981569915700return res;15701}1570215703u8 set_tx_beacon_cmd(_adapter *padapter, u8 flags)15704{15705struct cmd_obj *ph2c;15706struct Tx_Beacon_param *ptxBeacon_parm;15707struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);15708struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;15709struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);15710struct submit_ctx sctx;15711u8 res = _SUCCESS;15712int len_diff = 0;1571315714/*prepare cmd parameter*/15715ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param));15716if (ptxBeacon_parm == NULL) {15717res = _FAIL;15718goto exit;15719}1572015721_rtw_memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));1572215723len_diff = update_hidden_ssid(15724ptxBeacon_parm->network.IEs + _BEACON_IE_OFFSET_15725, ptxBeacon_parm->network.IELength - _BEACON_IE_OFFSET_15726, pmlmeinfo->hidden_ssid_mode15727);15728ptxBeacon_parm->network.IELength += len_diff;157291573015731/* need enqueue, prepare cmd_obj and enqueue */15732ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));15733if (ph2c == NULL) {15734res = _FAIL;15735rtw_mfree((u8 *)ptxBeacon_parm, sizeof(*ptxBeacon_parm));15736goto exit;15737}1573815739init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));1574015741if (flags & RTW_CMDF_WAIT_ACK) {15742ph2c->sctx = &sctx;15743rtw_sctx_init(&sctx, 10 * 1000);15744}1574515746res = rtw_enqueue_cmd(pcmdpriv, ph2c);1574715748if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {15749rtw_sctx_wait(&sctx, __func__);15750_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);15751if (sctx.status == RTW_SCTX_SUBMITTED)15752ph2c->sctx = NULL;15753_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);15754}157551575615757exit:157581575915760return res;15761}157621576315764u8 mlme_evt_hdl(_adapter *padapter, unsigned char *pbuf)15765{15766u8 evt_code, evt_seq;15767u16 evt_sz;15768uint *peventbuf;15769void (*event_callback)(_adapter *dev, u8 *pbuf);15770struct evt_priv *pevt_priv = &(padapter->evtpriv);1577115772if (pbuf == NULL)15773goto _abort_event_;1577415775peventbuf = (uint *)pbuf;15776evt_sz = (u16)(*peventbuf & 0xffff);15777evt_seq = (u8)((*peventbuf >> 24) & 0x7f);15778evt_code = (u8)((*peventbuf >> 16) & 0xff);157791578015781#ifdef CHECK_EVENT_SEQ15782/* checking event sequence... */15783if (evt_seq != (ATOMIC_READ(&pevt_priv->event_seq) & 0x7f)) {1578415785pevt_priv->event_seq = (evt_seq + 1) & 0x7f;1578615787goto _abort_event_;15788}15789#endif1579015791/* checking if event code is valid */15792if (evt_code >= MAX_C2HEVT) {15793goto _abort_event_;15794}1579515796/* checking if event size match the event parm size */15797if ((wlanevents[evt_code].parmsize != 0) &&15798(wlanevents[evt_code].parmsize != evt_sz)) {1579915800goto _abort_event_;1580115802}1580315804ATOMIC_INC(&pevt_priv->event_seq);1580515806peventbuf += 2;1580715808if (peventbuf) {15809event_callback = wlanevents[evt_code].event_callback;15810event_callback(padapter, (u8 *)peventbuf);1581115812pevt_priv->evt_done_cnt++;15813}158141581515816_abort_event_:158171581815819return H2C_SUCCESS;1582015821}1582215823u8 h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)15824{15825if (!pbuf)15826return H2C_PARAMETERS_ERROR;1582715828return H2C_SUCCESS;15829}1583015831u8 chk_bmc_sleepq_hdl(_adapter *padapter, unsigned char *pbuf)15832{15833#ifdef CONFIG_AP_MODE15834_irqL irqL;15835struct sta_info *psta_bmc;15836_list *xmitframe_plist, *xmitframe_phead;15837struct xmit_frame *pxmitframe = NULL;15838struct xmit_priv *pxmitpriv = &padapter->xmitpriv;15839struct sta_priv *pstapriv = &padapter->stapriv;1584015841/* for BC/MC Frames */15842psta_bmc = rtw_get_bcmc_stainfo(padapter);15843if (!psta_bmc)15844return H2C_SUCCESS;1584515846if ((rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) && (psta_bmc->sleepq_len > 0)) {15847#ifndef CONFIG_PCI_HCI15848rtw_msleep_os(10);/* 10ms, ATIM(HIQ) Windows */15849#endif15850/* _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL); */15851_enter_critical_bh(&pxmitpriv->lock, &irqL);1585215853xmitframe_phead = get_list_head(&psta_bmc->sleep_q);15854xmitframe_plist = get_next(xmitframe_phead);1585515856while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {15857pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);1585815859xmitframe_plist = get_next(xmitframe_plist);1586015861rtw_list_delete(&pxmitframe->list);1586215863psta_bmc->sleepq_len--;15864if (psta_bmc->sleepq_len > 0)15865pxmitframe->attrib.mdata = 1;15866else15867pxmitframe->attrib.mdata = 0;1586815869pxmitframe->attrib.triggered = 1;1587015871if (xmitframe_hiq_filter(pxmitframe) == _TRUE)15872pxmitframe->attrib.qsel = QSLT_HIGH;/* HIQ */1587315874#if 015875_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);15876if (rtw_hal_xmit(padapter, pxmitframe) == _TRUE)15877rtw_os_xmit_complete(padapter, pxmitframe);15878_enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);15879#endif15880rtw_hal_xmitframe_enqueue(padapter, pxmitframe);15881}1588215883/* _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL); */15884_exit_critical_bh(&pxmitpriv->lock, &irqL);1588515886if (rtw_get_intf_type(padapter) != RTW_PCIE) {15887/* check hi queue and bmc_sleepq */15888rtw_chk_hi_queue_cmd(padapter);15889}15890}15891#endif1589215893return H2C_SUCCESS;15894}1589515896u8 tx_beacon_hdl(_adapter *padapter, unsigned char *pbuf)15897{15898/*RTW_INFO(FUNC_ADPT_FMT, FUNC_ADPT_ARG(padapter));*/15899#ifdef CONFIG_SWTIMER_BASED_TXBCN1590015901tx_beacon_handlder(padapter->dvobj);1590215903#else1590415905if (send_beacon(padapter) == _FAIL) {15906RTW_INFO("issue_beacon, fail!\n");15907return H2C_PARAMETERS_ERROR;15908}1590915910/* tx bc/mc frames after update TIM */15911chk_bmc_sleepq_hdl(padapter, NULL);15912#endif1591315914return H2C_SUCCESS;15915}1591615917/*15918* according to channel15919* add/remove WLAN_BSSID_EX.IEs's ERP ie15920* set WLAN_BSSID_EX.SupportedRates15921* update WLAN_BSSID_EX.IEs's Supported Rate and Extended Supported Rate ie15922*/15923void change_band_update_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 ch)15924{15925u8 network_type, rate_len, total_rate_len, remainder_rate_len;15926struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);15927struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);15928u8 erpinfo = 0x4;1592915930if (ch >= 36) {15931network_type = WIRELESS_11A;15932total_rate_len = IEEE80211_NUM_OFDM_RATESLEN;15933rtw_remove_bcn_ie(padapter, pnetwork, _ERPINFO_IE_);15934#ifdef CONFIG_80211AC_VHT15935/* if channel in 5G band, then add vht ie . */15936if ((pmlmepriv->htpriv.ht_option == _TRUE)15937&& REGSTY_IS_11AC_ENABLE(&padapter->registrypriv)15938&& is_supported_vht(padapter->registrypriv.wireless_mode)15939&& (!rfctl->country_ent || COUNTRY_CHPLAN_EN_11AC(rfctl->country_ent))15940) {15941if (REGSTY_IS_11AC_AUTO(&padapter->registrypriv)15942|| pmlmepriv->ori_vht_en)15943rtw_vht_ies_attach(padapter, pnetwork);15944}15945#endif15946} else {15947network_type = 0;15948total_rate_len = 0;15949if (padapter->registrypriv.wireless_mode & WIRELESS_11B) {15950network_type |= WIRELESS_11B;15951total_rate_len += IEEE80211_CCK_RATE_LEN;15952}15953if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {15954network_type |= WIRELESS_11G;15955total_rate_len += IEEE80211_NUM_OFDM_RATESLEN;15956}15957rtw_add_bcn_ie(padapter, pnetwork, _ERPINFO_IE_, &erpinfo, 1);15958#ifdef CONFIG_80211AC_VHT15959rtw_vht_ies_detach(padapter, pnetwork);15960#endif15961}1596215963rtw_set_supported_rate(pnetwork->SupportedRates, network_type);1596415965UpdateBrateTbl(padapter, pnetwork->SupportedRates);1596615967if (total_rate_len > 8) {15968rate_len = 8;15969remainder_rate_len = total_rate_len - 8;15970} else {15971rate_len = total_rate_len;15972remainder_rate_len = 0;15973}1597415975rtw_add_bcn_ie(padapter, pnetwork, _SUPPORTEDRATES_IE_, pnetwork->SupportedRates, rate_len);1597615977if (remainder_rate_len)15978rtw_add_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_, (pnetwork->SupportedRates + 8), remainder_rate_len);15979else15980rtw_remove_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_);1598115982pnetwork->Length = get_WLAN_BSSID_EX_sz(pnetwork);15983}1598415985void rtw_join_done_chk_ch(_adapter *adapter, int join_res)15986{15987#define DUMP_ADAPTERS_STATUS 01598815989struct dvobj_priv *dvobj;15990_adapter *iface;15991struct mlme_priv *mlme;15992struct mlme_ext_priv *mlmeext;15993u8 u_ch, u_offset, u_bw;15994int i;1599515996dvobj = adapter_to_dvobj(adapter);1599715998if (DUMP_ADAPTERS_STATUS) {15999RTW_INFO(FUNC_ADPT_FMT" enter\n", FUNC_ADPT_ARG(adapter));16000dump_adapters_status(RTW_DBGDUMP , dvobj);16001}1600216003if (join_res >= 0) {1600416005#ifdef CONFIG_MCC_MODE16006/* MCC setting success, don't go to ch union process */16007if (rtw_hal_set_mcc_setting_join_done_chk_ch(adapter))16008return;16009#endif /* CONFIG_MCC_MODE */1601016011if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset) <= 0) {16012dump_adapters_status(RTW_DBGDUMP , dvobj);16013rtw_warn_on(1);16014}1601516016for (i = 0; i < dvobj->iface_nums; i++) {16017iface = dvobj->padapters[i];16018mlme = &iface->mlmepriv;16019mlmeext = &iface->mlmeextpriv;1602016021if (!iface || iface == adapter)16022continue;1602316024if ((MLME_IS_AP(iface) || MLME_IS_MESH(iface))16025&& check_fwstate(mlme, WIFI_ASOC_STATE)16026) {16027u8 ori_ch, ori_bw, ori_offset;16028bool is_grouped = rtw_is_chbw_grouped(u_ch, u_bw, u_offset16029, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset);1603016031if (is_grouped == _FALSE) {16032/* handle AP which need to switch ch setting */1603316034ori_ch = mlmeext->cur_channel;16035ori_bw = mlmeext->cur_bwmode;16036ori_offset = mlmeext->cur_ch_offset;1603716038/* restore original bw, adjust bw by registry setting on target ch */16039mlmeext->cur_bwmode = mlme->ori_bw;16040mlmeext->cur_channel = u_ch;16041rtw_adjust_chbw(iface, mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset);16042#ifdef CONFIG_RTW_MESH16043if (MLME_IS_MESH(iface))16044rtw_mesh_adjust_chbw(mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset);16045#endif1604616047rtw_chset_sync_chbw(adapter_to_chset(adapter)16048, &mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset16049, &u_ch, &u_bw, &u_offset);1605016051RTW_INFO(FUNC_ADPT_FMT" %u,%u,%u => %u,%u,%u\n", FUNC_ADPT_ARG(iface)16052, ori_ch, ori_bw, ori_offset16053, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset);1605416055rtw_ap_update_bss_chbw(iface, &(mlmeext->mlmext_info.network)16056, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset);1605716058_rtw_memcpy(&(mlme->cur_network.network), &(mlmeext->mlmext_info.network), sizeof(WLAN_BSSID_EX));1605916060rtw_start_bss_hdl_after_chbw_decided(iface);1606116062{16063#if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))16064u8 ht_option = 0;1606516066#ifdef CONFIG_80211N_HT16067ht_option = mlme->htpriv.ht_option;16068#endif1606916070rtw_cfg80211_ch_switch_notify(iface16071, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset16072, ht_option16073, 0);16074#endif16075}16076}1607716078clr_fwstate(mlme, WIFI_OP_CH_SWITCHING);16079update_beacon(iface, 0xFF, NULL, _TRUE, 0);16080}16081}1608216083#ifdef CONFIG_DFS_MASTER16084rtw_dfs_rd_en_decision(adapter, MLME_STA_CONNECTED, 0);16085#endif16086} else {16087for (i = 0; i < dvobj->iface_nums; i++) {16088iface = dvobj->padapters[i];16089mlme = &iface->mlmepriv;16090mlmeext = &iface->mlmeextpriv;1609116092if (!iface || iface == adapter)16093continue;1609416095if ((MLME_IS_AP(iface) || MLME_IS_MESH(iface))16096&& check_fwstate(mlme, WIFI_ASOC_STATE)16097) {16098clr_fwstate(mlme, WIFI_OP_CH_SWITCHING);16099update_beacon(iface, 0xFF, NULL, _TRUE, 0);16100}16101}16102#ifdef CONFIG_DFS_MASTER16103rtw_dfs_rd_en_decision(adapter, MLME_STA_DISCONNECTED, 0);16104#endif16105}1610616107if (rtw_mi_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset)) {16108RTW_INFO(FUNC_ADPT_FMT" union:%u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);16109set_channel_bwmode(adapter, u_ch, u_offset, u_bw);16110rtw_mi_update_union_chan_inf(adapter, u_ch, u_offset, u_bw);16111}1611216113if (DUMP_ADAPTERS_STATUS) {16114RTW_INFO(FUNC_ADPT_FMT" exit\n", FUNC_ADPT_ARG(adapter));16115dump_adapters_status(RTW_DBGDUMP , dvobj);16116}16117}1611816119int rtw_chk_start_clnt_join(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset)16120{16121#ifdef CONFIG_CONCURRENT_MODE16122bool chbw_allow = _TRUE;16123#endif16124bool connect_allow = _TRUE;16125struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;16126u8 cur_ch, cur_bw, cur_ch_offset;16127u8 u_ch, u_offset, u_bw;1612816129u_ch = cur_ch = pmlmeext->cur_channel;16130u_bw = cur_bw = pmlmeext->cur_bwmode;16131u_offset = cur_ch_offset = pmlmeext->cur_ch_offset;1613216133if (!ch || !bw || !offset) {16134connect_allow = _FALSE;16135rtw_warn_on(1);16136goto exit;16137}1613816139if (cur_ch == 0) {16140connect_allow = _FALSE;16141RTW_ERR(FUNC_ADPT_FMT" cur_ch:%u\n"16142, FUNC_ADPT_ARG(adapter), cur_ch);16143rtw_warn_on(1);16144goto exit;16145}16146RTW_INFO(FUNC_ADPT_FMT" req: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);1614716148#ifdef CONFIG_CONCURRENT_MODE16149{16150struct dvobj_priv *dvobj;16151_adapter *iface;16152struct mlme_priv *mlme;16153struct mlme_ext_priv *mlmeext;16154struct mi_state mstate;16155int i;1615616157dvobj = adapter_to_dvobj(adapter);1615816159rtw_mi_status_no_self(adapter, &mstate);16160RTW_INFO(FUNC_ADPT_FMT" others ld_sta_num:%u, ap_num:%u, mesh_num:%u\n"16161, FUNC_ADPT_ARG(adapter), MSTATE_STA_LD_NUM(&mstate)16162, MSTATE_AP_NUM(&mstate), MSTATE_MESH_NUM(&mstate));1616316164if (!MSTATE_STA_LD_NUM(&mstate) && !MSTATE_AP_NUM(&mstate) && !MSTATE_MESH_NUM(&mstate)) {16165/* consider linking STA? */16166goto connect_allow_hdl;16167}1616816169if (rtw_mi_get_ch_setting_union_no_self(adapter, &u_ch, &u_bw, &u_offset) <= 0) {16170dump_adapters_status(RTW_DBGDUMP , dvobj);16171rtw_warn_on(1);16172}16173RTW_INFO(FUNC_ADPT_FMT" others union:%u,%u,%u\n"16174, FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);1617516176/* chbw_allow? */16177chbw_allow = rtw_is_chbw_grouped(pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset16178, u_ch, u_bw, u_offset);1617916180RTW_INFO(FUNC_ADPT_FMT" chbw_allow:%d\n"16181, FUNC_ADPT_ARG(adapter), chbw_allow);1618216183#ifdef CONFIG_MCC_MODE16184/* check setting success, don't go to ch union process */16185if (rtw_hal_set_mcc_setting_chk_start_clnt_join(adapter, &u_ch, &u_bw, &u_offset, chbw_allow))16186goto exit;16187#endif1618816189if (chbw_allow == _TRUE) {16190rtw_sync_chbw(&cur_ch, &cur_bw, &cur_ch_offset, &u_ch, &u_bw, &u_offset);16191rtw_warn_on(cur_ch != pmlmeext->cur_channel);16192rtw_warn_on(cur_bw != pmlmeext->cur_bwmode);16193rtw_warn_on(cur_ch_offset != pmlmeext->cur_ch_offset);16194goto connect_allow_hdl;16195}1619616197#ifdef CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT16198/* chbw_allow is _FALSE, connect allow? */16199for (i = 0; i < dvobj->iface_nums; i++) {16200iface = dvobj->padapters[i];16201mlme = &iface->mlmepriv;16202mlmeext = &iface->mlmeextpriv;1620316204if (check_fwstate(mlme, WIFI_STATION_STATE)16205&& check_fwstate(mlme, WIFI_ASOC_STATE)16206#if defined(CONFIG_P2P)16207&& rtw_p2p_chk_state(&(iface->wdinfo), P2P_STATE_NONE)16208#endif16209) {16210connect_allow = _FALSE;16211break;16212}16213}16214#endif /* CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT */1621516216if (MSTATE_STA_LD_NUM(&mstate) + MSTATE_AP_LD_NUM(&mstate) + MSTATE_MESH_LD_NUM(&mstate) >= 4)16217connect_allow = _FALSE;1621816219RTW_INFO(FUNC_ADPT_FMT" connect_allow:%d\n"16220, FUNC_ADPT_ARG(adapter), connect_allow);1622116222if (connect_allow == _FALSE)16223goto exit;1622416225connect_allow_hdl:16226/* connect_allow == _TRUE */1622716228if (chbw_allow == _FALSE) {16229u_ch = cur_ch;16230u_bw = cur_bw;16231u_offset = cur_ch_offset;1623216233for (i = 0; i < dvobj->iface_nums; i++) {16234iface = dvobj->padapters[i];16235mlme = &iface->mlmepriv;16236mlmeext = &iface->mlmeextpriv;1623716238if (!iface || iface == adapter)16239continue;1624016241if ((MLME_IS_AP(iface) || MLME_IS_MESH(iface))16242&& check_fwstate(mlme, WIFI_ASOC_STATE)16243) {16244#ifdef CONFIG_SPCT_CH_SWITCH16245if (1)16246rtw_ap_inform_ch_switch(iface, pmlmeext->cur_channel , pmlmeext->cur_ch_offset);16247else16248#endif16249rtw_sta_flush(iface, _FALSE);1625016251rtw_hal_set_hwreg(iface, HW_VAR_CHECK_TXBUF, 0);16252set_fwstate(mlme, WIFI_OP_CH_SWITCHING);1625316254} else if (check_fwstate(mlme, WIFI_STATION_STATE)16255&& check_fwstate(mlme, WIFI_ASOC_STATE)16256) {16257rtw_disassoc_cmd(iface, 500, RTW_CMDF_DIRECTLY);16258rtw_indicate_disconnect(iface, 0, _FALSE);16259rtw_free_assoc_resources(iface, _TRUE);16260}16261}16262}1626316264#ifdef CONFIG_DFS_MASTER16265rtw_dfs_rd_en_decision(adapter, MLME_STA_CONNECTING, 0);16266#endif16267}16268#endif /* CONFIG_CONCURRENT_MODE */1626916270exit:1627116272if (connect_allow == _TRUE) {16273RTW_INFO(FUNC_ADPT_FMT" union: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);16274*ch = u_ch;16275*bw = u_bw;16276*offset = u_offset;1627716278#if defined(CONFIG_IOCTL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))16279{16280u8 ht_option = 0;1628116282#ifdef CONFIG_80211N_HT16283ht_option = adapter->mlmepriv.htpriv.ht_option;16284#endif /* CONFIG_80211N_HT */1628516286/*16287when supplicant send the mlme frame,16288the bss freq is updated by channel switch event.16289*/16290rtw_cfg80211_ch_switch_notify(adapter,16291cur_ch, cur_bw, cur_ch_offset, ht_option, 1);16292}16293#endif16294}1629516296return connect_allow == _TRUE ? _SUCCESS : _FAIL;16297}1629816299void rtw_set_external_auth_status(_adapter *padapter,16300const void *data, int len)16301{16302#ifdef CONFIG_IOCTL_CFG8021116303struct net_device *dev = padapter->pnetdev;16304struct wiphy *wiphy = adapter_to_wiphy(padapter);16305struct rtw_external_auth_params params;1630616307/* convert data to external_auth_params */16308params.action = RTW_GET_BE32((u8 *)data);16309_rtw_memcpy(¶ms.bssid, (u8 *)data + 4, ETH_ALEN);16310_rtw_memcpy(¶ms.ssid.ssid, (u8 *)data + 10, WLAN_SSID_MAXLEN);16311params.ssid.ssid_len = RTW_GET_BE64((u8 *)data + 42);16312params.key_mgmt_suite = RTW_GET_BE32((u8 *)data + 58);16313params.status = RTW_GET_BE16((u8 *)data + 62);16314_rtw_memcpy(¶ms.pmkid, (u8 *)data + 64, PMKID_LEN);1631516316rtw_cfg80211_external_auth_status(wiphy, dev, ¶ms);16317#endif /* CONFIG_IOCTL_CFG80211 */16318}1631916320u8 rtw_set_chbw_hdl(_adapter *padapter, u8 *pbuf)16321{16322struct set_ch_parm *set_ch_parm;16323struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;1632416325if (!pbuf)16326return H2C_PARAMETERS_ERROR;1632716328set_ch_parm = (struct set_ch_parm *)pbuf;1632916330RTW_INFO(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",16331FUNC_NDEV_ARG(padapter->pnetdev),16332set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);1633316334pmlmeext->cur_channel = set_ch_parm->ch;16335pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;16336pmlmeext->cur_bwmode = set_ch_parm->bw;1633716338set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);1633916340return H2C_SUCCESS;16341}1634216343u8 set_chplan_hdl(_adapter *padapter, unsigned char *pbuf)16344{16345struct SetChannelPlan_param *setChannelPlan_param;16346struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);1634716348if (!pbuf)16349return H2C_PARAMETERS_ERROR;1635016351setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;1635216353if (!rtw_is_channel_plan_valid(setChannelPlan_param->channel_plan))16354return H2C_PARAMETERS_ERROR;1635516356rfctl->country_ent = setChannelPlan_param->country_ent;16357rfctl->ChannelPlan = setChannelPlan_param->channel_plan;1635816359rfctl->max_chan_nums = init_channel_set(padapter, rfctl->ChannelPlan, rfctl->channel_set);16360init_channel_list(padapter, rfctl->channel_set, &rfctl->channel_list);16361#if CONFIG_TXPWR_LIMIT16362rtw_txpwr_init_regd(rfctl);16363#endif1636416365rtw_hal_set_odm_var(padapter, HAL_ODM_REGULATION, NULL, _TRUE);1636616367#ifdef CONFIG_IOCTL_CFG8021116368rtw_regd_apply_flags(adapter_to_wiphy(padapter));16369#endif1637016371return H2C_SUCCESS;16372}1637316374u8 led_blink_hdl(_adapter *padapter, unsigned char *pbuf)16375{16376struct LedBlink_param *ledBlink_param;1637716378if (!pbuf)16379return H2C_PARAMETERS_ERROR;1638016381ledBlink_param = (struct LedBlink_param *)pbuf;1638216383#ifdef CONFIG_RTW_LED_HANDLED_BY_CMD_THREAD16384BlinkHandler((PLED_DATA)ledBlink_param->pLed);16385#endif1638616387return H2C_SUCCESS;16388}1638916390u8 set_csa_hdl(_adapter *adapter, unsigned char *pbuf)16391{16392#ifdef CONFIG_DFS16393struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);1639416395if (rfctl->csa_ch)16396rtw_dfs_ch_switch_hdl(adapter_to_dvobj(adapter));16397#endif16398return H2C_SUCCESS;16399}1640016401u8 tdls_hdl(_adapter *padapter, unsigned char *pbuf)16402{16403#ifdef CONFIG_TDLS16404_irqL irqL;16405HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);16406struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;16407#ifdef CONFIG_TDLS_CH_SW16408struct tdls_ch_switch *pchsw_info = &ptdlsinfo->chsw_info;16409#endif16410struct TDLSoption_param *TDLSoption;16411struct sta_info *ptdls_sta = NULL;16412struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;16413struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;16414struct sta_info *ap_sta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(&(pmlmeinfo->network)));16415u8 survey_channel, i, min, option;16416struct tdls_txmgmt txmgmt;16417u32 setchtime, resp_sleep = 0, wait_time;16418u8 zaddr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};16419u8 ret;16420u8 doiqk;16421u64 tx_ra_bitmap = 0;1642216423if (!pbuf)16424return H2C_PARAMETERS_ERROR;1642516426TDLSoption = (struct TDLSoption_param *)pbuf;16427option = TDLSoption->option;1642816429if (!_rtw_memcmp(TDLSoption->addr, zaddr, ETH_ALEN)) {16430ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), TDLSoption->addr);16431if (ptdls_sta == NULL)16432return H2C_REJECTED;16433} else {16434if (!(option == TDLS_RS_RCR))16435return H2C_REJECTED;16436}1643716438/* _enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL); */16439/* RTW_INFO("[%s] option:%d\n", __FUNCTION__, option); */1644016441switch (option) {16442case TDLS_ESTABLISHED: {16443/* As long as TDLS handshake success, we should set RCR_CBSSID_DATA bit to 0 */16444/* So we can receive all kinds of data frames. */16445u8 sta_band = 0;1644616447/* leave ALL PS when TDLS is established */16448rtw_pwr_wakeup(padapter);1644916450rtw_hal_rcr_set_chk_bssid(padapter, MLME_TDLS_LINKED);16451RTW_INFO("Created Direct Link with "MAC_FMT"\n", MAC_ARG(ptdls_sta->cmn.mac_addr));1645216453/* Set TDLS sta rate. */16454/* Update station supportRate */16455rtw_hal_update_sta_ra_info(padapter, ptdls_sta);16456tx_ra_bitmap = ptdls_sta->cmn.ra_info.ramask;1645716458if (pmlmeext->cur_channel > 14) {16459if (tx_ra_bitmap & 0xffff000)16460sta_band |= WIRELESS_11_5N ;1646116462if (tx_ra_bitmap & 0xff0)16463sta_band |= WIRELESS_11A;1646416465/* 5G band */16466#ifdef CONFIG_80211AC_VHT16467if (ptdls_sta->vhtpriv.vht_option)16468sta_band = WIRELESS_11_5AC;16469#endif1647016471} else {16472if (tx_ra_bitmap & 0xffff000)16473sta_band |= WIRELESS_11_24N;1647416475if (tx_ra_bitmap & 0xff0)16476sta_band |= WIRELESS_11G;1647716478if (tx_ra_bitmap & 0x0f)16479sta_band |= WIRELESS_11B;16480}16481ptdls_sta->wireless_mode = sta_band;16482rtw_hal_update_sta_wset(padapter, ptdls_sta);16483/* Sta mode */16484rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, ptdls_sta, _TRUE);1648516486set_sta_rate(padapter, ptdls_sta);16487rtw_sta_media_status_rpt(padapter, ptdls_sta, 1);16488break;16489}16490case TDLS_ISSUE_PTI:16491ptdls_sta->tdls_sta_state |= TDLS_WAIT_PTR_STATE;16492issue_tdls_peer_traffic_indication(padapter, ptdls_sta);16493_set_timer(&ptdls_sta->pti_timer, TDLS_PTI_TIME);16494break;16495#ifdef CONFIG_TDLS_CH_SW16496case TDLS_CH_SW_RESP:16497_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));16498txmgmt.status_code = 0;16499_rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN);1650016501if (ap_sta)16502rtw_hal_macid_sleep(padapter, ap_sta->cmn.mac_id);16503issue_nulldata(padapter, NULL, 1, 3, 3);1650416505RTW_INFO("[TDLS ] issue tdls channel switch response\n");16506ret = issue_tdls_ch_switch_rsp(padapter, &txmgmt, _TRUE);1650716508/* If we receive TDLS_CH_SW_REQ at off channel which it's target is AP's channel */16509/* then we just switch to AP's channel*/16510if (padapter->mlmeextpriv.cur_channel == pchsw_info->off_ch_num) {16511rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_END_TO_BASE_CHNL);16512break;16513}1651416515if (ret == _SUCCESS)16516rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_OFF_CHNL);16517else16518RTW_INFO("[TDLS] issue_tdls_ch_switch_rsp wait ack fail !!!!!!!!!!\n");1651916520break;16521case TDLS_CH_SW_PREPARE:16522pchsw_info->ch_sw_state |= TDLS_CH_SWITCH_PREPARE_STATE;1652316524/* to collect IQK info of off-chnl */16525doiqk = _TRUE;16526rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, &doiqk);16527set_channel_bwmode(padapter, pchsw_info->off_ch_num, pchsw_info->ch_offset, (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20);16528doiqk = _FALSE;16529rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, &doiqk);1653016531/* switch back to base-chnl */16532set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);1653316534rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_START);1653516536pchsw_info->ch_sw_state &= ~(TDLS_CH_SWITCH_PREPARE_STATE);1653716538break;16539case TDLS_CH_SW_START:16540rtw_tdls_set_ch_sw_oper_control(padapter, _TRUE);16541break;16542case TDLS_CH_SW_TO_OFF_CHNL:16543if (ap_sta)16544rtw_hal_macid_sleep(padapter, ap_sta->cmn.mac_id);16545issue_nulldata(padapter, NULL, 1, 3, 3);1654616547if (padapter->registrypriv.wifi_spec == 0) {16548if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE))16549_set_timer(&ptdls_sta->ch_sw_timer, (u32)(ptdls_sta->ch_switch_timeout) / 1000);16550}1655116552if (rtw_tdls_do_ch_sw(padapter, ptdls_sta, TDLS_CH_SW_OFF_CHNL, pchsw_info->off_ch_num,16553pchsw_info->ch_offset, (pchsw_info->ch_offset) ? CHANNEL_WIDTH_40 : CHANNEL_WIDTH_20, ptdls_sta->ch_switch_time) == _SUCCESS) {16554pchsw_info->ch_sw_state &= ~(TDLS_PEER_AT_OFF_STATE);16555if (pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE) {16556if (issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta->cmn.mac_addr, 0, 1,16557(padapter->registrypriv.wifi_spec == 0) ? 3 : 0) == _FAIL)16558rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_BASE_CHNL);16559}16560} else {16561if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE))16562_cancel_timer_ex(&ptdls_sta->ch_sw_timer);16563}165641656516566break;16567case TDLS_CH_SW_END:16568case TDLS_CH_SW_END_TO_BASE_CHNL:16569rtw_tdls_set_ch_sw_oper_control(padapter, _FALSE);16570_cancel_timer_ex(&ptdls_sta->ch_sw_timer);16571_cancel_timer_ex(&ptdls_sta->stay_on_base_chnl_timer);16572_cancel_timer_ex(&ptdls_sta->ch_sw_monitor_timer);16573#if 016574_rtw_memset(pHalData->tdls_ch_sw_iqk_info_base_chnl, 0x00, sizeof(pHalData->tdls_ch_sw_iqk_info_base_chnl));16575_rtw_memset(pHalData->tdls_ch_sw_iqk_info_off_chnl, 0x00, sizeof(pHalData->tdls_ch_sw_iqk_info_off_chnl));16576#endif1657716578if (option == TDLS_CH_SW_END_TO_BASE_CHNL)16579rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_CH_SW_TO_BASE_CHNL);1658016581break;16582case TDLS_CH_SW_TO_BASE_CHNL_UNSOLICITED:16583case TDLS_CH_SW_TO_BASE_CHNL:16584pchsw_info->ch_sw_state &= ~(TDLS_PEER_AT_OFF_STATE | TDLS_WAIT_CH_RSP_STATE);1658516586if (option == TDLS_CH_SW_TO_BASE_CHNL_UNSOLICITED) {16587if (ptdls_sta != NULL) {16588/* Send unsolicited channel switch rsp. to peer */16589_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));16590txmgmt.status_code = 0;16591_rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN);16592issue_tdls_ch_switch_rsp(padapter, &txmgmt, _FALSE);16593}16594}1659516596if (rtw_tdls_do_ch_sw(padapter, ptdls_sta, TDLS_CH_SW_BASE_CHNL, pmlmeext->cur_channel,16597pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode, ptdls_sta->ch_switch_time) == _SUCCESS) {16598if (ap_sta)16599rtw_hal_macid_wakeup(padapter, ap_sta->cmn.mac_id);16600issue_nulldata(padapter, NULL, 0, 3, 3);16601/* set ch sw monitor timer for responder */16602if (!(pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE))16603_set_timer(&ptdls_sta->ch_sw_monitor_timer, TDLS_CH_SW_MONITOR_TIMEOUT);16604}1660516606break;16607#endif16608case TDLS_RS_RCR:16609rtw_hal_rcr_set_chk_bssid(padapter, MLME_TDLS_NOLINK);16610break;16611case TDLS_TEARDOWN_STA:16612case TDLS_TEARDOWN_STA_NO_WAIT:16613_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));16614txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;16615_rtw_memcpy(txmgmt.peer, ptdls_sta->cmn.mac_addr, ETH_ALEN);1661616617issue_tdls_teardown(padapter, &txmgmt, (option == TDLS_TEARDOWN_STA) ? _TRUE : _FALSE);1661816619break;16620case TDLS_TEARDOWN_STA_LOCALLY:16621case TDLS_TEARDOWN_STA_LOCALLY_POST:16622#ifdef CONFIG_TDLS_CH_SW16623if (_rtw_memcmp(TDLSoption->addr, pchsw_info->addr, ETH_ALEN) == _TRUE) {16624pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE |16625TDLS_CH_SWITCH_ON_STATE |16626TDLS_PEER_AT_OFF_STATE);16627rtw_tdls_set_ch_sw_oper_control(padapter, _FALSE);16628_rtw_memset(pchsw_info->addr, 0x00, ETH_ALEN);16629}16630#endif1663116632if (option == TDLS_TEARDOWN_STA_LOCALLY)16633rtw_tdls_teardown_pre_hdl(padapter, ptdls_sta);1663416635rtw_tdls_teardown_post_hdl(padapter, ptdls_sta, _FALSE);1663616637if (ptdlsinfo->tdls_sctx != NULL)16638rtw_sctx_done(&(ptdlsinfo->tdls_sctx));1663916640break;16641}1664216643/* _exit_critical_bh(&(ptdlsinfo->hdl_lock), &irqL); */1664416645return H2C_SUCCESS;16646#else16647return H2C_REJECTED;16648#endif /* CONFIG_TDLS */1664916650}1665116652u8 run_in_thread_hdl(_adapter *padapter, u8 *pbuf)16653{16654struct RunInThread_param *p;166551665616657if (NULL == pbuf)16658return H2C_PARAMETERS_ERROR;16659p = (struct RunInThread_param *)pbuf;1666016661if (p->func)16662p->func(p->context);1666316664return H2C_SUCCESS;16665}1666616667u8 rtw_getmacreg_hdl(_adapter *padapter, u8 *pbuf)16668{1666916670struct readMAC_parm *preadmacparm = NULL;16671u8 sz = 0;16672u32 addr = 0;16673u32 value = 0;1667416675if (!pbuf)16676return H2C_PARAMETERS_ERROR;1667716678preadmacparm = (struct readMAC_parm *) pbuf;16679sz = preadmacparm->len;16680addr = preadmacparm->addr;16681value = 0;1668216683switch (sz) {16684case 1:16685value = rtw_read8(padapter, addr);16686break;16687case 2:16688value = rtw_read16(padapter, addr);16689break;16690case 4:16691value = rtw_read32(padapter, addr);16692break;16693default:16694RTW_INFO("%s: Unknown size\n", __func__);16695break;16696}16697RTW_INFO("%s: addr:0x%02x valeu:0x%02x\n", __func__, addr, value);1669816699return H2C_SUCCESS;16700}1670116702int rtw_sae_preprocess(_adapter *adapter, const u8 *buf, u32 len, u8 tx)16703{16704#ifdef CONFIG_IOCTL_CFG8021116705const u8 *frame_body = buf + sizeof(struct rtw_ieee80211_hdr_3addr);16706u16 alg;16707u16 seq;16708u16 status;16709int ret = _FAIL;1671016711alg = RTW_GET_LE16(frame_body);16712if (alg != WLAN_AUTH_SAE)16713goto exit;1671416715seq = RTW_GET_LE16(frame_body + 2);16716status = RTW_GET_LE16(frame_body + 4);1671716718RTW_INFO("RTW_%s:AUTH alg:0x%04x, seq:0x%04x, status:0x%04x, mesg:%s\n",16719(tx == _TRUE) ? "Tx" : "Rx", alg, seq, status,16720(seq == 1) ? "Commit" : "Confirm");1672116722ret = _SUCCESS;1672316724#ifdef CONFIG_RTW_MESH16725if (MLME_IS_MESH(adapter)) {16726rtw_mesh_sae_check_frames(adapter, buf, len, tx, alg, seq, status);16727goto exit;16728}16729#endif1673016731if (tx && (seq == 2) && (status == 0)) {16732/* quere commit frame until external auth statue update */16733struct sta_priv *pstapriv = &adapter->stapriv;16734struct sta_info *psta = NULL;16735_irqL irqL;1673616737psta = rtw_get_stainfo(pstapriv, GetAddr1Ptr(buf));16738if (psta) {16739_enter_critical_bh(&psta->lock, &irqL);16740if (psta->pauth_frame) {16741rtw_mfree(psta->pauth_frame, psta->auth_len);16742psta->pauth_frame = NULL;16743psta->auth_len = 0;16744}1674516746psta->pauth_frame = rtw_zmalloc(len);16747if (psta->pauth_frame) {16748_rtw_memcpy(psta->pauth_frame, buf, len);16749psta->auth_len = len;16750}16751_exit_critical_bh(&psta->lock, &irqL);1675216753ret = 2;16754}16755}16756exit:16757return ret;16758#else16759return _SUCCESS;16760#endif /* CONFIG_IOCTL_CFG80211 */16761}16762167631676416765