linux/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7#include <drv_types.h>
   8#include <rtw_debug.h>
   9#include <rtw_wifi_regd.h>
  10#include <hal_btcoex.h>
  11#include <linux/kernel.h>
  12#include <asm/unaligned.h>
  13
  14static struct mlme_handler mlme_sta_tbl[] = {
  15        {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
  16        {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
  17        {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
  18        {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
  19        {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
  20        {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
  21
  22        /*----------------------------------------------------------
  23                                        below 2 are reserved
  24        -----------------------------------------------------------*/
  25        {0,                                     "DoReserved",           &DoReserved},
  26        {0,                                     "DoReserved",           &DoReserved},
  27        {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
  28        {WIFI_ATIM,                     "OnATIM",               &OnAtim},
  29        {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
  30        {WIFI_AUTH,                     "OnAuth",               &OnAuthClient},
  31        {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
  32        {WIFI_ACTION,           "OnAction",             &OnAction},
  33        {WIFI_ACTION_NOACK, "OnActionNoAck",    &OnAction},
  34};
  35
  36static struct action_handler OnAction_tbl[] = {
  37        {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,        "ACTION_SPECTRUM_MGMT", on_action_spct},
  38        {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &DoReserved},
  39        {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &DoReserved},
  40        {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
  41        {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
  42        {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
  43        {RTW_WLAN_CATEGORY_FT, "ACTION_FT",     &DoReserved},
  44        {RTW_WLAN_CATEGORY_HT,  "ACTION_HT",    &OnAction_ht},
  45        {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},
  46        {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved},
  47        {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved},
  48        {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &DoReserved},
  49        {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved},
  50};
  51
  52static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
  53
  54/**************************************************
  55OUI definitions for the vendor specific IE
  56***************************************************/
  57unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
  58unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
  59unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
  60unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
  61unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
  62
  63unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
  64unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
  65
  66static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
  67
  68/********************************************************
  69ChannelPlan definitions
  70*********************************************************/
  71static struct rt_channel_plan_2g        RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
  72        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x00, RT_CHANNEL_DOMAIN_2G_WORLD , Passive scan CH 12, 13 */
  73        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
  74        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},                      /*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
  75        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
  76        {{10, 11, 12, 13}, 4},                                          /*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
  77        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x05, RT_CHANNEL_DOMAIN_2G_GLOBAL , Passive scan CH 12, 13, 14 */
  78        {{}, 0},                                                                /*  0x06, RT_CHANNEL_DOMAIN_2G_NULL */
  79};
  80
  81static struct rt_channel_plan_map       RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
  82        /*  0x00 ~ 0x1F , Old Define ===== */
  83        {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
  84        {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
  85        {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
  86        {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
  87        {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
  88        {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
  89        {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
  90        {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
  91        {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
  92        {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
  93        {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
  94        {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
  95        {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
  96        {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
  97        {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
  98        {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
  99        {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
 100        {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
 101        {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
 102        {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
 103        {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
 104        {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
 105        {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
 106        {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
 107        {0x06}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
 108        {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
 109        {0x00}, /* 0x1A, */
 110        {0x00}, /* 0x1B, */
 111        {0x00}, /* 0x1C, */
 112        {0x00}, /* 0x1D, */
 113        {0x00}, /* 0x1E, */
 114        {0x06}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
 115        /*  0x20 ~ 0x7F , New Define ===== */
 116        {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
 117        {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
 118        {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
 119        {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
 120        {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
 121        {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
 122        {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
 123        {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
 124        {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
 125        {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
 126        {0x00}, /* 0x2A, */
 127        {0x00}, /* 0x2B, */
 128        {0x00}, /* 0x2C, */
 129        {0x00}, /* 0x2D, */
 130        {0x00}, /* 0x2E, */
 131        {0x00}, /* 0x2F, */
 132        {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
 133        {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
 134        {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
 135        {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
 136        {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
 137        {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
 138        {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
 139        {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
 140        {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
 141        {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
 142        {0x00}, /* 0x3A, */
 143        {0x00}, /* 0x3B, */
 144        {0x00}, /* 0x3C, */
 145        {0x00}, /* 0x3D, */
 146        {0x00}, /* 0x3E, */
 147        {0x00}, /* 0x3F, */
 148        {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
 149        {0x05}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */
 150        {0x01}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */
 151        {0x02}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */
 152        {0x02}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */
 153        {0x00}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */
 154        {0x02}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */
 155        {0x00}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */
 156        {0x00}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */
 157        {0x00}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */
 158        {0x00}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */
 159        {0x00}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */
 160        {0x00}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */
 161        {0x02}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */
 162        {0x00}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */
 163        {0x02}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */
 164        {0x00}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */
 165        {0x02}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */
 166};
 167
 168 /* use the combination for max channel numbers */
 169static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03};
 170
 171/* Search the @param ch in given @param ch_set
 172 * @ch_set: the given channel set
 173 * @ch: the given channel number
 174 *
 175 * return the index of channel_num in channel_set, -1 if not found
 176 */
 177int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
 178{
 179        int i;
 180
 181        for (i = 0; ch_set[i].ChannelNum != 0; i++) {
 182                if (ch == ch_set[i].ChannelNum)
 183                        break;
 184        }
 185
 186        if (i >= ch_set[i].ChannelNum)
 187                return -1;
 188        return i;
 189}
 190
 191/****************************************************************************
 192
 193Following are the initialization functions for WiFi MLME
 194
 195*****************************************************************************/
 196
 197int init_hw_mlme_ext(struct adapter *padapter)
 198{
 199        struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 200
 201        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
 202        return _SUCCESS;
 203}
 204
 205void init_mlme_default_rate_set(struct adapter *padapter)
 206{
 207        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 208
 209        unsigned char mixed_datarate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_, 0xff};
 210        unsigned char mixed_basicrate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,};
 211        unsigned char supported_mcs_set[16] = {0xff, 0xff, 0x00, 0x00, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
 212
 213        memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
 214        memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
 215
 216        memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set));
 217}
 218
 219static void init_mlme_ext_priv_value(struct adapter *padapter)
 220{
 221        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 222        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 223
 224        atomic_set(&pmlmeext->event_seq, 0);
 225        pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
 226        pmlmeext->sa_query_seq = 0;
 227        pmlmeext->mgnt_80211w_IPN = 0;
 228        pmlmeext->mgnt_80211w_IPN_rx = 0;
 229        pmlmeext->cur_channel = padapter->registrypriv.channel;
 230        pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
 231        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 232
 233        pmlmeext->retry = 0;
 234
 235        pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
 236
 237        init_mlme_default_rate_set(padapter);
 238
 239        pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
 240        pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
 241        pmlmeext->sitesurvey_res.channel_idx = 0;
 242        pmlmeext->sitesurvey_res.bss_cnt = 0;
 243        pmlmeext->scan_abort = false;
 244
 245        pmlmeinfo->state = WIFI_FW_NULL_STATE;
 246        pmlmeinfo->reauth_count = 0;
 247        pmlmeinfo->reassoc_count = 0;
 248        pmlmeinfo->link_count = 0;
 249        pmlmeinfo->auth_seq = 0;
 250        pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
 251        pmlmeinfo->key_index = 0;
 252        pmlmeinfo->iv = 0;
 253
 254        pmlmeinfo->enc_algo = _NO_PRIVACY_;
 255        pmlmeinfo->authModeToggle = 0;
 256
 257        memset(pmlmeinfo->chg_txt, 0, 128);
 258
 259        pmlmeinfo->slotTime = SHORT_SLOT_TIME;
 260        pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
 261
 262        pmlmeinfo->dialogToken = 0;
 263
 264        pmlmeext->action_public_rxseq = 0xffff;
 265        pmlmeext->action_public_dialog_token = 0xff;
 266}
 267
 268static int has_channel(struct rt_channel_info *channel_set,
 269                                           u8 chanset_size,
 270                                           u8 chan)
 271{
 272        int i;
 273
 274        for (i = 0; i < chanset_size; i++) {
 275                if (channel_set[i].ChannelNum == chan) {
 276                        return 1;
 277                }
 278        }
 279
 280        return 0;
 281}
 282
 283static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set,
 284                                                          u8 chanset_size,
 285                                                          struct p2p_channels *channel_list)
 286{
 287
 288        static const struct p2p_oper_class_map op_class[] = {
 289                { IEEE80211G,  81,   1,  13,  1, BW20 },
 290                { IEEE80211G,  82,  14,  14,  1, BW20 },
 291                { IEEE80211A, 115,  36,  48,  4, BW20 },
 292                { IEEE80211A, 116,  36,  44,  8, BW40PLUS },
 293                { IEEE80211A, 117,  40,  48,  8, BW40MINUS },
 294                { IEEE80211A, 124, 149, 161,  4, BW20 },
 295                { IEEE80211A, 125, 149, 169,  4, BW20 },
 296                { IEEE80211A, 126, 149, 157,  8, BW40PLUS },
 297                { IEEE80211A, 127, 153, 161,  8, BW40MINUS },
 298                { -1, 0, 0, 0, 0, BW20 }
 299        };
 300
 301        int cla, op;
 302
 303        cla = 0;
 304
 305        for (op = 0; op_class[op].op_class; op++) {
 306                u8 ch;
 307                const struct p2p_oper_class_map *o = &op_class[op];
 308                struct p2p_reg_class *reg = NULL;
 309
 310                for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
 311                        if (!has_channel(channel_set, chanset_size, ch))
 312                                continue;
 313
 314                        if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
 315                                continue;
 316
 317                        if ((0 < (padapter->registrypriv.bw_mode & 0xf0)) &&
 318                                ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
 319                                continue;
 320
 321                        if (!reg) {
 322                                reg = &channel_list->reg_class[cla];
 323                                cla++;
 324                                reg->reg_class = o->op_class;
 325                                reg->channels = 0;
 326                        }
 327                        reg->channel[reg->channels] = ch;
 328                        reg->channels++;
 329                }
 330        }
 331        channel_list->reg_classes = cla;
 332
 333}
 334
 335static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set)
 336{
 337        u8 index, chanset_size = 0;
 338        u8 b2_4GBand = false;
 339        u8 Index2G = 0;
 340
 341        memset(channel_set, 0, sizeof(struct rt_channel_info)*MAX_CHANNEL_NUM);
 342
 343        if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE)
 344                return chanset_size;
 345
 346        if (IsSupported24G(padapter->registrypriv.wireless_mode)) {
 347                b2_4GBand = true;
 348                if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
 349                        Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
 350                else
 351                        Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
 352        }
 353
 354        if (b2_4GBand) {
 355                for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
 356                        channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
 357
 358                        if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */
 359                                (RT_CHANNEL_DOMAIN_GLOBAL_NULL == ChannelPlan)) {
 360                                if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
 361                                        channel_set[chanset_size].ScanType = SCAN_ACTIVE;
 362                                else if ((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
 363                                        channel_set[chanset_size].ScanType  = SCAN_PASSIVE;
 364                        } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan ||
 365                                RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { /*  channel 12~13, passive scan */
 366                                if (channel_set[chanset_size].ChannelNum <= 11)
 367                                        channel_set[chanset_size].ScanType = SCAN_ACTIVE;
 368                                else
 369                                        channel_set[chanset_size].ScanType = SCAN_PASSIVE;
 370                        } else
 371                                channel_set[chanset_size].ScanType = SCAN_ACTIVE;
 372
 373                        chanset_size++;
 374                }
 375        }
 376
 377        return chanset_size;
 378}
 379
 380void init_mlme_ext_priv(struct adapter *padapter)
 381{
 382        struct registry_priv *pregistrypriv = &padapter->registrypriv;
 383        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 384        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 385        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 386
 387        pmlmeext->padapter = padapter;
 388
 389        /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */
 390
 391        init_mlme_ext_priv_value(padapter);
 392        pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req;
 393
 394        init_mlme_ext_timer(padapter);
 395
 396        init_mlme_ap_info(padapter);
 397
 398        pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
 399        init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
 400        pmlmeext->last_scan_time = 0;
 401        pmlmeext->chan_scan_time = SURVEY_TO;
 402        pmlmeext->mlmeext_init = true;
 403        pmlmeext->active_keep_alive_check = true;
 404
 405#ifdef DBG_FIXED_CHAN
 406        pmlmeext->fixed_chan = 0xFF;
 407#endif
 408}
 409
 410void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
 411{
 412        struct adapter *padapter = pmlmeext->padapter;
 413
 414        if (!padapter)
 415                return;
 416
 417        if (padapter->bDriverStopped) {
 418                del_timer_sync(&pmlmeext->survey_timer);
 419                del_timer_sync(&pmlmeext->link_timer);
 420                /* del_timer_sync(&pmlmeext->ADDBA_timer); */
 421        }
 422}
 423
 424static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
 425{
 426        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 427        u8 *pframe = precv_frame->u.hdr.rx_data;
 428
 429        if (ptable->func) {
 430                /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
 431                if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
 432                    memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
 433                        return;
 434
 435                ptable->func(padapter, precv_frame);
 436        }
 437}
 438
 439void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
 440{
 441        int index;
 442        struct mlme_handler *ptable;
 443        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 444        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 445        u8 *pframe = precv_frame->u.hdr.rx_data;
 446        struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
 447        struct dvobj_priv *psdpriv = padapter->dvobj;
 448        struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
 449
 450        if (GetFrameType(pframe) != WIFI_MGT_TYPE)
 451                return;
 452
 453        /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
 454        if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
 455                memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) {
 456                return;
 457        }
 458
 459        ptable = mlme_sta_tbl;
 460
 461        index = GetFrameSubType(pframe) >> 4;
 462
 463        if (index >= ARRAY_SIZE(mlme_sta_tbl))
 464                return;
 465
 466        ptable += index;
 467
 468        if (psta) {
 469                if (GetRetry(pframe)) {
 470                        if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {
 471                                /* drop the duplicate management frame */
 472                                pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++;
 473                                return;
 474                        }
 475                }
 476                psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
 477        }
 478
 479        switch (GetFrameSubType(pframe)) {
 480        case WIFI_AUTH:
 481                if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 482                        ptable->func = &OnAuth;
 483                else
 484                        ptable->func = &OnAuthClient;
 485                fallthrough;
 486        case WIFI_ASSOCREQ:
 487        case WIFI_REASSOCREQ:
 488                _mgt_dispatcher(padapter, ptable, precv_frame);
 489                break;
 490        case WIFI_PROBEREQ:
 491                _mgt_dispatcher(padapter, ptable, precv_frame);
 492                break;
 493        case WIFI_BEACON:
 494                _mgt_dispatcher(padapter, ptable, precv_frame);
 495                break;
 496        case WIFI_ACTION:
 497                /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */
 498                _mgt_dispatcher(padapter, ptable, precv_frame);
 499                break;
 500        default:
 501                _mgt_dispatcher(padapter, ptable, precv_frame);
 502                break;
 503        }
 504}
 505
 506/****************************************************************************
 507
 508Following are the callback functions for each subtype of the management frames
 509
 510*****************************************************************************/
 511
 512unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
 513{
 514        unsigned int    ielen;
 515        unsigned char *p;
 516        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 517        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 518        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 519        struct wlan_bssid_ex    *cur = &pmlmeinfo->network;
 520        u8 *pframe = precv_frame->u.hdr.rx_data;
 521        uint len = precv_frame->u.hdr.len;
 522        u8 is_valid_p2p_probereq = false;
 523
 524        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 525                return _SUCCESS;
 526
 527        if (check_fwstate(pmlmepriv, _FW_LINKED) == false &&
 528                check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) {
 529                return _SUCCESS;
 530        }
 531
 532        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_SSID, (int *)&ielen,
 533                        len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
 534
 535
 536        /* check (wildcard) SSID */
 537        if (p) {
 538                if (is_valid_p2p_probereq)
 539                        goto _issue_probersp;
 540
 541                if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength))
 542                        || (ielen == 0 && pmlmeinfo->hidden_ssid_mode)
 543                )
 544                        return _SUCCESS;
 545
 546_issue_probersp:
 547                if ((check_fwstate(pmlmepriv, _FW_LINKED) &&
 548                     pmlmepriv->cur_network.join_res) ||
 549                    check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
 550                        issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
 551        }
 552
 553        return _SUCCESS;
 554
 555}
 556
 557unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
 558{
 559        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 560
 561        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
 562                report_survey_event(padapter, precv_frame);
 563                return _SUCCESS;
 564        }
 565
 566        return _SUCCESS;
 567
 568}
 569
 570unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
 571{
 572        int cam_idx;
 573        struct sta_info *psta;
 574        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 575        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 576        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 577        struct sta_priv *pstapriv = &padapter->stapriv;
 578        u8 *pframe = precv_frame->u.hdr.rx_data;
 579        uint len = precv_frame->u.hdr.len;
 580        struct wlan_bssid_ex *pbss;
 581        int ret = _SUCCESS;
 582        u8 *p = NULL;
 583        u32 ielen = 0;
 584
 585        p = rtw_get_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, WLAN_EID_EXT_SUPP_RATES, &ielen, precv_frame->u.hdr.len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_);
 586        if (p && ielen > 0) {
 587                if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D))
 588                        /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */
 589                        *(p + 1) = ielen - 1;
 590        }
 591
 592        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
 593                report_survey_event(padapter, precv_frame);
 594                return _SUCCESS;
 595        }
 596
 597        if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
 598                if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
 599                        /* we should update current network before auth, or some IE is wrong */
 600                        pbss = rtw_malloc(sizeof(struct wlan_bssid_ex));
 601                        if (pbss) {
 602                                if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
 603                                        update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
 604                                        rtw_get_bcn_info(&(pmlmepriv->cur_network));
 605                                }
 606                                kfree(pbss);
 607                        }
 608
 609                        /* check the vendor of the assoc AP */
 610                        pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
 611
 612                        /* update TSF Value */
 613                        update_TSF(pmlmeext, pframe, len);
 614
 615                        /* reset for adaptive_early_32k */
 616                        pmlmeext->adaptive_tsf_done = false;
 617                        pmlmeext->DrvBcnEarly = 0xff;
 618                        pmlmeext->DrvBcnTimeOut = 0xff;
 619                        pmlmeext->bcn_cnt = 0;
 620                        memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt));
 621                        memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio));
 622
 623                        /* start auth */
 624                        start_clnt_auth(padapter);
 625
 626                        return _SUCCESS;
 627                }
 628
 629                if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
 630                        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
 631                        if (psta) {
 632                                ret = rtw_check_bcn_info(padapter, pframe, len);
 633                                if (!ret) {
 634                                        netdev_dbg(padapter->pnetdev,
 635                                                   "ap has changed, disconnect now\n ");
 636                                        receive_disconnect(padapter,
 637                                                           pmlmeinfo->network.MacAddress, 0);
 638                                        return _SUCCESS;
 639                                }
 640                                /* update WMM, ERP in the beacon */
 641                                /* todo: the timer is used instead of the number of the beacon received */
 642                                if ((sta_rx_pkts(psta) & 0xf) == 0)
 643                                        update_beacon_info(padapter, pframe, len, psta);
 644
 645                                adaptive_early_32k(pmlmeext, pframe, len);
 646                        }
 647                } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
 648                        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
 649                        if (psta) {
 650                                /* update WMM, ERP in the beacon */
 651                                /* todo: the timer is used instead of the number of the beacon received */
 652                                if ((sta_rx_pkts(psta) & 0xf) == 0) {
 653                                        update_beacon_info(padapter, pframe, len, psta);
 654                                }
 655                        } else {
 656                                /* allocate a new CAM entry for IBSS station */
 657                                cam_idx = allocate_fw_sta_entry(padapter);
 658                                if (cam_idx == NUM_STA)
 659                                        goto _END_ONBEACON_;
 660
 661                                /* get supported rate */
 662                                if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL) {
 663                                        pmlmeinfo->FW_sta_info[cam_idx].status = 0;
 664                                        goto _END_ONBEACON_;
 665                                }
 666
 667                                /* update TSF Value */
 668                                update_TSF(pmlmeext, pframe, len);
 669
 670                                /* report sta add event */
 671                                report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
 672                        }
 673                }
 674        }
 675
 676_END_ONBEACON_:
 677
 678        return _SUCCESS;
 679
 680}
 681
 682unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
 683{
 684        unsigned int    auth_mode, seq, ie_len;
 685        unsigned char *sa, *p;
 686        u16 algorithm;
 687        int     status;
 688        static struct sta_info stat;
 689        struct  sta_info *pstat = NULL;
 690        struct  sta_priv *pstapriv = &padapter->stapriv;
 691        struct security_priv *psecuritypriv = &padapter->securitypriv;
 692        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 693        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 694        u8 *pframe = precv_frame->u.hdr.rx_data;
 695        uint len = precv_frame->u.hdr.len;
 696        u8 offset = 0;
 697
 698        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
 699                return _FAIL;
 700
 701        sa = GetAddr2Ptr(pframe);
 702
 703        auth_mode = psecuritypriv->dot11AuthAlgrthm;
 704
 705        if (GetPrivacy(pframe)) {
 706                u8 *iv;
 707                struct rx_pkt_attrib     *prxattrib = &(precv_frame->u.hdr.attrib);
 708
 709                prxattrib->hdrlen = WLAN_HDR_A3_LEN;
 710                prxattrib->encrypt = _WEP40_;
 711
 712                iv = pframe+prxattrib->hdrlen;
 713                prxattrib->key_index = ((iv[3]>>6)&0x3);
 714
 715                prxattrib->iv_len = 4;
 716                prxattrib->icv_len = 4;
 717
 718                rtw_wep_decrypt(padapter, (u8 *)precv_frame);
 719
 720                offset = 4;
 721        }
 722
 723        algorithm = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
 724        seq     = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
 725
 726        if (auth_mode == 2 &&
 727                        psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
 728                        psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
 729                auth_mode = 0;
 730
 731        if ((algorithm > 0 && auth_mode == 0) ||        /*  rx a shared-key auth but shared not enabled */
 732                (algorithm == 0 && auth_mode == 1)) {   /*  rx a open-system auth but shared-key is enabled */
 733
 734                status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
 735
 736                goto auth_fail;
 737        }
 738
 739        if (rtw_access_ctrl(padapter, sa) == false) {
 740                status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
 741                goto auth_fail;
 742        }
 743
 744        pstat = rtw_get_stainfo(pstapriv, sa);
 745        if (pstat == NULL) {
 746
 747                /*  allocate a new one */
 748                pstat = rtw_alloc_stainfo(pstapriv, sa);
 749                if (pstat == NULL) {
 750                        status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
 751                        goto auth_fail;
 752                }
 753
 754                pstat->state = WIFI_FW_AUTH_NULL;
 755                pstat->auth_seq = 0;
 756
 757                /* pstat->flags = 0; */
 758                /* pstat->capability = 0; */
 759        } else {
 760
 761                spin_lock_bh(&pstapriv->asoc_list_lock);
 762                if (list_empty(&pstat->asoc_list) == false) {
 763                        list_del_init(&pstat->asoc_list);
 764                        pstapriv->asoc_list_cnt--;
 765                        if (pstat->expire_to > 0) {
 766                                /* TODO: STA re_auth within expire_to */
 767                        }
 768                }
 769                spin_unlock_bh(&pstapriv->asoc_list_lock);
 770
 771                if (seq == 1) {
 772                        /* TODO: STA re_auth and auth timeout */
 773                }
 774        }
 775
 776        spin_lock_bh(&pstapriv->auth_list_lock);
 777        if (list_empty(&pstat->auth_list)) {
 778
 779                list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
 780                pstapriv->auth_list_cnt++;
 781        }
 782        spin_unlock_bh(&pstapriv->auth_list_lock);
 783
 784        if (pstat->auth_seq == 0)
 785                pstat->expire_to = pstapriv->auth_to;
 786
 787
 788        if ((pstat->auth_seq + 1) != seq) {
 789                status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
 790                goto auth_fail;
 791        }
 792
 793        if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) {
 794                if (seq == 1) {
 795                        pstat->state &= ~WIFI_FW_AUTH_NULL;
 796                        pstat->state |= WIFI_FW_AUTH_SUCCESS;
 797                        pstat->expire_to = pstapriv->assoc_to;
 798                        pstat->authalg = algorithm;
 799                } else {
 800                        status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
 801                        goto auth_fail;
 802                }
 803        } else { /*  shared system or auto authentication */
 804                if (seq == 1) {
 805                        /* prepare for the challenging txt... */
 806                        memset((void *)pstat->chg_txt, 78, 128);
 807
 808                        pstat->state &= ~WIFI_FW_AUTH_NULL;
 809                        pstat->state |= WIFI_FW_AUTH_STATE;
 810                        pstat->authalg = algorithm;
 811                        pstat->auth_seq = 2;
 812                } else if (seq == 3) {
 813
 814                        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&ie_len,
 815                                        len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
 816
 817                        if ((p == NULL) || (ie_len <= 0)) {
 818                                status = WLAN_STATUS_CHALLENGE_FAIL;
 819                                goto auth_fail;
 820                        }
 821
 822                        if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
 823                                pstat->state &= (~WIFI_FW_AUTH_STATE);
 824                                pstat->state |= WIFI_FW_AUTH_SUCCESS;
 825                                /*  challenging txt is correct... */
 826                                pstat->expire_to =  pstapriv->assoc_to;
 827                        } else {
 828                                status = WLAN_STATUS_CHALLENGE_FAIL;
 829                                goto auth_fail;
 830                        }
 831                } else {
 832                        status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
 833                        goto auth_fail;
 834                }
 835        }
 836
 837
 838        /*  Now, we are going to issue_auth... */
 839        pstat->auth_seq = seq + 1;
 840
 841        issue_auth(padapter, pstat, (unsigned short)(WLAN_STATUS_SUCCESS));
 842
 843        if (pstat->state & WIFI_FW_AUTH_SUCCESS)
 844                pstat->auth_seq = 0;
 845
 846
 847        return _SUCCESS;
 848
 849auth_fail:
 850
 851        if (pstat)
 852                rtw_free_stainfo(padapter, pstat);
 853
 854        pstat = &stat;
 855        memset((char *)pstat, '\0', sizeof(stat));
 856        pstat->auth_seq = 2;
 857        memcpy(pstat->hwaddr, sa, 6);
 858
 859        issue_auth(padapter, pstat, (unsigned short)status);
 860
 861        return _FAIL;
 862
 863}
 864
 865unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame)
 866{
 867        unsigned int    seq, len, status, offset;
 868        unsigned char *p;
 869        unsigned int    go2asoc = 0;
 870        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 871        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 872        u8 *pframe = precv_frame->u.hdr.rx_data;
 873        uint pkt_len = precv_frame->u.hdr.len;
 874
 875        /* check A1 matches or not */
 876        if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
 877                return _SUCCESS;
 878
 879        if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
 880                return _SUCCESS;
 881
 882        offset = (GetPrivacy(pframe)) ? 4 : 0;
 883
 884        seq     = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
 885        status  = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4));
 886
 887        if (status != 0) {
 888                if (status == 13) { /*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
 889                        if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
 890                                pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
 891                        else
 892                                pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
 893                        /* pmlmeinfo->reauth_count = 0; */
 894                }
 895
 896                set_link_timer(pmlmeext, 1);
 897                goto authclnt_fail;
 898        }
 899
 900        if (seq == 2) {
 901                if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
 902                         /*  legendary shared system */
 903                        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&len,
 904                                pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
 905
 906                        if (!p)
 907                                goto authclnt_fail;
 908
 909                        memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
 910                        pmlmeinfo->auth_seq = 3;
 911                        issue_auth(padapter, NULL, 0);
 912                        set_link_timer(pmlmeext, REAUTH_TO);
 913
 914                        return _SUCCESS;
 915                } else {
 916                        /*  open system */
 917                        go2asoc = 1;
 918                }
 919        } else if (seq == 4) {
 920                if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
 921                        go2asoc = 1;
 922                } else {
 923                        goto authclnt_fail;
 924                }
 925        } else {
 926                /*  this is also illegal */
 927                goto authclnt_fail;
 928        }
 929
 930        if (go2asoc) {
 931                netdev_dbg(padapter->pnetdev, "auth success, start assoc\n");
 932                start_clnt_assoc(padapter);
 933                return _SUCCESS;
 934        }
 935
 936authclnt_fail:
 937
 938        /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
 939
 940        return _FAIL;
 941
 942}
 943
 944unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
 945{
 946        u16 capab_info;
 947        struct rtw_ieee802_11_elems elems;
 948        struct sta_info *pstat;
 949        unsigned char   *p, *pos, *wpa_ie;
 950        unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
 951        int             i, ie_len, wpa_ie_len, left;
 952        unsigned char   supportRate[16];
 953        int                                     supportRateNum;
 954        unsigned short          status = WLAN_STATUS_SUCCESS;
 955        unsigned short          frame_type, ie_offset = 0;
 956        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 957        struct security_priv *psecuritypriv = &padapter->securitypriv;
 958        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 959        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 960        struct wlan_bssid_ex    *cur = &(pmlmeinfo->network);
 961        struct sta_priv *pstapriv = &padapter->stapriv;
 962        u8 *pframe = precv_frame->u.hdr.rx_data;
 963        uint pkt_len = precv_frame->u.hdr.len;
 964
 965        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
 966                return _FAIL;
 967
 968        frame_type = GetFrameSubType(pframe);
 969        if (frame_type == WIFI_ASSOCREQ) 
 970                ie_offset = _ASOCREQ_IE_OFFSET_;
 971        else /*  WIFI_REASSOCREQ */
 972                ie_offset = _REASOCREQ_IE_OFFSET_;
 973
 974
 975        if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset)
 976                return _FAIL;
 977
 978        pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
 979        if (!pstat) {
 980                status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
 981                goto asoc_class2_error;
 982        }
 983
 984        capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN);
 985        /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */
 986
 987        left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
 988        pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
 989
 990        /*  check if this stat has been successfully authenticated/assocated */
 991        if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
 992                if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
 993                        status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA;
 994                        goto asoc_class2_error;
 995                } else {
 996                        pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
 997                        pstat->state |= WIFI_FW_ASSOC_STATE;
 998                }
 999        } else {
1000                pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1001                pstat->state |= WIFI_FW_ASSOC_STATE;
1002        }
1003
1004
1005        pstat->capability = capab_info;
1006
1007        /* now parse all ieee802_11 ie to point to elems */
1008        if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
1009            !elems.ssid) {
1010                status = WLAN_STATUS_CHALLENGE_FAIL;
1011                goto OnAssocReqFail;
1012        }
1013
1014        /*  now we should check all the fields... */
1015        /*  checking SSID */
1016        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SSID, &ie_len,
1017                pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1018
1019        if (!p || ie_len == 0) {
1020                /*  broadcast ssid, however it is not allowed in assocreq */
1021                status = WLAN_STATUS_CHALLENGE_FAIL;
1022                goto OnAssocReqFail;
1023        } else {
1024                /*  check if ssid match */
1025                if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
1026                        status = WLAN_STATUS_CHALLENGE_FAIL;
1027
1028                if (ie_len != cur->Ssid.SsidLength)
1029                        status = WLAN_STATUS_CHALLENGE_FAIL;
1030        }
1031
1032        if (status != WLAN_STATUS_SUCCESS)
1033                goto OnAssocReqFail;
1034
1035        /*  check if the supported rate is ok */
1036        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SUPP_RATES, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1037        if (p == NULL) {
1038                /*  use our own rate set as statoin used */
1039                /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1040                /* supportRateNum = AP_BSSRATE_LEN; */
1041
1042                status = WLAN_STATUS_CHALLENGE_FAIL;
1043                goto OnAssocReqFail;
1044        } else {
1045                memcpy(supportRate, p+2, ie_len);
1046                supportRateNum = ie_len;
1047
1048                p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_EXT_SUPP_RATES, &ie_len,
1049                                pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1050                if (p !=  NULL) {
1051
1052                        if (supportRateNum <= sizeof(supportRate)) {
1053                                memcpy(supportRate+supportRateNum, p+2, ie_len);
1054                                supportRateNum += ie_len;
1055                        }
1056                }
1057        }
1058
1059        /* todo: mask supportRate between AP & STA -> move to update raid */
1060        /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1061
1062        /* update station supportRate */
1063        pstat->bssratelen = supportRateNum;
1064        memcpy(pstat->bssrateset, supportRate, supportRateNum);
1065        UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1066
1067        /* check RSN/WPA/WPS */
1068        pstat->dot8021xalg = 0;
1069        pstat->wpa_psk = 0;
1070        pstat->wpa_group_cipher = 0;
1071        pstat->wpa2_group_cipher = 0;
1072        pstat->wpa_pairwise_cipher = 0;
1073        pstat->wpa2_pairwise_cipher = 0;
1074        memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1075        if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1076
1077                int group_cipher = 0, pairwise_cipher = 0;
1078
1079                wpa_ie = elems.rsn_ie;
1080                wpa_ie_len = elems.rsn_ie_len;
1081
1082                if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1083                        pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1084                        pstat->wpa_psk |= BIT(1);
1085
1086                        pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
1087                        pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
1088
1089                        if (!pstat->wpa2_group_cipher)
1090                                status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1091
1092                        if (!pstat->wpa2_pairwise_cipher)
1093                                status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1094                } else {
1095                        status = WLAN_STATUS_INVALID_IE;
1096                }
1097
1098        } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1099
1100                int group_cipher = 0, pairwise_cipher = 0;
1101
1102                wpa_ie = elems.wpa_ie;
1103                wpa_ie_len = elems.wpa_ie_len;
1104
1105                if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1106                        pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1107                        pstat->wpa_psk |= BIT(0);
1108
1109                        pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
1110                        pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
1111
1112                        if (!pstat->wpa_group_cipher)
1113                                status = WLAN_STATUS_INVALID_GROUP_CIPHER;
1114
1115                        if (!pstat->wpa_pairwise_cipher)
1116                                status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER;
1117
1118                } else {
1119                        status = WLAN_STATUS_INVALID_IE;
1120                }
1121
1122        } else {
1123                wpa_ie = NULL;
1124                wpa_ie_len = 0;
1125        }
1126
1127        if (status != WLAN_STATUS_SUCCESS)
1128                goto OnAssocReqFail;
1129
1130        pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1131        if (!wpa_ie) {
1132                if (elems.wps_ie) {
1133                        pstat->flags |= WLAN_STA_WPS;
1134                        /* wpabuf_free(sta->wps_ie); */
1135                        /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
1136                        /*                              elems.wps_ie_len - 4); */
1137                } else {
1138                        pstat->flags |= WLAN_STA_MAYBE_WPS;
1139                }
1140
1141
1142                /*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1143                /*  that the selected registrar of AP is _FLASE */
1144                if ((psecuritypriv->wpa_psk > 0)
1145                        && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
1146                        if (pmlmepriv->wps_beacon_ie) {
1147                                u8 selected_registrar = 0;
1148
1149                                rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
1150
1151                                if (!selected_registrar) {
1152                                        status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1153
1154                                        goto OnAssocReqFail;
1155                                }
1156                        }
1157                }
1158
1159        } else {
1160                int copy_len;
1161
1162                if (psecuritypriv->wpa_psk == 0) {
1163                        status = WLAN_STATUS_INVALID_IE;
1164
1165                        goto OnAssocReqFail;
1166
1167                }
1168
1169                if (elems.wps_ie) {
1170                        pstat->flags |= WLAN_STA_WPS;
1171                        copy_len = 0;
1172                } else {
1173                        copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
1174                }
1175
1176
1177                if (copy_len > 0)
1178                        memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
1179
1180        }
1181
1182
1183        /*  check if there is WMM IE & support WWM-PS */
1184        pstat->flags &= ~WLAN_STA_WME;
1185        pstat->qos_option = 0;
1186        pstat->qos_info = 0;
1187        pstat->has_legacy_ac = true;
1188        pstat->uapsd_vo = 0;
1189        pstat->uapsd_vi = 0;
1190        pstat->uapsd_be = 0;
1191        pstat->uapsd_bk = 0;
1192        if (pmlmepriv->qospriv.qos_option) {
1193                p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
1194                for (;;) {
1195                        p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1196                        if (p) {
1197                                if (!memcmp(p+2, WMM_IE, 6)) {
1198
1199                                        pstat->flags |= WLAN_STA_WME;
1200
1201                                        pstat->qos_option = 1;
1202                                        pstat->qos_info = *(p+8);
1203
1204                                        pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
1205
1206                                        if ((pstat->qos_info&0xf) != 0xf)
1207                                                pstat->has_legacy_ac = true;
1208                                        else
1209                                                pstat->has_legacy_ac = false;
1210
1211                                        if (pstat->qos_info&0xf) {
1212                                                if (pstat->qos_info&BIT(0))
1213                                                        pstat->uapsd_vo = BIT(0)|BIT(1);
1214                                                else
1215                                                        pstat->uapsd_vo = 0;
1216
1217                                                if (pstat->qos_info&BIT(1))
1218                                                        pstat->uapsd_vi = BIT(0)|BIT(1);
1219                                                else
1220                                                        pstat->uapsd_vi = 0;
1221
1222                                                if (pstat->qos_info&BIT(2))
1223                                                        pstat->uapsd_bk = BIT(0)|BIT(1);
1224                                                else
1225                                                        pstat->uapsd_bk = 0;
1226
1227                                                if (pstat->qos_info&BIT(3))
1228                                                        pstat->uapsd_be = BIT(0)|BIT(1);
1229                                                else
1230                                                        pstat->uapsd_be = 0;
1231
1232                                        }
1233
1234                                        break;
1235                                }
1236                        } else {
1237                                break;
1238                        }
1239                        p = p + ie_len + 2;
1240                }
1241        }
1242
1243        /* save HT capabilities in the sta object */
1244        memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap));
1245        if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) {
1246                pstat->flags |= WLAN_STA_HT;
1247
1248                pstat->flags |= WLAN_STA_WME;
1249
1250                memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap));
1251
1252        } else
1253                pstat->flags &= ~WLAN_STA_HT;
1254
1255
1256        if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT)) {
1257                status = WLAN_STATUS_CHALLENGE_FAIL;
1258                goto OnAssocReqFail;
1259        }
1260
1261
1262        if ((pstat->flags & WLAN_STA_HT) &&
1263                    ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1264                      (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) {
1265                /* status = WLAN_STATUS_CIPHER_SUITE_REJECTED; */
1266                /* goto OnAssocReqFail; */
1267        }
1268        pstat->flags |= WLAN_STA_NONERP;
1269        for (i = 0; i < pstat->bssratelen; i++) {
1270                if ((pstat->bssrateset[i] & 0x7f) > 22) {
1271                        pstat->flags &= ~WLAN_STA_NONERP;
1272                        break;
1273                }
1274        }
1275
1276        if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1277                pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1278        else
1279                pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1280
1281
1282
1283        if (status != WLAN_STATUS_SUCCESS)
1284                goto OnAssocReqFail;
1285
1286        /* TODO: identify_proprietary_vendor_ie(); */
1287        /*  Realtek proprietary IE */
1288        /*  identify if this is Broadcom sta */
1289        /*  identify if this is ralink sta */
1290        /*  Customer proprietary IE */
1291
1292
1293
1294        /* get a unique AID */
1295        if (pstat->aid == 0) {
1296                for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1297                        if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1298                                break;
1299
1300                /* if (pstat->aid > NUM_STA) { */
1301                if (pstat->aid > pstapriv->max_num_sta) {
1302
1303                        pstat->aid = 0;
1304
1305                        status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1306
1307                        goto OnAssocReqFail;
1308
1309
1310                } else {
1311                        pstapriv->sta_aid[pstat->aid - 1] = pstat;
1312                }
1313        }
1314
1315
1316        pstat->state &= (~WIFI_FW_ASSOC_STATE);
1317        pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1318
1319        spin_lock_bh(&pstapriv->auth_list_lock);
1320        if (!list_empty(&pstat->auth_list)) {
1321                list_del_init(&pstat->auth_list);
1322                pstapriv->auth_list_cnt--;
1323        }
1324        spin_unlock_bh(&pstapriv->auth_list_lock);
1325
1326        spin_lock_bh(&pstapriv->asoc_list_lock);
1327        if (list_empty(&pstat->asoc_list)) {
1328                pstat->expire_to = pstapriv->expire_to;
1329                list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1330                pstapriv->asoc_list_cnt++;
1331        }
1332        spin_unlock_bh(&pstapriv->asoc_list_lock);
1333
1334        /*  now the station is qualified to join our BSS... */
1335        if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (WLAN_STATUS_SUCCESS == status)) {
1336                /* 1 bss_cap_update & sta_info_update */
1337                bss_cap_update_on_sta_join(padapter, pstat);
1338                sta_info_update(padapter, pstat);
1339
1340                /* 2 issue assoc rsp before notify station join event. */
1341                if (frame_type == WIFI_ASSOCREQ)
1342                        issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1343                else
1344                        issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1345
1346                spin_lock_bh(&pstat->lock);
1347                if (pstat->passoc_req) {
1348                        kfree(pstat->passoc_req);
1349                        pstat->passoc_req = NULL;
1350                        pstat->assoc_req_len = 0;
1351                }
1352
1353                pstat->passoc_req =  rtw_zmalloc(pkt_len);
1354                if (pstat->passoc_req) {
1355                        memcpy(pstat->passoc_req, pframe, pkt_len);
1356                        pstat->assoc_req_len = pkt_len;
1357                }
1358                spin_unlock_bh(&pstat->lock);
1359
1360                /* 3-(1) report sta add event */
1361                report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
1362        }
1363
1364        return _SUCCESS;
1365
1366asoc_class2_error:
1367
1368        issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1369
1370        return _FAIL;
1371
1372OnAssocReqFail:
1373
1374        pstat->aid = 0;
1375        if (frame_type == WIFI_ASSOCREQ)
1376                issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1377        else
1378                issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1379
1380        return _FAIL;
1381}
1382
1383unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
1384{
1385        uint i;
1386        int res;
1387        unsigned short  status;
1388        struct ndis_80211_var_ie *pIE;
1389        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1390        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1391        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1392        /* struct wlan_bssid_ex                 *cur_network = &(pmlmeinfo->network); */
1393        u8 *pframe = precv_frame->u.hdr.rx_data;
1394        uint pkt_len = precv_frame->u.hdr.len;
1395
1396        /* check A1 matches or not */
1397        if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1398                return _SUCCESS;
1399
1400        if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1401                return _SUCCESS;
1402
1403        if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1404                return _SUCCESS;
1405
1406        del_timer_sync(&pmlmeext->link_timer);
1407
1408        /* status */
1409        status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
1410        if (status > 0) {
1411                pmlmeinfo->state = WIFI_FW_NULL_STATE;
1412                res = -4;
1413                goto report_assoc_result;
1414        }
1415
1416        /* get capabilities */
1417        pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1418
1419        /* set slot time */
1420        pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
1421
1422        /* AID */
1423        res = pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
1424
1425        /* following are moved to join event callback function */
1426        /* to handle HT, WMM, rate adaptive, update MAC reg */
1427        /* for not to handle the synchronous IO in the tasklet */
1428        for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
1429                pIE = (struct ndis_80211_var_ie *)(pframe + i);
1430
1431                switch (pIE->ElementID) {
1432                case WLAN_EID_VENDOR_SPECIFIC:
1433                        if (!memcmp(pIE->data, WMM_PARA_OUI, 6))        /* WMM */
1434                                WMM_param_handler(padapter, pIE);
1435                        break;
1436
1437                case WLAN_EID_HT_CAPABILITY:    /* HT caps */
1438                        HT_caps_handler(padapter, pIE);
1439                        break;
1440
1441                case WLAN_EID_HT_OPERATION:     /* HT info */
1442                        HT_info_handler(padapter, pIE);
1443                        break;
1444
1445                case WLAN_EID_ERP_INFO:
1446                        ERP_IE_handler(padapter, pIE);
1447                        break;
1448
1449                default:
1450                        break;
1451                }
1452
1453                i += (pIE->Length + 2);
1454        }
1455
1456        pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1457        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1458
1459        /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1460        UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
1461
1462report_assoc_result:
1463        if (res > 0) {
1464                rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
1465        } else {
1466                rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
1467        }
1468
1469        report_join_res(padapter, res);
1470
1471        return _SUCCESS;
1472}
1473
1474unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
1475{
1476        unsigned short  reason;
1477        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1478        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1479        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1480        u8 *pframe = precv_frame->u.hdr.rx_data;
1481
1482        /* check A3 */
1483        if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1484                return _SUCCESS;
1485
1486        reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1487
1488        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1489                struct sta_info *psta;
1490                struct sta_priv *pstapriv = &padapter->stapriv;
1491
1492                /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
1493                /* rtw_free_stainfo(padapter, psta); */
1494                /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
1495
1496                netdev_dbg(padapter->pnetdev,
1497                           "ap recv deauth reason code(%d) sta:%pM\n", reason,
1498                           GetAddr2Ptr(pframe));
1499
1500                psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1501                if (psta) {
1502                        u8 updated = false;
1503
1504                        spin_lock_bh(&pstapriv->asoc_list_lock);
1505                        if (list_empty(&psta->asoc_list) == false) {
1506                                list_del_init(&psta->asoc_list);
1507                                pstapriv->asoc_list_cnt--;
1508                                updated = ap_free_sta(padapter, psta, false, reason);
1509
1510                        }
1511                        spin_unlock_bh(&pstapriv->asoc_list_lock);
1512
1513                        associated_clients_update(padapter, updated);
1514                }
1515
1516
1517                return _SUCCESS;
1518        } else {
1519                int     ignore_received_deauth = 0;
1520
1521                /*      Commented by Albert 20130604 */
1522                /*      Before sending the auth frame to start the STA/GC mode connection with AP/GO, */
1523                /*      we will send the deauth first. */
1524                /*      However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */
1525                /*      Added the following code to avoid this case. */
1526                if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||
1527                        (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {
1528                        if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) {
1529                                ignore_received_deauth = 1;
1530                        } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) {
1531                                /*  TODO: 802.11r */
1532                                ignore_received_deauth = 1;
1533                        }
1534                }
1535
1536                netdev_dbg(padapter->pnetdev,
1537                           "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n",
1538                           reason, GetAddr3Ptr(pframe),
1539                           ignore_received_deauth);
1540
1541                if (0 == ignore_received_deauth) {
1542                        receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1543                }
1544        }
1545        pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1546        return _SUCCESS;
1547
1548}
1549
1550unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame)
1551{
1552        unsigned short  reason;
1553        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1554        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1555        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1556        u8 *pframe = precv_frame->u.hdr.rx_data;
1557
1558        /* check A3 */
1559        if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1560                return _SUCCESS;
1561
1562        reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1563
1564        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1565                struct sta_info *psta;
1566                struct sta_priv *pstapriv = &padapter->stapriv;
1567
1568                /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
1569                /* rtw_free_stainfo(padapter, psta); */
1570                /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
1571
1572                netdev_dbg(padapter->pnetdev,
1573                           "ap recv disassoc reason code(%d) sta:%pM\n",
1574                           reason, GetAddr2Ptr(pframe));
1575
1576                psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1577                if (psta) {
1578                        u8 updated = false;
1579
1580                        spin_lock_bh(&pstapriv->asoc_list_lock);
1581                        if (list_empty(&psta->asoc_list) == false) {
1582                                list_del_init(&psta->asoc_list);
1583                                pstapriv->asoc_list_cnt--;
1584                                updated = ap_free_sta(padapter, psta, false, reason);
1585
1586                        }
1587                        spin_unlock_bh(&pstapriv->asoc_list_lock);
1588
1589                        associated_clients_update(padapter, updated);
1590                }
1591
1592                return _SUCCESS;
1593        } else {
1594                netdev_dbg(padapter->pnetdev,
1595                           "sta recv disassoc reason code(%d) sta:%pM\n",
1596                           reason, GetAddr3Ptr(pframe));
1597
1598                receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1599        }
1600        pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1601        return _SUCCESS;
1602
1603}
1604
1605unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame)
1606{
1607        return _SUCCESS;
1608}
1609
1610unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame)
1611{
1612        struct sta_info *psta = NULL;
1613        struct sta_priv *pstapriv = &padapter->stapriv;
1614        u8 *pframe = precv_frame->u.hdr.rx_data;
1615        u8 *frame_body = (u8 *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1616        u8 category;
1617        u8 action;
1618
1619        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1620
1621        if (!psta)
1622                goto exit;
1623
1624        category = frame_body[0];
1625        if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
1626                goto exit;
1627
1628        action = frame_body[1];
1629        switch (action) {
1630        case WLAN_ACTION_SPCT_MSR_REQ:
1631        case WLAN_ACTION_SPCT_MSR_RPRT:
1632        case WLAN_ACTION_SPCT_TPC_REQ:
1633        case WLAN_ACTION_SPCT_TPC_RPRT:
1634        case WLAN_ACTION_SPCT_CHL_SWITCH:
1635                break;
1636        default:
1637                break;
1638        }
1639
1640exit:
1641        return _FAIL;
1642}
1643
1644unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame)
1645{
1646        u8 *addr;
1647        struct sta_info *psta = NULL;
1648        struct recv_reorder_ctrl *preorder_ctrl;
1649        unsigned char   *frame_body;
1650        unsigned char   category, action;
1651        unsigned short  tid, status;
1652        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1653        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1654        u8 *pframe = precv_frame->u.hdr.rx_data;
1655        struct sta_priv *pstapriv = &padapter->stapriv;
1656
1657        /* check RA matches or not */
1658        if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
1659                return _SUCCESS;
1660
1661        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1662                if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1663                        return _SUCCESS;
1664
1665        addr = GetAddr2Ptr(pframe);
1666        psta = rtw_get_stainfo(pstapriv, addr);
1667
1668        if (!psta)
1669                return _SUCCESS;
1670
1671        frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1672
1673        category = frame_body[0];
1674        if (category == RTW_WLAN_CATEGORY_BACK) {/*  representing Block Ack */
1675                if (!pmlmeinfo->HT_enable)
1676                        return _SUCCESS;
1677
1678                action = frame_body[1];
1679                switch (action) {
1680                case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
1681
1682                        memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
1683                        /* process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */
1684                        process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
1685
1686                        if (pmlmeinfo->accept_addba_req) {
1687                                issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 0);
1688                        } else {
1689                                issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
1690                        }
1691
1692                        break;
1693
1694                case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
1695                        status = get_unaligned_le16(&frame_body[3]);
1696                        tid = ((frame_body[5] >> 2) & 0x7);
1697
1698                        if (status == 0) {
1699                                /* successful */
1700                                psta->htpriv.agg_enable_bitmap |= BIT(tid);
1701                                psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1702                        } else {
1703                                psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1704                        }
1705
1706                        if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
1707                                psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1708                                psta->expire_to = pstapriv->expire_to;
1709                                psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
1710                        }
1711
1712                        break;
1713
1714                case WLAN_ACTION_DELBA: /* DELBA */
1715                        if ((frame_body[3] & BIT(3)) == 0) {
1716                                psta->htpriv.agg_enable_bitmap &=
1717                                        ~BIT((frame_body[3] >> 4) & 0xf);
1718                                psta->htpriv.candidate_tid_bitmap &=
1719                                        ~BIT((frame_body[3] >> 4) & 0xf);
1720                        } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
1721                                tid = (frame_body[3] >> 4) & 0x0F;
1722
1723                                preorder_ctrl =  &psta->recvreorder_ctrl[tid];
1724                                preorder_ctrl->enable = false;
1725                                preorder_ctrl->indicate_seq = 0xffff;
1726                        }
1727                        /* todo: how to notify the host while receiving DELETE BA */
1728                        break;
1729
1730                default:
1731                        break;
1732                }
1733        }
1734        return _SUCCESS;
1735}
1736
1737static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
1738{
1739        struct adapter *adapter = recv_frame->u.hdr.adapter;
1740        struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
1741        u8 *frame = recv_frame->u.hdr.rx_data;
1742        u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
1743                (recv_frame->u.hdr.attrib.frag_num & 0xf);
1744
1745        if (GetRetry(frame)) {
1746                if (token >= 0) {
1747                        if ((seq_ctrl == mlmeext->action_public_rxseq)
1748                                && (token == mlmeext->action_public_dialog_token))
1749                                return _FAIL;
1750                } else {
1751                        if (seq_ctrl == mlmeext->action_public_rxseq)
1752                                return _FAIL;
1753                }
1754        }
1755
1756        mlmeext->action_public_rxseq = seq_ctrl;
1757
1758        if (token >= 0)
1759                mlmeext->action_public_dialog_token = token;
1760
1761        return _SUCCESS;
1762}
1763
1764static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
1765{
1766        u8 *pframe = precv_frame->u.hdr.rx_data;
1767        u8 *frame_body;
1768        u8 dialogToken = 0;
1769
1770        frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1771
1772        dialogToken = frame_body[7];
1773
1774        if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
1775                return _FAIL;
1776
1777        return _SUCCESS;
1778}
1779
1780static unsigned int on_action_public_vendor(union recv_frame *precv_frame)
1781{
1782        unsigned int ret = _FAIL;
1783        u8 *pframe = precv_frame->u.hdr.rx_data;
1784        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1785
1786        if (!memcmp(frame_body + 2, P2P_OUI, 4)) {
1787                ret = on_action_public_p2p(precv_frame);
1788        }
1789
1790        return ret;
1791}
1792
1793static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
1794{
1795        unsigned int ret = _FAIL;
1796        u8 *pframe = precv_frame->u.hdr.rx_data;
1797        uint frame_len = precv_frame->u.hdr.len;
1798        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1799        u8 token;
1800        struct adapter *adapter = precv_frame->u.hdr.adapter;
1801        char msg[64];
1802
1803        token = frame_body[2];
1804
1805        if (rtw_action_public_decache(precv_frame, token) == _FAIL)
1806                goto exit;
1807
1808        scnprintf(msg, sizeof(msg), "%s(token:%u)", action_public_str(action), token);
1809        rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
1810
1811        ret = _SUCCESS;
1812
1813exit:
1814        return ret;
1815}
1816
1817unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame)
1818{
1819        unsigned int ret = _FAIL;
1820        u8 *pframe = precv_frame->u.hdr.rx_data;
1821        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1822        u8 category, action;
1823
1824        /* check RA matches or not */
1825        if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
1826                goto exit;
1827
1828        category = frame_body[0];
1829        if (category != RTW_WLAN_CATEGORY_PUBLIC)
1830                goto exit;
1831
1832        action = frame_body[1];
1833        switch (action) {
1834        case ACT_PUBLIC_VENDOR:
1835                ret = on_action_public_vendor(precv_frame);
1836                break;
1837        default:
1838                ret = on_action_public_default(precv_frame, action);
1839                break;
1840        }
1841
1842exit:
1843        return ret;
1844}
1845
1846unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame)
1847{
1848        u8 *pframe = precv_frame->u.hdr.rx_data;
1849        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
1850        u8 category, action;
1851
1852        /* check RA matches or not */
1853        if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
1854                goto exit;
1855
1856        category = frame_body[0];
1857        if (category != RTW_WLAN_CATEGORY_HT)
1858                goto exit;
1859
1860        action = frame_body[1];
1861        switch (action) {
1862        case WLAN_HT_ACTION_COMPRESSED_BF:
1863                break;
1864        default:
1865                break;
1866        }
1867
1868exit:
1869
1870        return _SUCCESS;
1871}
1872
1873unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv_frame)
1874{
1875        u8 *pframe = precv_frame->u.hdr.rx_data;
1876        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
1877        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1878        unsigned short tid;
1879
1880        switch (pframe[WLAN_HDR_A3_LEN+1]) {
1881        case 0: /* SA Query req */
1882                memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short));
1883                issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid);
1884                break;
1885
1886        case 1: /* SA Query rsp */
1887                del_timer_sync(&pmlmeext->sa_query_timer);
1888                break;
1889        default:
1890                break;
1891        }
1892        if (0) {
1893                int pp;
1894
1895                printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
1896                for (pp = 0; pp < pattrib->pkt_len; pp++)
1897                        printk(" %02x ", pframe[pp]);
1898                printk("\n");
1899        }
1900
1901        return _SUCCESS;
1902}
1903
1904unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame)
1905{
1906        int i;
1907        unsigned char category;
1908        struct action_handler *ptable;
1909        unsigned char *frame_body;
1910        u8 *pframe = precv_frame->u.hdr.rx_data;
1911
1912        frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1913
1914        category = frame_body[0];
1915
1916        for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) {
1917                ptable = &OnAction_tbl[i];
1918
1919                if (category == ptable->num)
1920                        ptable->func(padapter, precv_frame);
1921
1922        }
1923
1924        return _SUCCESS;
1925
1926}
1927
1928unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame)
1929{
1930        return _SUCCESS;
1931}
1932
1933static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
1934{
1935        struct xmit_frame *pmgntframe;
1936        struct xmit_buf *pxmitbuf;
1937
1938        if (once)
1939                pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
1940        else
1941                pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
1942
1943        if (!pmgntframe)
1944                goto exit;
1945
1946        pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
1947        if (pxmitbuf == NULL) {
1948                rtw_free_xmitframe(pxmitpriv, pmgntframe);
1949                pmgntframe = NULL;
1950                goto exit;
1951        }
1952
1953        pmgntframe->frame_tag = MGNT_FRAMETAG;
1954        pmgntframe->pxmitbuf = pxmitbuf;
1955        pmgntframe->buf_addr = pxmitbuf->pbuf;
1956        pxmitbuf->priv_data = pmgntframe;
1957
1958exit:
1959        return pmgntframe;
1960
1961}
1962
1963inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
1964{
1965        return _alloc_mgtxmitframe(pxmitpriv, false);
1966}
1967
1968/****************************************************************************
1969
1970Following are some TX functions for WiFi MLME
1971
1972*****************************************************************************/
1973
1974void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
1975{
1976        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1977
1978        pmlmeext->tx_rate = rate;
1979}
1980
1981void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
1982{
1983        u8 wireless_mode;
1984        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1985
1986        /* memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */
1987
1988        pattrib->hdrlen = 24;
1989        pattrib->nr_frags = 1;
1990        pattrib->priority = 7;
1991        pattrib->mac_id = 0;
1992        pattrib->qsel = 0x12;
1993
1994        pattrib->pktlen = 0;
1995
1996        if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
1997                wireless_mode = WIRELESS_11B;
1998        else
1999                wireless_mode = WIRELESS_11G;
2000        pattrib->raid =  rtw_get_mgntframe_raid(padapter, wireless_mode);
2001        pattrib->rate = pmlmeext->tx_rate;
2002
2003        pattrib->encrypt = _NO_PRIVACY_;
2004        pattrib->bswenc = false;
2005
2006        pattrib->qos_en = false;
2007        pattrib->ht_en = false;
2008        pattrib->bwmode = CHANNEL_WIDTH_20;
2009        pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2010        pattrib->sgi = false;
2011
2012        pattrib->seqnum = pmlmeext->mgnt_seq;
2013
2014        pattrib->retry_ctrl = true;
2015
2016        pattrib->mbssid = 0;
2017
2018}
2019
2020void update_mgntframe_attrib_addr(struct adapter *padapter, struct xmit_frame *pmgntframe)
2021{
2022        u8 *pframe;
2023        struct pkt_attrib       *pattrib = &pmgntframe->attrib;
2024
2025        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2026
2027        memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);
2028        memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN);
2029}
2030
2031void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
2032{
2033        if (padapter->bSurpriseRemoved ||
2034                padapter->bDriverStopped) {
2035                rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2036                rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2037                return;
2038        }
2039
2040        rtw_hal_mgnt_xmit(padapter, pmgntframe);
2041}
2042
2043s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
2044{
2045        s32 ret = _FAIL;
2046        unsigned long irqL;
2047        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2048        struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2049        struct submit_ctx sctx;
2050
2051        if (padapter->bSurpriseRemoved ||
2052                padapter->bDriverStopped) {
2053                rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2054                rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2055                return ret;
2056        }
2057
2058        rtw_sctx_init(&sctx, timeout_ms);
2059        pxmitbuf->sctx = &sctx;
2060
2061        ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
2062
2063        if (ret == _SUCCESS)
2064                ret = rtw_sctx_wait(&sctx);
2065
2066        spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2067        pxmitbuf->sctx = NULL;
2068        spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2069
2070        return ret;
2071}
2072
2073s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
2074{
2075        static u8 seq_no;
2076        s32 ret = _FAIL;
2077        u32 timeout_ms = 500;/*   500ms */
2078        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2079
2080        if (padapter->bSurpriseRemoved ||
2081                padapter->bDriverStopped) {
2082                rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2083                rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2084                return -1;
2085        }
2086
2087        if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex) == 0) {
2088                pxmitpriv->ack_tx = true;
2089                pxmitpriv->seq_no = seq_no++;
2090                pmgntframe->ack_report = 1;
2091                if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
2092                        ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
2093
2094                pxmitpriv->ack_tx = false;
2095                mutex_unlock(&pxmitpriv->ack_tx_mutex);
2096        }
2097
2098        return ret;
2099}
2100
2101static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2102{
2103        u8 *ssid_ie;
2104        signed int ssid_len_ori;
2105        int len_diff = 0;
2106
2107        ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
2108
2109        if (ssid_ie && ssid_len_ori > 0) {
2110                switch (hidden_ssid_mode) {
2111                case 1:
2112                {
2113                        u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
2114                        u32 remain_len = 0;
2115
2116                        remain_len = ies_len - (next_ie-ies);
2117
2118                        ssid_ie[1] = 0;
2119                        memcpy(ssid_ie+2, next_ie, remain_len);
2120                        len_diff -= ssid_len_ori;
2121
2122                        break;
2123                }
2124                case 2:
2125                        memset(&ssid_ie[2], 0, ssid_len_ori);
2126                        break;
2127                default:
2128                        break;
2129        }
2130        }
2131
2132        return len_diff;
2133}
2134
2135void issue_beacon(struct adapter *padapter, int timeout_ms)
2136{
2137        struct xmit_frame       *pmgntframe;
2138        struct pkt_attrib       *pattrib;
2139        unsigned char *pframe;
2140        struct ieee80211_hdr *pwlanhdr;
2141        __le16 *fctrl;
2142        unsigned int    rate_len;
2143        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2144        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2145        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2146        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2147        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
2148
2149        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2150        if (!pmgntframe)
2151                return;
2152
2153        spin_lock_bh(&pmlmepriv->bcn_update_lock);
2154
2155        /* update attribute */
2156        pattrib = &pmgntframe->attrib;
2157        update_mgntframe_attrib(padapter, pattrib);
2158        pattrib->qsel = 0x10;
2159
2160        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2161
2162        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2163        pwlanhdr = (struct ieee80211_hdr *)pframe;
2164
2165
2166        fctrl = &(pwlanhdr->frame_control);
2167        *(fctrl) = 0;
2168
2169        eth_broadcast_addr(pwlanhdr->addr1);
2170        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2171        memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
2172
2173        SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
2174        /* pmlmeext->mgnt_seq++; */
2175        SetFrameSubType(pframe, WIFI_BEACON);
2176
2177        pframe += sizeof(struct ieee80211_hdr_3addr);
2178        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2179
2180        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2181                {
2182                        int len_diff;
2183
2184                        memcpy(pframe, cur_network->IEs, cur_network->IELength);
2185                        len_diff = update_hidden_ssid(pframe+_BEACON_IE_OFFSET_,
2186                                                      cur_network->IELength-_BEACON_IE_OFFSET_,
2187                                                      pmlmeinfo->hidden_ssid_mode);
2188                        pframe += (cur_network->IELength+len_diff);
2189                        pattrib->pktlen += (cur_network->IELength+len_diff);
2190                }
2191
2192                {
2193                        u8 *wps_ie;
2194                        uint wps_ielen;
2195                        u8 sr = 0;
2196
2197                        wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
2198                                pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
2199                        if (wps_ie && wps_ielen > 0) {
2200                                rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
2201                        }
2202                        if (sr != 0)
2203                                set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2204                        else
2205                                _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2206                }
2207
2208                goto _issue_bcn;
2209
2210        }
2211
2212        /* below for ad-hoc mode */
2213
2214        /* timestamp will be inserted by hardware */
2215        pframe += 8;
2216        pattrib->pktlen += 8;
2217
2218        /*  beacon interval: 2 bytes */
2219
2220        memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
2221
2222        pframe += 2;
2223        pattrib->pktlen += 2;
2224
2225        /*  capability info: 2 bytes */
2226
2227        memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
2228
2229        pframe += 2;
2230        pattrib->pktlen += 2;
2231
2232        /*  SSID */
2233        pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
2234
2235        /*  supported rates... */
2236        rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
2237        pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
2238
2239        /*  DS parameter set */
2240        pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
2241
2242        /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
2243        {
2244                u8 erpinfo = 0;
2245                u32 ATIMWindow;
2246                /*  IBSS Parameter Set... */
2247                /* ATIMWindow = cur->Configuration.ATIMWindow; */
2248                ATIMWindow = 0;
2249                pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
2250
2251                /* ERP IE */
2252                pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen);
2253        }
2254
2255
2256        /*  EXTERNDED SUPPORTED RATE */
2257        if (rate_len > 8) {
2258                pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
2259        }
2260
2261
2262        /* todo:HT for adhoc */
2263
2264_issue_bcn:
2265
2266        pmlmepriv->update_bcn = false;
2267
2268        spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2269
2270        if ((pattrib->pktlen + TXDESC_SIZE) > 512)
2271                return;
2272
2273        pattrib->last_txcmdsz = pattrib->pktlen;
2274
2275        if (timeout_ms > 0)
2276                dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
2277        else
2278                dump_mgntframe(padapter, pmgntframe);
2279
2280}
2281
2282void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
2283{
2284        struct xmit_frame                       *pmgntframe;
2285        struct pkt_attrib                       *pattrib;
2286        unsigned char                           *pframe;
2287        struct ieee80211_hdr    *pwlanhdr;
2288        __le16 *fctrl;
2289        unsigned char                           *mac, *bssid;
2290        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2291
2292        u8 *pwps_ie;
2293        uint wps_ielen;
2294        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2295        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2296        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2297        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
2298        unsigned int    rate_len;
2299
2300        if (da == NULL)
2301                return;
2302
2303        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2304        if (!pmgntframe)
2305                return;
2306
2307        /* update attribute */
2308        pattrib = &pmgntframe->attrib;
2309        update_mgntframe_attrib(padapter, pattrib);
2310
2311        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2312
2313        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2314        pwlanhdr = (struct ieee80211_hdr *)pframe;
2315
2316        mac = myid(&(padapter->eeprompriv));
2317        bssid = cur_network->MacAddress;
2318
2319        fctrl = &(pwlanhdr->frame_control);
2320        *(fctrl) = 0;
2321        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
2322        memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
2323        memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
2324
2325        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2326        pmlmeext->mgnt_seq++;
2327        SetFrameSubType(fctrl, WIFI_PROBERSP);
2328
2329        pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2330        pattrib->pktlen = pattrib->hdrlen;
2331        pframe += pattrib->hdrlen;
2332
2333
2334        if (cur_network->IELength > MAX_IE_SZ)
2335                return;
2336
2337        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2338                pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
2339
2340                /* inerset & update wps_probe_resp_ie */
2341                if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) {
2342                        uint wps_offset, remainder_ielen;
2343                        u8 *premainder_ie;
2344
2345                        wps_offset = (uint)(pwps_ie - cur_network->IEs);
2346
2347                        premainder_ie = pwps_ie + wps_ielen;
2348
2349                        remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
2350
2351                        memcpy(pframe, cur_network->IEs, wps_offset);
2352                        pframe += wps_offset;
2353                        pattrib->pktlen += wps_offset;
2354
2355                        wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
2356                        if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
2357                                memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
2358                                pframe += wps_ielen+2;
2359                                pattrib->pktlen += wps_ielen+2;
2360                        }
2361
2362                        if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
2363                                memcpy(pframe, premainder_ie, remainder_ielen);
2364                                pframe += remainder_ielen;
2365                                pattrib->pktlen += remainder_ielen;
2366                        }
2367                } else {
2368                        memcpy(pframe, cur_network->IEs, cur_network->IELength);
2369                        pframe += cur_network->IELength;
2370                        pattrib->pktlen += cur_network->IELength;
2371                }
2372
2373                /* retrieve SSID IE from cur_network->Ssid */
2374                {
2375                        u8 *ssid_ie;
2376                        signed int ssid_ielen;
2377                        signed int ssid_ielen_diff;
2378                        u8 *buf;
2379                        u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr);
2380
2381                        buf = rtw_zmalloc(MAX_IE_SZ);
2382                        if (!buf)
2383                                return;
2384
2385                        ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, WLAN_EID_SSID, &ssid_ielen,
2386                                (pframe-ies)-_FIXED_IE_LENGTH_);
2387
2388                        ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
2389
2390                        if (ssid_ie &&  cur_network->Ssid.SsidLength) {
2391                                uint remainder_ielen;
2392                                u8 *remainder_ie;
2393
2394                                remainder_ie = ssid_ie+2;
2395                                remainder_ielen = (pframe-remainder_ie);
2396
2397                                if (remainder_ielen > MAX_IE_SZ) {
2398                                        netdev_warn(padapter->pnetdev,
2399                                                    FUNC_ADPT_FMT " remainder_ielen > MAX_IE_SZ\n",
2400                                                    FUNC_ADPT_ARG(padapter));
2401                                        remainder_ielen = MAX_IE_SZ;
2402                                }
2403
2404                                memcpy(buf, remainder_ie, remainder_ielen);
2405                                memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
2406                                *(ssid_ie+1) = cur_network->Ssid.SsidLength;
2407                                memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
2408
2409                                pframe += ssid_ielen_diff;
2410                                pattrib->pktlen += ssid_ielen_diff;
2411                        }
2412                        kfree (buf);
2413                }
2414        } else {
2415                /* timestamp will be inserted by hardware */
2416                pframe += 8;
2417                pattrib->pktlen += 8;
2418
2419                /*  beacon interval: 2 bytes */
2420
2421                memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
2422
2423                pframe += 2;
2424                pattrib->pktlen += 2;
2425
2426                /*  capability info: 2 bytes */
2427
2428                memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
2429
2430                pframe += 2;
2431                pattrib->pktlen += 2;
2432
2433                /* below for ad-hoc mode */
2434
2435                /*  SSID */
2436                pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
2437
2438                /*  supported rates... */
2439                rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
2440                pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
2441
2442                /*  DS parameter set */
2443                pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
2444
2445                if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
2446                        u8 erpinfo = 0;
2447                        u32 ATIMWindow;
2448                        /*  IBSS Parameter Set... */
2449                        /* ATIMWindow = cur->Configuration.ATIMWindow; */
2450                        ATIMWindow = 0;
2451                        pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
2452
2453                        /* ERP IE */
2454                        pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen);
2455                }
2456
2457
2458                /*  EXTERNDED SUPPORTED RATE */
2459                if (rate_len > 8) {
2460                        pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
2461                }
2462
2463
2464                /* todo:HT for adhoc */
2465
2466        }
2467
2468        pattrib->last_txcmdsz = pattrib->pktlen;
2469
2470
2471        dump_mgntframe(padapter, pmgntframe);
2472
2473        return;
2474
2475}
2476
2477static int _issue_probereq(struct adapter *padapter,
2478                           struct ndis_802_11_ssid *pssid,
2479                           u8 *da, u8 ch, bool append_wps, bool wait_ack)
2480{
2481        int ret = _FAIL;
2482        struct xmit_frame               *pmgntframe;
2483        struct pkt_attrib               *pattrib;
2484        unsigned char           *pframe;
2485        struct ieee80211_hdr    *pwlanhdr;
2486        __le16 *fctrl;
2487        unsigned char           *mac;
2488        unsigned char           bssrate[NumRates];
2489        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
2490        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2491        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2492        int     bssrate_len = 0;
2493
2494        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2495        if (!pmgntframe)
2496                goto exit;
2497
2498        /* update attribute */
2499        pattrib = &pmgntframe->attrib;
2500        update_mgntframe_attrib(padapter, pattrib);
2501
2502
2503        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2504
2505        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2506        pwlanhdr = (struct ieee80211_hdr *)pframe;
2507
2508        mac = myid(&(padapter->eeprompriv));
2509
2510        fctrl = &(pwlanhdr->frame_control);
2511        *(fctrl) = 0;
2512
2513        if (da) {
2514                /*      unicast probe request frame */
2515                memcpy(pwlanhdr->addr1, da, ETH_ALEN);
2516                memcpy(pwlanhdr->addr3, da, ETH_ALEN);
2517        } else {
2518                /*      broadcast probe request frame */
2519                eth_broadcast_addr(pwlanhdr->addr1);
2520                eth_broadcast_addr(pwlanhdr->addr3);
2521        }
2522
2523        memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
2524
2525        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2526        pmlmeext->mgnt_seq++;
2527        SetFrameSubType(pframe, WIFI_PROBEREQ);
2528
2529        pframe += sizeof(struct ieee80211_hdr_3addr);
2530        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2531
2532        if (pssid)
2533                pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
2534        else
2535                pframe = rtw_set_ie(pframe, WLAN_EID_SSID, 0, NULL, &(pattrib->pktlen));
2536
2537        get_rate_set(padapter, bssrate, &bssrate_len);
2538
2539        if (bssrate_len > 8) {
2540                pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen));
2541                pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
2542        } else {
2543                pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen));
2544        }
2545
2546        if (ch)
2547                pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, &ch, &pattrib->pktlen);
2548
2549        if (append_wps) {
2550                /* add wps_ie for wps2.0 */
2551                if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
2552                        memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
2553                        pframe += pmlmepriv->wps_probe_req_ie_len;
2554                        pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2555                }
2556        }
2557
2558        pattrib->last_txcmdsz = pattrib->pktlen;
2559
2560        if (wait_ack) {
2561                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
2562        } else {
2563                dump_mgntframe(padapter, pmgntframe);
2564                ret = _SUCCESS;
2565        }
2566
2567exit:
2568        return ret;
2569}
2570
2571inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
2572{
2573        _issue_probereq(padapter, pssid, da, 0, 1, false);
2574}
2575
2576int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps,
2577        int try_cnt, int wait_ms)
2578{
2579        int ret;
2580        int i = 0;
2581
2582        do {
2583                ret = _issue_probereq(padapter, pssid, da, ch, append_wps,
2584                                      wait_ms > 0);
2585
2586                i++;
2587
2588                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2589                        break;
2590
2591                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2592                        msleep(wait_ms);
2593
2594        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2595
2596        if (ret != _FAIL) {
2597                ret = _SUCCESS;
2598                #ifndef DBG_XMIT_ACK
2599                goto exit;
2600                #endif
2601        }
2602
2603exit:
2604        return ret;
2605}
2606
2607/*  if psta == NULL, indicate we are station(client) now... */
2608void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
2609{
2610        struct xmit_frame                       *pmgntframe;
2611        struct pkt_attrib                       *pattrib;
2612        unsigned char                           *pframe;
2613        struct ieee80211_hdr    *pwlanhdr;
2614        __le16 *fctrl;
2615        unsigned int                                    val32;
2616        unsigned short                          val16;
2617        int use_shared_key = 0;
2618        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
2619        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2620        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2621        __le16 le_tmp;
2622
2623        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2624        if (pmgntframe == NULL)
2625                return;
2626
2627        /* update attribute */
2628        pattrib = &pmgntframe->attrib;
2629        update_mgntframe_attrib(padapter, pattrib);
2630
2631        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2632
2633        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2634        pwlanhdr = (struct ieee80211_hdr *)pframe;
2635
2636        fctrl = &(pwlanhdr->frame_control);
2637        *(fctrl) = 0;
2638
2639        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2640        pmlmeext->mgnt_seq++;
2641        SetFrameSubType(pframe, WIFI_AUTH);
2642
2643        pframe += sizeof(struct ieee80211_hdr_3addr);
2644        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2645
2646
2647        if (psta) { /*  for AP mode */
2648                memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
2649                memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2650                memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
2651
2652                /*  setting auth algo number */
2653                val16 = (u16)psta->authalg;
2654
2655                if (status != WLAN_STATUS_SUCCESS)
2656                        val16 = 0;
2657
2658                if (val16)
2659                        use_shared_key = 1;
2660
2661                le_tmp = cpu_to_le16(val16);
2662
2663                pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2664
2665                /*  setting auth seq number */
2666                val16 = (u16)psta->auth_seq;
2667                le_tmp = cpu_to_le16(val16);
2668                pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2669
2670                /*  setting status code... */
2671                val16 = status;
2672                le_tmp = cpu_to_le16(val16);
2673                pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2674
2675                /*  added challenging text... */
2676                if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
2677                        pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, psta->chg_txt, &(pattrib->pktlen));
2678
2679        } else {
2680                memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
2681                memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
2682                memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
2683
2684                /*  setting auth algo number */
2685                val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/*  0:OPEN System, 1:Shared key */
2686                if (val16) {
2687                        use_shared_key = 1;
2688                }
2689                le_tmp = cpu_to_le16(val16);
2690
2691                /* setting IV for auth seq #3 */
2692                if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
2693                        __le32 le_tmp32;
2694
2695                        val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
2696                        le_tmp32 = cpu_to_le32(val32);
2697                        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen));
2698
2699                        pattrib->iv_len = 4;
2700                }
2701
2702                pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2703
2704                /*  setting auth seq number */
2705                le_tmp = cpu_to_le16(pmlmeinfo->auth_seq);
2706                pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2707
2708
2709                /*  setting status code... */
2710                le_tmp = cpu_to_le16(status);
2711                pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2712
2713                /*  then checking to see if sending challenging text... */
2714                if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
2715                        pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
2716
2717                        SetPrivacy(fctrl);
2718
2719                        pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2720
2721                        pattrib->encrypt = _WEP40_;
2722
2723                        pattrib->icv_len = 4;
2724
2725                        pattrib->pktlen += pattrib->icv_len;
2726
2727                }
2728
2729        }
2730
2731        pattrib->last_txcmdsz = pattrib->pktlen;
2732
2733        rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
2734        dump_mgntframe(padapter, pmgntframe);
2735}
2736
2737
2738void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
2739{
2740        struct xmit_frame       *pmgntframe;
2741        struct ieee80211_hdr    *pwlanhdr;
2742        struct pkt_attrib *pattrib;
2743        unsigned char *pbuf, *pframe;
2744        unsigned short val;
2745        __le16 *fctrl;
2746        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2747        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2748        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2749        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2750        struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
2751        u8 *ie = pnetwork->IEs;
2752        __le16 lestatus, le_tmp;
2753
2754        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2755        if (pmgntframe == NULL)
2756                return;
2757
2758        /* update attribute */
2759        pattrib = &pmgntframe->attrib;
2760        update_mgntframe_attrib(padapter, pattrib);
2761
2762
2763        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2764
2765        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2766        pwlanhdr = (struct ieee80211_hdr *)pframe;
2767
2768        fctrl = &(pwlanhdr->frame_control);
2769        *(fctrl) = 0;
2770
2771        memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
2772        memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
2773        memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
2774
2775
2776        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2777        pmlmeext->mgnt_seq++;
2778        if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
2779                SetFrameSubType(pwlanhdr, pkt_type);
2780        else
2781                return;
2782
2783        pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2784        pattrib->pktlen += pattrib->hdrlen;
2785        pframe += pattrib->hdrlen;
2786
2787        /* capability */
2788        val = *(unsigned short *)rtw_get_capability_from_ie(ie);
2789
2790        pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &(pattrib->pktlen));
2791
2792        lestatus = cpu_to_le16(status);
2793        pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &(pattrib->pktlen));
2794
2795        le_tmp = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
2796        pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
2797
2798        if (pstat->bssratelen <= 8) {
2799                pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
2800        } else {
2801                pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, pstat->bssrateset, &(pattrib->pktlen));
2802                pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
2803        }
2804
2805        if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
2806                uint ie_len = 0;
2807
2808                /* FILL HT CAP INFO IE */
2809                /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
2810                pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
2811                if (pbuf && ie_len > 0) {
2812                        memcpy(pframe, pbuf, ie_len+2);
2813                        pframe += (ie_len+2);
2814                        pattrib->pktlen += (ie_len+2);
2815                }
2816
2817                /* FILL HT ADD INFO IE */
2818                /* p = hostapd_eid_ht_operation(hapd, p); */
2819                pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
2820                if (pbuf && ie_len > 0) {
2821                        memcpy(pframe, pbuf, ie_len+2);
2822                        pframe += (ie_len+2);
2823                        pattrib->pktlen += (ie_len+2);
2824                }
2825
2826        }
2827
2828        /* FILL WMM IE */
2829        if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
2830                uint ie_len = 0;
2831                unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
2832
2833                for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
2834                        pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
2835                        if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
2836                                memcpy(pframe, pbuf, ie_len+2);
2837                                pframe += (ie_len+2);
2838                                pattrib->pktlen += (ie_len+2);
2839
2840                                break;
2841                        }
2842
2843                        if ((pbuf == NULL) || (ie_len == 0)) {
2844                                break;
2845                        }
2846                }
2847
2848        }
2849
2850        if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
2851                pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen));
2852        }
2853
2854        /* add WPS IE ie for wps 2.0 */
2855        if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
2856                memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
2857
2858                pframe += pmlmepriv->wps_assoc_resp_ie_len;
2859                pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
2860        }
2861
2862        pattrib->last_txcmdsz = pattrib->pktlen;
2863
2864        dump_mgntframe(padapter, pmgntframe);
2865}
2866
2867void issue_assocreq(struct adapter *padapter)
2868{
2869        int ret = _FAIL;
2870        struct xmit_frame                               *pmgntframe;
2871        struct pkt_attrib                               *pattrib;
2872        unsigned char                           *pframe;
2873        struct ieee80211_hdr                    *pwlanhdr;
2874        __le16 *fctrl;
2875        __le16 val16;
2876        unsigned int                                    i, j, index = 0;
2877        unsigned char bssrate[NumRates], sta_bssrate[NumRates];
2878        struct ndis_80211_var_ie *pIE;
2879        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
2880        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2881        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2882        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2883        int     bssrate_len = 0, sta_bssrate_len = 0;
2884        u8 vs_ie_length = 0;
2885
2886        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2887        if (pmgntframe == NULL)
2888                goto exit;
2889
2890        /* update attribute */
2891        pattrib = &pmgntframe->attrib;
2892        update_mgntframe_attrib(padapter, pattrib);
2893
2894        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2895
2896        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2897        pwlanhdr = (struct ieee80211_hdr *)pframe;
2898
2899        fctrl = &(pwlanhdr->frame_control);
2900        *(fctrl) = 0;
2901        memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
2902        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2903        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
2904
2905        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2906        pmlmeext->mgnt_seq++;
2907        SetFrameSubType(pframe, WIFI_ASSOCREQ);
2908
2909        pframe += sizeof(struct ieee80211_hdr_3addr);
2910        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2911
2912        /* caps */
2913        memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
2914
2915        pframe += 2;
2916        pattrib->pktlen += 2;
2917
2918        /* listen interval */
2919        /* todo: listen interval for power saving */
2920        val16 = cpu_to_le16(3);
2921        memcpy(pframe, (unsigned char *)&val16, 2);
2922        pframe += 2;
2923        pattrib->pktlen += 2;
2924
2925        /* SSID */
2926        pframe = rtw_set_ie(pframe, WLAN_EID_SSID,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
2927
2928        /* supported rate & extended supported rate */
2929
2930        /*  Check if the AP's supported rates are also supported by STA. */
2931        get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
2932
2933        if (pmlmeext->cur_channel == 14) /*  for JAPAN, channel 14 can only uses B Mode(CCK) */
2934                sta_bssrate_len = 4;
2935
2936
2937        /* for (i = 0; i < sta_bssrate_len; i++) { */
2938        /*  */
2939
2940        for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
2941                if (pmlmeinfo->network.SupportedRates[i] == 0)
2942                        break;
2943        }
2944
2945
2946        for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
2947                if (pmlmeinfo->network.SupportedRates[i] == 0)
2948                        break;
2949
2950
2951                /*  Check if the AP's supported rates are also supported by STA. */
2952                for (j = 0; j < sta_bssrate_len; j++) {
2953                         /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
2954                        if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK)
2955                                        == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK))
2956                                break;
2957                }
2958
2959                if (j != sta_bssrate_len)
2960                        /*  the rate is supported by STA */
2961                        bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
2962        }
2963
2964        bssrate_len = index;
2965
2966        if (bssrate_len == 0) {
2967                rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
2968                rtw_free_xmitframe(pxmitpriv, pmgntframe);
2969                goto exit; /* don't connect to AP if no joint supported rate */
2970        }
2971
2972
2973        if (bssrate_len > 8) {
2974                pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen));
2975                pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
2976        } else
2977                pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen));
2978
2979        /* vendor specific IE, such as WPA, WMM, WPS */
2980        for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) {
2981                pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i);
2982
2983                switch (pIE->ElementID) {
2984                case WLAN_EID_VENDOR_SPECIFIC:
2985                        if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
2986                                        (!memcmp(pIE->data, WMM_OUI, 4)) ||
2987                                        (!memcmp(pIE->data, WPS_OUI, 4))) {
2988                                vs_ie_length = pIE->Length;
2989                                if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) {
2990                                        /* Commented by Kurt 20110629
2991                                         * In some older APs, WPS handshake
2992                                         * would be fail if we append vendor
2993                                         * extensions information to AP
2994                                         */
2995
2996                                        vs_ie_length = 14;
2997                                }
2998
2999                                pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, vs_ie_length, pIE->data, &(pattrib->pktlen));
3000                        }
3001                        break;
3002
3003                case WLAN_EID_RSN:
3004                        pframe = rtw_set_ie(pframe, WLAN_EID_RSN, pIE->Length, pIE->data, &(pattrib->pktlen));
3005                        break;
3006                case WLAN_EID_HT_CAPABILITY:
3007                        if (padapter->mlmepriv.htpriv.ht_option) {
3008                                if (!(is_ap_in_tkip(padapter))) {
3009                                        memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
3010                                        pframe = rtw_set_ie(pframe, WLAN_EID_HT_CAPABILITY, pIE->Length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
3011                                }
3012                        }
3013                        break;
3014
3015                case WLAN_EID_EXT_CAPABILITY:
3016                        if (padapter->mlmepriv.htpriv.ht_option)
3017                                pframe = rtw_set_ie(pframe, WLAN_EID_EXT_CAPABILITY, pIE->Length, pIE->data, &(pattrib->pktlen));
3018                        break;
3019                default:
3020                        break;
3021                }
3022
3023                i += (pIE->Length + 2);
3024        }
3025
3026        if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
3027                pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen));
3028
3029
3030        pattrib->last_txcmdsz = pattrib->pktlen;
3031        dump_mgntframe(padapter, pmgntframe);
3032
3033        ret = _SUCCESS;
3034
3035exit:
3036        if (ret == _SUCCESS)
3037                rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
3038        else
3039                rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
3040}
3041
3042/* when wait_ack is true, this function should be called at process context */
3043static int _issue_nulldata(struct adapter *padapter, unsigned char *da,
3044                           unsigned int power_mode, bool wait_ack)
3045{
3046        int ret = _FAIL;
3047        struct xmit_frame                       *pmgntframe;
3048        struct pkt_attrib                       *pattrib;
3049        unsigned char                           *pframe;
3050        struct ieee80211_hdr    *pwlanhdr;
3051        __le16 *fctrl;
3052        struct xmit_priv *pxmitpriv;
3053        struct mlme_ext_priv *pmlmeext;
3054        struct mlme_ext_info *pmlmeinfo;
3055
3056        if (!padapter)
3057                goto exit;
3058
3059        pxmitpriv = &(padapter->xmitpriv);
3060        pmlmeext = &(padapter->mlmeextpriv);
3061        pmlmeinfo = &(pmlmeext->mlmext_info);
3062
3063        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3064        if (pmgntframe == NULL)
3065                goto exit;
3066
3067        /* update attribute */
3068        pattrib = &pmgntframe->attrib;
3069        update_mgntframe_attrib(padapter, pattrib);
3070        pattrib->retry_ctrl = false;
3071
3072        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3073
3074        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3075        pwlanhdr = (struct ieee80211_hdr *)pframe;
3076
3077        fctrl = &(pwlanhdr->frame_control);
3078        *(fctrl) = 0;
3079
3080        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3081                SetFrDs(fctrl);
3082        else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3083                SetToDs(fctrl);
3084
3085        if (power_mode)
3086                SetPwrMgt(fctrl);
3087
3088        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3089        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3090        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3091
3092        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3093        pmlmeext->mgnt_seq++;
3094        SetFrameSubType(pframe, WIFI_DATA_NULL);
3095
3096        pframe += sizeof(struct ieee80211_hdr_3addr);
3097        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3098
3099        pattrib->last_txcmdsz = pattrib->pktlen;
3100
3101        if (wait_ack) {
3102                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3103        } else {
3104                dump_mgntframe(padapter, pmgntframe);
3105                ret = _SUCCESS;
3106        }
3107
3108exit:
3109        return ret;
3110}
3111
3112/*
3113 * [IMPORTANT] Don't call this function in interrupt context
3114 *
3115 * When wait_ms > 0, this function should be called at process context
3116 * da == NULL for station mode
3117 */
3118int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
3119{
3120        int ret;
3121        int i = 0;
3122        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3123        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3124        struct sta_info *psta;
3125
3126
3127        /* da == NULL, assume it's null data for sta to ap*/
3128        if (!da)
3129                da = get_my_bssid(&(pmlmeinfo->network));
3130
3131        psta = rtw_get_stainfo(&padapter->stapriv, da);
3132        if (psta) {
3133                if (power_mode)
3134                        rtw_hal_macid_sleep(padapter, psta->mac_id);
3135                else
3136                        rtw_hal_macid_wakeup(padapter, psta->mac_id);
3137        } else {
3138                rtw_warn_on(1);
3139        }
3140
3141        do {
3142                ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0);
3143
3144                i++;
3145
3146                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3147                        break;
3148
3149                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3150                        msleep(wait_ms);
3151
3152        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3153
3154        if (ret != _FAIL) {
3155                ret = _SUCCESS;
3156                #ifndef DBG_XMIT_ACK
3157                goto exit;
3158                #endif
3159        }
3160
3161exit:
3162        return ret;
3163}
3164
3165/*
3166 * [IMPORTANT] This function run in interrupt context
3167 *
3168 * The null data packet would be sent without power bit,
3169 * and not guarantee success.
3170 */
3171s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da)
3172{
3173        struct mlme_ext_priv *pmlmeext;
3174        struct mlme_ext_info *pmlmeinfo;
3175
3176
3177        pmlmeext = &padapter->mlmeextpriv;
3178        pmlmeinfo = &pmlmeext->mlmext_info;
3179
3180        /* da == NULL, assume it's null data for sta to ap*/
3181        if (!da)
3182                da = get_my_bssid(&(pmlmeinfo->network));
3183
3184        return _issue_nulldata(padapter, da, 0, false);
3185}
3186
3187/* when wait_ack is true, this function should be called at process context */
3188static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
3189                               u16 tid, bool wait_ack)
3190{
3191        int ret = _FAIL;
3192        struct xmit_frame                       *pmgntframe;
3193        struct pkt_attrib                       *pattrib;
3194        unsigned char                           *pframe;
3195        struct ieee80211_hdr    *pwlanhdr;
3196        __le16 *fctrl;
3197        u16 *qc;
3198        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3199        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3200        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3201
3202        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3203        if (pmgntframe == NULL)
3204                goto exit;
3205
3206        /* update attribute */
3207        pattrib = &pmgntframe->attrib;
3208        update_mgntframe_attrib(padapter, pattrib);
3209
3210        pattrib->hdrlen += 2;
3211        pattrib->qos_en = true;
3212        pattrib->eosp = 1;
3213        pattrib->ack_policy = 0;
3214        pattrib->mdata = 0;
3215
3216        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3217
3218        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3219        pwlanhdr = (struct ieee80211_hdr *)pframe;
3220
3221        fctrl = &(pwlanhdr->frame_control);
3222        *(fctrl) = 0;
3223
3224        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3225                SetFrDs(fctrl);
3226        else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3227                SetToDs(fctrl);
3228
3229        if (pattrib->mdata)
3230                SetMData(fctrl);
3231
3232        qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
3233
3234        SetPriority(qc, tid);
3235
3236        SetEOSP(qc, pattrib->eosp);
3237
3238        SetAckpolicy(qc, pattrib->ack_policy);
3239
3240        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3241        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3242        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3243
3244        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3245        pmlmeext->mgnt_seq++;
3246        SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
3247
3248        pframe += sizeof(struct ieee80211_qos_hdr);
3249        pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3250
3251        pattrib->last_txcmdsz = pattrib->pktlen;
3252
3253        if (wait_ack) {
3254                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3255        } else {
3256                dump_mgntframe(padapter, pmgntframe);
3257                ret = _SUCCESS;
3258        }
3259
3260exit:
3261        return ret;
3262}
3263
3264/* when wait_ms >0 , this function should be called at process context */
3265/* da == NULL for station mode */
3266int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
3267{
3268        int ret;
3269        int i = 0;
3270        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3271        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3272
3273        /* da == NULL, assume it's null data for sta to ap*/
3274        if (!da)
3275                da = get_my_bssid(&(pmlmeinfo->network));
3276
3277        do {
3278                ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0);
3279
3280                i++;
3281
3282                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3283                        break;
3284
3285                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3286                        msleep(wait_ms);
3287
3288        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3289
3290        if (ret != _FAIL) {
3291                ret = _SUCCESS;
3292                #ifndef DBG_XMIT_ACK
3293                goto exit;
3294                #endif
3295        }
3296
3297exit:
3298        return ret;
3299}
3300
3301static int _issue_deauth(struct adapter *padapter, unsigned char *da,
3302                         unsigned short reason, bool wait_ack)
3303{
3304        struct xmit_frame                       *pmgntframe;
3305        struct pkt_attrib                       *pattrib;
3306        unsigned char                           *pframe;
3307        struct ieee80211_hdr    *pwlanhdr;
3308        __le16 *fctrl;
3309        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3310        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3311        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3312        int ret = _FAIL;
3313        __le16 le_tmp;
3314
3315        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3316        if (pmgntframe == NULL) {
3317                goto exit;
3318        }
3319
3320        /* update attribute */
3321        pattrib = &pmgntframe->attrib;
3322        update_mgntframe_attrib(padapter, pattrib);
3323        pattrib->retry_ctrl = false;
3324
3325        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3326
3327        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3328        pwlanhdr = (struct ieee80211_hdr *)pframe;
3329
3330        fctrl = &(pwlanhdr->frame_control);
3331        *(fctrl) = 0;
3332
3333        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3334        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3335        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3336
3337        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3338        pmlmeext->mgnt_seq++;
3339        SetFrameSubType(pframe, WIFI_DEAUTH);
3340
3341        pframe += sizeof(struct ieee80211_hdr_3addr);
3342        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3343
3344        le_tmp = cpu_to_le16(reason);
3345        pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3346
3347        pattrib->last_txcmdsz = pattrib->pktlen;
3348
3349
3350        if (wait_ack) {
3351                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3352        } else {
3353                dump_mgntframe(padapter, pmgntframe);
3354                ret = _SUCCESS;
3355        }
3356
3357exit:
3358        return ret;
3359}
3360
3361int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
3362{
3363        return _issue_deauth(padapter, da, reason, false);
3364}
3365
3366int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
3367        int wait_ms)
3368{
3369        int ret;
3370        int i = 0;
3371
3372        do {
3373                ret = _issue_deauth(padapter, da, reason, wait_ms > 0);
3374
3375                i++;
3376
3377                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3378                        break;
3379
3380                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3381                        mdelay(wait_ms);
3382
3383        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3384
3385        if (ret != _FAIL) {
3386                ret = _SUCCESS;
3387                #ifndef DBG_XMIT_ACK
3388                goto exit;
3389                #endif
3390        }
3391
3392exit:
3393        return ret;
3394}
3395
3396void issue_action_SA_Query(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid)
3397{
3398        u8 category = RTW_WLAN_CATEGORY_SA_QUERY;
3399        struct xmit_frame               *pmgntframe;
3400        struct pkt_attrib               *pattrib;
3401        u8                      *pframe;
3402        struct ieee80211_hdr    *pwlanhdr;
3403        __le16 *fctrl;
3404        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3405        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3406        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3407        __le16 le_tmp;
3408
3409        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3410        if (!pmgntframe)
3411                return;
3412
3413        /* update attribute */
3414        pattrib = &pmgntframe->attrib;
3415        update_mgntframe_attrib(padapter, pattrib);
3416
3417        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3418
3419        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3420        pwlanhdr = (struct ieee80211_hdr *)pframe;
3421
3422        fctrl = &(pwlanhdr->frame_control);
3423        *(fctrl) = 0;
3424
3425        if (raddr)
3426                memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3427        else
3428                memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3429        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3430        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3431
3432        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3433        pmlmeext->mgnt_seq++;
3434        SetFrameSubType(pframe, WIFI_ACTION);
3435
3436        pframe += sizeof(struct ieee80211_hdr_3addr);
3437        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3438
3439        pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
3440        pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
3441
3442        switch (action) {
3443        case 0: /* SA Query req */
3444                pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);
3445                pmlmeext->sa_query_seq++;
3446                /* send sa query request to AP, AP should reply sa query response in 1 second */
3447                set_sa_query_timer(pmlmeext, 1000);
3448                break;
3449
3450        case 1: /* SA Query rsp */
3451                le_tmp = cpu_to_le16(tid);
3452                pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
3453                break;
3454        default:
3455                break;
3456        }
3457
3458        pattrib->last_txcmdsz = pattrib->pktlen;
3459
3460        dump_mgntframe(padapter, pmgntframe);
3461}
3462
3463void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
3464{
3465        u8 category = RTW_WLAN_CATEGORY_BACK;
3466        u16 start_seq;
3467        u16 BA_para_set;
3468        u16 reason_code;
3469        u16 BA_timeout_value;
3470        u16 BA_starting_seqctrl = 0;
3471        enum ieee80211_max_ampdu_length_exp max_rx_ampdu_factor;
3472        struct xmit_frame               *pmgntframe;
3473        struct pkt_attrib               *pattrib;
3474        u8                      *pframe;
3475        struct ieee80211_hdr    *pwlanhdr;
3476        __le16 *fctrl;
3477        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3478        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3479        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3480        struct sta_info         *psta;
3481        struct sta_priv         *pstapriv = &padapter->stapriv;
3482        struct registry_priv    *pregpriv = &padapter->registrypriv;
3483        __le16 le_tmp;
3484
3485        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3486        if (!pmgntframe)
3487                return;
3488
3489        /* update attribute */
3490        pattrib = &pmgntframe->attrib;
3491        update_mgntframe_attrib(padapter, pattrib);
3492
3493        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3494
3495        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3496        pwlanhdr = (struct ieee80211_hdr *)pframe;
3497
3498        fctrl = &(pwlanhdr->frame_control);
3499        *(fctrl) = 0;
3500
3501        /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
3502        memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3503        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3504        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3505
3506        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3507        pmlmeext->mgnt_seq++;
3508        SetFrameSubType(pframe, WIFI_ACTION);
3509
3510        pframe += sizeof(struct ieee80211_hdr_3addr);
3511        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3512
3513        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3514        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3515
3516        if (category == 3) {
3517                switch (action) {
3518                case 0: /* ADDBA req */
3519                        do {
3520                                pmlmeinfo->dialogToken++;
3521                        } while (pmlmeinfo->dialogToken == 0);
3522                        pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
3523
3524                        if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter)) {
3525                                /*  A-MSDU NOT Supported */
3526                                BA_para_set = 0;
3527                                /*  immediate Block Ack */
3528                                BA_para_set |= BIT(1) & IEEE80211_ADDBA_PARAM_POLICY_MASK;
3529                                /*  TID */
3530                                BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
3531                                /*  max buffer size is 8 MSDU */
3532                                BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3533                        } else {
3534                                BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
3535                        }
3536                        le_tmp = cpu_to_le16(BA_para_set);
3537                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3538
3539                        BA_timeout_value = 5000;/*  5ms */
3540                        le_tmp = cpu_to_le16(BA_timeout_value);
3541                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3542
3543                        /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */
3544                        psta = rtw_get_stainfo(pstapriv, raddr);
3545                        if (psta) {
3546                                start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
3547
3548                                psta->BA_starting_seqctrl[status & 0x07] = start_seq;
3549
3550                                BA_starting_seqctrl = start_seq << 4;
3551                        }
3552
3553                        le_tmp = cpu_to_le16(BA_starting_seqctrl);
3554                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3555                        break;
3556
3557                case 1: /* ADDBA rsp */
3558                        pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
3559                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
3560                        if (padapter->driver_rx_ampdu_factor != 0xFF)
3561                                max_rx_ampdu_factor =
3562                                  (enum ieee80211_max_ampdu_length_exp)padapter->driver_rx_ampdu_factor;
3563                        else
3564                                rtw_hal_get_def_var(padapter,
3565                                                    HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
3566
3567                        if (IEEE80211_HT_MAX_AMPDU_64K == max_rx_ampdu_factor)
3568                                BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
3569                        else if (IEEE80211_HT_MAX_AMPDU_32K == max_rx_ampdu_factor)
3570                                BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
3571                        else if (IEEE80211_HT_MAX_AMPDU_16K == max_rx_ampdu_factor)
3572                                BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
3573                        else if (IEEE80211_HT_MAX_AMPDU_8K == max_rx_ampdu_factor)
3574                                BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
3575                        else
3576                                BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
3577
3578                        if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter) &&
3579                            padapter->driver_rx_ampdu_factor == 0xFF) {
3580                                /*  max buffer size is 8 MSDU */
3581                                BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3582                                BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3583                        }
3584
3585                        if (pregpriv->ampdu_amsdu == 0)/* disabled */
3586                                le_tmp = cpu_to_le16(BA_para_set & ~BIT(0));
3587                        else if (pregpriv->ampdu_amsdu == 1)/* enabled */
3588                                le_tmp = cpu_to_le16(BA_para_set | BIT(0));
3589                        else /* auto */
3590                                le_tmp = cpu_to_le16(BA_para_set);
3591
3592                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3593                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
3594                        break;
3595                case 2:/* DELBA */
3596                        BA_para_set = (status & 0x1F) << 3;
3597                        le_tmp = cpu_to_le16(BA_para_set);
3598                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3599
3600                        reason_code = 37;
3601                        le_tmp = cpu_to_le16(reason_code);
3602                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3603                        break;
3604                default:
3605                        break;
3606                }
3607        }
3608
3609        pattrib->last_txcmdsz = pattrib->pktlen;
3610
3611        dump_mgntframe(padapter, pmgntframe);
3612}
3613
3614static void issue_action_BSSCoexistPacket(struct adapter *padapter)
3615{
3616        struct list_head                *plist, *phead;
3617        unsigned char category, action;
3618        struct xmit_frame                       *pmgntframe;
3619        struct pkt_attrib                       *pattrib;
3620        unsigned char                   *pframe;
3621        struct ieee80211_hdr    *pwlanhdr;
3622        __le16 *fctrl;
3623        struct  wlan_network    *pnetwork = NULL;
3624        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3625        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3626        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3627        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3628        struct __queue          *queue  = &(pmlmepriv->scanned_queue);
3629        u8 InfoContent[16] = {0};
3630        u8 ICS[8][15];
3631
3632        if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
3633                return;
3634
3635        if (true == pmlmeinfo->bwmode_updated)
3636                return;
3637
3638        category = RTW_WLAN_CATEGORY_PUBLIC;
3639        action = ACT_PUBLIC_BSSCOEXIST;
3640
3641        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3642        if (pmgntframe == NULL) {
3643                return;
3644        }
3645
3646        /* update attribute */
3647        pattrib = &pmgntframe->attrib;
3648        update_mgntframe_attrib(padapter, pattrib);
3649
3650        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3651
3652        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3653        pwlanhdr = (struct ieee80211_hdr *)pframe;
3654
3655        fctrl = &(pwlanhdr->frame_control);
3656        *(fctrl) = 0;
3657
3658        memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3659        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3660        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3661
3662        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3663        pmlmeext->mgnt_seq++;
3664        SetFrameSubType(pframe, WIFI_ACTION);
3665
3666        pframe += sizeof(struct ieee80211_hdr_3addr);
3667        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3668
3669        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3670        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3671
3672
3673        /*  */
3674        if (pmlmepriv->num_FortyMHzIntolerant > 0) {
3675                u8 iedata = 0;
3676
3677                iedata |= BIT(2);/* 20 MHz BSS Width Request */
3678
3679                pframe = rtw_set_ie(pframe, WLAN_EID_BSS_COEX_2040,  1, &iedata, &(pattrib->pktlen));
3680
3681        }
3682
3683
3684        /*  */
3685        memset(ICS, 0, sizeof(ICS));
3686        if (pmlmepriv->num_sta_no_ht > 0) {
3687                int i;
3688
3689                spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
3690
3691                phead = get_list_head(queue);
3692                plist = get_next(phead);
3693
3694                while (1) {
3695                        int len;
3696                        u8 *p;
3697                        struct wlan_bssid_ex *pbss_network;
3698
3699                        if (phead == plist)
3700                                break;
3701
3702                        pnetwork = container_of(plist, struct wlan_network, list);
3703
3704                        plist = get_next(plist);
3705
3706                        pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
3707
3708                        p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
3709                        if ((p == NULL) || (len == 0)) {/* non-HT */
3710
3711                                if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
3712                                        continue;
3713
3714                                ICS[0][pbss_network->Configuration.DSConfig] = 1;
3715
3716                                if (ICS[0][0] == 0)
3717                                        ICS[0][0] = 1;
3718                        }
3719
3720                }
3721
3722                spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
3723
3724
3725                for (i = 0; i < 8; i++) {
3726                        if (ICS[i][0] == 1) {
3727                                int j, k = 0;
3728
3729                                InfoContent[k] = i;
3730                                /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
3731                                k++;
3732
3733                                for (j = 1; j <= 14; j++) {
3734                                        if (ICS[i][j] == 1) {
3735                                                if (k < 16) {
3736                                                        InfoContent[k] = j; /* channel number */
3737                                                        /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
3738                                                        k++;
3739                                                }
3740                                        }
3741                                }
3742
3743                                pframe = rtw_set_ie(pframe, WLAN_EID_BSS_INTOLERANT_CHL_REPORT, k, InfoContent, &(pattrib->pktlen));
3744
3745                        }
3746
3747                }
3748
3749
3750        }
3751
3752
3753        pattrib->last_txcmdsz = pattrib->pktlen;
3754
3755        dump_mgntframe(padapter, pmgntframe);
3756}
3757
3758unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
3759{
3760        struct sta_priv *pstapriv = &padapter->stapriv;
3761        struct sta_info *psta = NULL;
3762        /* struct recv_reorder_ctrl *preorder_ctrl; */
3763        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3764        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3765        u16 tid;
3766
3767        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
3768                if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
3769                        return _SUCCESS;
3770
3771        psta = rtw_get_stainfo(pstapriv, addr);
3772        if (psta == NULL)
3773                return _SUCCESS;
3774
3775        if (initiator == 0) {/*  recipient */
3776                for (tid = 0; tid < MAXTID; tid++) {
3777                        if (psta->recvreorder_ctrl[tid].enable) {
3778                                issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
3779                                psta->recvreorder_ctrl[tid].enable = false;
3780                                psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
3781                        }
3782                }
3783        } else if (initiator == 1) {/*  originator */
3784                for (tid = 0; tid < MAXTID; tid++) {
3785                        if (psta