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 (is_supported_24g(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.ssid_length))
 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.mac_address, 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.ssid_length))
1026                        status = WLAN_STATUS_CHALLENGE_FAIL;
1027
1028                if (ie_len != cur->ssid.ssid_length)
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->element_id) {
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.supported_rates);
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->ie_length);
2185                        len_diff = update_hidden_ssid(pframe+_BEACON_IE_OFFSET_,
2186                                                      cur_network->ie_length-_BEACON_IE_OFFSET_,
2187                                                      pmlmeinfo->hidden_ssid_mode);
2188                        pframe += (cur_network->ie_length+len_diff);
2189                        pattrib->pktlen += (cur_network->ie_length+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.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
2234
2235        /*  supported rates... */
2236        rate_len = rtw_get_rateset_len(cur_network->supported_rates);
2237        pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->supported_rates, &pattrib->pktlen);
2238
2239        /*  DS parameter set */
2240        pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->configuration.ds_config), &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->supported_rates + 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->mac_address;
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->ie_length > 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->ie_length-_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->ie_length - 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->ie_length);
2369                        pframe += cur_network->ie_length;
2370                        pattrib->pktlen += cur_network->ie_length;
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.ssid_length - ssid_ielen;
2389
2390                        if (ssid_ie &&  cur_network->ssid.ssid_length) {
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.ssid_length;
2407                                memcpy(ssid_ie+2, cur_network->ssid.ssid, cur_network->ssid.ssid_length);
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.ssid_length, cur_network->ssid.ssid, &pattrib->pktlen);
2437
2438                /*  supported rates... */
2439                rate_len = rtw_get_rateset_len(cur_network->supported_rates);
2440                pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->supported_rates, &pattrib->pktlen);
2441
2442                /*  DS parameter set */
2443                pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->configuration.ds_config), &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->supported_rates + 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->ssid_length, 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->ie_length - _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->ie_length - _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->ie_length - _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.ssid_length, 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.supported_rates[i] == 0)
2942                        break;
2943        }
2944
2945
2946        for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
2947                if (pmlmeinfo->network.supported_rates[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.supported_rates[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.supported_rates[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.ie_length;) {
2981                pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.ies + i);
2982
2983                switch (pIE->element_id) {
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.mac_address)) != 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->ie_length - _FIXED_IE_LENGTH_);
3709                        if ((p == NULL) || (len == 0)) {/* non-HT */
3710
3711                                if (pbss_network->configuration.ds_config <= 0)
3712                                        continue;
3713
3714                                ICS[0][pbss_network->configuration.ds_config] = 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->htpriv.agg_enable_bitmap & BIT(tid)) {
3786                                issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
3787                                psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
3788                                psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
3789
3790                        }
3791                }
3792        }
3793
3794        return _SUCCESS;
3795
3796}
3797
3798unsigned int send_beacon(struct adapter *padapter)
3799{
3800        u8 bxmitok = false;
3801        int     issue = 0;
3802        int poll = 0;
3803
3804        rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
3805        rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
3806        do {
3807                issue_beacon(padapter, 100);
3808                issue++;
3809                do {
3810                        cond_resched();
3811                        rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
3812                        poll++;
3813                } while ((poll%10) != 0 && false == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
3814
3815        } while (false == bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
3816
3817        if (padapter->bSurpriseRemoved || padapter->bDriverStopped) {
3818                return _FAIL;
3819        }
3820
3821
3822        if (!bxmitok)
3823                return _FAIL;
3824        else
3825                return _SUCCESS;
3826}
3827
3828/****************************************************************************
3829
3830Following are some utility functions for WiFi MLME
3831
3832*****************************************************************************/
3833
3834void site_survey(struct adapter *padapter)
3835{
3836        unsigned char   survey_channel = 0, val8;
3837        enum rt_scan_type       ScanType = SCAN_PASSIVE;
3838        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3839        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3840        u32 initialgain = 0;
3841        u32 channel_scan_time_ms = 0;
3842
3843        {
3844                struct rtw_ieee80211_channel *ch;
3845
3846                if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
3847                        ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
3848                        survey_channel = ch->hw_value;
3849                        ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
3850                }
3851        }
3852
3853        if (survey_channel != 0) {
3854                /* PAUSE 4-AC Queue when site_survey */
3855                /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
3856                /* val8 |= 0x0f; */
3857                /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
3858                if (pmlmeext->sitesurvey_res.channel_idx == 0) {
3859#ifdef DBG_FIXED_CHAN
3860                        if (pmlmeext->fixed_chan != 0xff)
3861                                set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3862                        else
3863#endif
3864                                set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
3865                } else {
3866#ifdef DBG_FIXED_CHAN
3867                        if (pmlmeext->fixed_chan != 0xff)
3868                                SelectChannel(padapter, pmlmeext->fixed_chan);
3869                        else
3870#endif
3871                                SelectChannel(padapter, survey_channel);
3872                }
3873
3874                if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
3875                        {
3876                                int i;
3877
3878                                for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
3879                                        if (pmlmeext->sitesurvey_res.ssid[i].ssid_length) {
3880                                                /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
3881                                                if (padapter->registrypriv.wifi_spec)
3882                                                        issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
3883                                                else
3884                                                        issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
3885                                                issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
3886                                        }
3887                                }
3888
3889                                if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
3890                                        /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
3891                                        if (padapter->registrypriv.wifi_spec)
3892                                                issue_probereq(padapter, NULL, NULL);
3893                                        else
3894                                                issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
3895                                        issue_probereq(padapter, NULL, NULL);
3896                                }
3897                        }
3898                }
3899
3900                channel_scan_time_ms = pmlmeext->chan_scan_time;
3901
3902                set_survey_timer(pmlmeext, channel_scan_time_ms);
3903        } else {
3904
3905                /*      channel number is 0 or this channel is not valid. */
3906
3907                {
3908                        pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
3909
3910                        /* switch back to the original channel */
3911                        /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
3912
3913                        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
3914
3915                        /* flush 4-AC Queue after site_survey */
3916                        /* val8 = 0; */
3917                        /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
3918
3919                        /* config MSR */
3920                        Set_MSR(padapter, (pmlmeinfo->state & 0x3));
3921
3922                        initialgain = 0xff; /* restore RX GAIN */
3923                        rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
3924                        /* turn on dynamic functions */
3925                        Restore_DM_Func_Flag(padapter);
3926                        /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
3927
3928                        if (is_client_associated_to_ap(padapter))
3929                                issue_nulldata(padapter, NULL, 0, 3, 500);
3930
3931                        val8 = 0; /* survey done */
3932                        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
3933
3934                        report_surveydone_event(padapter);
3935
3936                        pmlmeext->chan_scan_time = SURVEY_TO;
3937                        pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
3938
3939                        issue_action_BSSCoexistPacket(padapter);
3940                        issue_action_BSSCoexistPacket(padapter);
3941                        issue_action_BSSCoexistPacket(padapter);
3942                }
3943        }
3944
3945        return;
3946
3947}
3948
3949/* collect bss info from Beacon and Probe request/response frames. */
3950u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
3951{
3952        int     i;
3953        u32 len;
3954        u8 *p;
3955        u16 val16, subtype;
3956        u8 *pframe = precv_frame->u.hdr.rx_data;
3957        u32 packet_len = precv_frame->u.hdr.len;
3958        u8 ie_offset;
3959        struct registry_priv *pregistrypriv = &padapter->registrypriv;
3960        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3961        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3962        __le32 le32_tmp;
3963
3964        len = packet_len - sizeof(struct ieee80211_hdr_3addr);
3965
3966        if (len > MAX_IE_SZ)
3967                return _FAIL;
3968
3969        memset(bssid, 0, sizeof(struct wlan_bssid_ex));
3970
3971        subtype = GetFrameSubType(pframe);
3972
3973        if (subtype == WIFI_BEACON) {
3974                bssid->reserved[0] = 1;
3975                ie_offset = _BEACON_IE_OFFSET_;
3976        } else {
3977                /*  FIXME : more type */
3978                if (subtype == WIFI_PROBERSP) {
3979                        ie_offset = _PROBERSP_IE_OFFSET_;
3980                        bssid->reserved[0] = 3;
3981                } else if (subtype == WIFI_PROBEREQ) {
3982                        ie_offset = _PROBEREQ_IE_OFFSET_;
3983                        bssid->reserved[0] = 2;
3984                } else {
3985                        bssid->reserved[0] = 0;
3986                        ie_offset = _FIXED_IE_LENGTH_;
3987                }
3988        }
3989
3990        bssid->length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
3991
3992        /* below is to copy the information element */
3993        bssid->ie_length = len;
3994        memcpy(bssid->ies, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->ie_length);
3995
3996        /* get the signal strength */
3997        bssid->rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /*  in dBM.raw data */
3998        bssid->phy_info.signal_quality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
3999        bssid->phy_info.signal_strength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
4000
4001        /*  checking SSID */
4002        p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SSID, &len, bssid->ie_length - ie_offset);
4003        if (!p)
4004                return _FAIL;
4005
4006        if (*(p + 1)) {
4007                if (len > NDIS_802_11_LENGTH_SSID)
4008                        return _FAIL;
4009
4010                memcpy(bssid->ssid.ssid, (p + 2), *(p + 1));
4011                bssid->ssid.ssid_length = *(p + 1);
4012        } else
4013                bssid->ssid.ssid_length = 0;
4014
4015        memset(bssid->supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
4016
4017        /* checking rate info... */
4018        i = 0;
4019        p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_SUPP_RATES, &len, bssid->ie_length - ie_offset);
4020        if (p) {
4021                if (len > NDIS_802_11_LENGTH_RATES_EX)
4022                        return _FAIL;
4023
4024                memcpy(bssid->supported_rates, (p + 2), len);
4025                i = len;
4026        }
4027
4028        p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_EXT_SUPP_RATES, &len, bssid->ie_length - ie_offset);
4029        if (p) {
4030                if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
4031                        return _FAIL;
4032
4033                memcpy(bssid->supported_rates + i, (p + 2), len);
4034        }
4035
4036        bssid->network_type_in_use = Ndis802_11OFDM24;
4037
4038        if (bssid->ie_length < 12)
4039                return _FAIL;
4040
4041        /*  Checking for ds_config */
4042        p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_DS_PARAMS, &len, bssid->ie_length - ie_offset);
4043
4044        bssid->configuration.ds_config = 0;
4045        bssid->configuration.length = 0;
4046
4047        if (p) {
4048                bssid->configuration.ds_config = *(p + 2);
4049        } else {
4050                /*  In 5G, some ap do not have DSSET IE */
4051                /*  checking HT info for channel */
4052                p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_HT_OPERATION, &len, bssid->ie_length - ie_offset);
4053                if (p) {
4054                        struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
4055
4056                        bssid->configuration.ds_config = HT_info->primary_channel;
4057                } else { /*  use current channel */
4058                        bssid->configuration.ds_config = rtw_get_oper_ch(padapter);
4059                }
4060        }
4061
4062        memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->ies), 2);
4063        bssid->configuration.beacon_period = le32_to_cpu(le32_tmp);
4064
4065        val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
4066
4067        if (val16 & BIT(0)) {
4068                bssid->infrastructure_mode = Ndis802_11Infrastructure;
4069                memcpy(bssid->mac_address, GetAddr2Ptr(pframe), ETH_ALEN);
4070        } else {
4071                bssid->infrastructure_mode = Ndis802_11IBSS;
4072                memcpy(bssid->mac_address, GetAddr3Ptr(pframe), ETH_ALEN);
4073        }
4074
4075        if (val16 & BIT(4))
4076                bssid->privacy = 1;
4077        else
4078                bssid->privacy = 0;
4079
4080        bssid->configuration.atim_window = 0;
4081
4082        /* 20/40 BSS Coexistence check */
4083        if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) {
4084                struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4085
4086                p = rtw_get_ie(bssid->ies + ie_offset, WLAN_EID_HT_CAPABILITY, &len, bssid->ie_length - ie_offset);
4087                if (p && len > 0) {
4088                        struct HT_caps_element  *pHT_caps;
4089
4090                        pHT_caps = (struct HT_caps_element      *)(p + 2);
4091
4092                        if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14))
4093                                pmlmepriv->num_FortyMHzIntolerant++;
4094                } else
4095                        pmlmepriv->num_sta_no_ht++;
4096        }
4097
4098        /*  mark bss info receiving from nearby channel as signal_quality 101 */
4099        if (bssid->configuration.ds_config != rtw_get_oper_ch(padapter))
4100                bssid->phy_info.signal_quality = 101;
4101
4102        return _SUCCESS;
4103}
4104
4105void start_create_ibss(struct adapter *padapter)
4106{
4107        unsigned short  caps;
4108        u8 val8;
4109        u8 join_type;
4110        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4111        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4112        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4113
4114        pmlmeext->cur_channel = (u8)pnetwork->configuration.ds_config;
4115        pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
4116
4117        /* update wireless mode */
4118        update_wireless_mode(padapter);
4119
4120        /* update capability */
4121        caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
4122        update_capinfo(padapter, caps);
4123        if (caps&WLAN_CAPABILITY_IBSS) {/* adhoc master */
4124                val8 = 0xcf;
4125                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4126
4127                rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
4128
4129                /* switch channel */
4130                /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
4131                set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4132
4133                beacon_timing_control(padapter);
4134
4135                /* set msr to WIFI_FW_ADHOC_STATE */
4136                pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4137                Set_MSR(padapter, (pmlmeinfo->state & 0x3));
4138
4139                /* issue beacon */
4140                if (send_beacon(padapter) == _FAIL) {
4141                        report_join_res(padapter, -1);
4142                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
4143                } else {
4144                        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.mac_address);
4145                        join_type = 0;
4146                        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4147
4148                        report_join_res(padapter, 1);
4149                        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4150                        rtw_indicate_connect(padapter);
4151                }
4152        } else {
4153                return;
4154        }
4155        /* update bc/mc sta_info */
4156        update_bmc_sta(padapter);
4157
4158}
4159
4160void start_clnt_join(struct adapter *padapter)
4161{
4162        unsigned short  caps;
4163        u8 val8;
4164        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4165        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4166        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4167        int beacon_timeout;
4168
4169        /* update wireless mode */
4170        update_wireless_mode(padapter);
4171
4172        /* update capability */
4173        caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
4174        update_capinfo(padapter, caps);
4175        if (caps&WLAN_CAPABILITY_ESS) {
4176                Set_MSR(padapter, WIFI_FW_STATION_STATE);
4177
4178                val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
4179
4180                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4181
4182                /*  Because of AP's not receiving deauth before */
4183                /*  AP may: 1)not response auth or 2)deauth us after link is complete */
4184                /*  issue deauth before issuing auth to deal with the situation */
4185
4186                /*      Commented by Albert 2012/07/21 */
4187                /*      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
4188                {
4189                                /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */
4190                                issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
4191                }
4192
4193                /* here wait for receiving the beacon to start auth */
4194                /* and enable a timer */
4195                beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
4196                set_link_timer(pmlmeext, beacon_timeout);
4197                _set_timer(&padapter->mlmepriv.assoc_timer,
4198                        (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout);
4199
4200                pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
4201        } else if (caps&WLAN_CAPABILITY_IBSS) { /* adhoc client */
4202                Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
4203
4204                val8 = 0xcf;
4205                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4206
4207                beacon_timing_control(padapter);
4208
4209                pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4210
4211                report_join_res(padapter, 1);
4212        } else {
4213                return;
4214        }
4215
4216}
4217
4218void start_clnt_auth(struct adapter *padapter)
4219{
4220        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4221        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4222
4223        del_timer_sync(&pmlmeext->link_timer);
4224
4225        pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4226        pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4227
4228        pmlmeinfo->auth_seq = 1;
4229        pmlmeinfo->reauth_count = 0;
4230        pmlmeinfo->reassoc_count = 0;
4231        pmlmeinfo->link_count = 0;
4232        pmlmeext->retry = 0;
4233
4234
4235        netdev_dbg(padapter->pnetdev, "start auth\n");
4236        issue_auth(padapter, NULL, 0);
4237
4238        set_link_timer(pmlmeext, REAUTH_TO);
4239
4240}
4241
4242
4243void start_clnt_assoc(struct adapter *padapter)
4244{
4245        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4246        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4247
4248        del_timer_sync(&pmlmeext->link_timer);
4249
4250        pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4251        pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4252
4253        issue_assocreq(padapter);
4254
4255        set_link_timer(pmlmeext, REASSOC_TO);
4256}
4257
4258unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
4259{
4260        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4261        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4262
4263        /* check A3 */
4264        if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
4265                return _SUCCESS;
4266
4267        if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
4268                if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4269                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
4270                        report_del_sta_event(padapter, MacAddr, reason);
4271
4272                } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
4273                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
4274                        report_join_res(padapter, -2);
4275                }
4276        }
4277
4278        return _SUCCESS;
4279}
4280
4281static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
4282{
4283        struct registry_priv *pregistrypriv;
4284        struct mlme_ext_priv *pmlmeext;
4285        struct rt_channel_info *chplan_new;
4286        u8 channel;
4287        u8 i;
4288
4289
4290        pregistrypriv = &padapter->registrypriv;
4291        pmlmeext = &padapter->mlmeextpriv;
4292
4293        /*  Adjust channel plan by AP Country IE */
4294        if (pregistrypriv->enable80211d &&
4295                (!pmlmeext->update_channel_plan_by_ap_done)) {
4296                u8 *ie, *p;
4297                u32 len;
4298                struct rt_channel_plan chplan_ap;
4299                struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
4300                u8 country[4];
4301                u8 fcn; /*  first channel number */
4302                u8 noc; /*  number of channel */
4303                u8 j, k;
4304
4305                ie = rtw_get_ie(bssid->ies + _FIXED_IE_LENGTH_, WLAN_EID_COUNTRY, &len, bssid->ie_length - _FIXED_IE_LENGTH_);
4306                if (!ie)
4307                        return;
4308                if (len < 6)
4309                        return;
4310
4311                ie += 2;
4312                p = ie;
4313                ie += len;
4314
4315                memset(country, 0, 4);
4316                memcpy(country, p, 3);
4317                p += 3;
4318
4319                i = 0;
4320                while ((ie - p) >= 3) {
4321                        fcn = *(p++);
4322                        noc = *(p++);
4323                        p++;
4324
4325                        for (j = 0; j < noc; j++) {
4326                                if (fcn <= 14)
4327                                        channel = fcn + j; /*  2.4 GHz */
4328                                else
4329                                        channel = fcn + j*4; /*  5 GHz */
4330
4331                                chplan_ap.Channel[i++] = channel;
4332                        }
4333                }
4334                chplan_ap.Len = i;
4335
4336                memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4337
4338                memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4339                chplan_new = pmlmeext->channel_set;
4340
4341                i = j = k = 0;
4342                if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4343                        do {
4344                                if ((i == MAX_CHANNEL_NUM) ||
4345                                        (chplan_sta[i].ChannelNum == 0) ||
4346                                        (chplan_sta[i].ChannelNum > 14))
4347                                        break;
4348
4349                                if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
4350                                        break;
4351
4352                                if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
4353                                        chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4354                                        chplan_new[k].ScanType = SCAN_ACTIVE;
4355                                        i++;
4356                                        j++;
4357                                        k++;
4358                                } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
4359                                        chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4360/*                                      chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4361                                        chplan_new[k].ScanType = SCAN_PASSIVE;
4362                                        i++;
4363                                        k++;
4364                                } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
4365                                        chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4366                                        chplan_new[k].ScanType = SCAN_ACTIVE;
4367                                        j++;
4368                                        k++;
4369                                }
4370                        } while (1);
4371
4372                        /*  change AP not support channel to Passive scan */
4373                        while ((i < MAX_CHANNEL_NUM) &&
4374                                (chplan_sta[i].ChannelNum != 0) &&
4375                                (chplan_sta[i].ChannelNum <= 14)) {
4376
4377                                chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4378/*                              chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4379                                chplan_new[k].ScanType = SCAN_PASSIVE;
4380                                i++;
4381                                k++;
4382                        }
4383
4384                        /*  add channel AP supported */
4385                        while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
4386                                chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4387                                chplan_new[k].ScanType = SCAN_ACTIVE;
4388                                j++;
4389                                k++;
4390                        }
4391                } else {
4392                        /*  keep original STA 2.4G channel plan */
4393                        while ((i < MAX_CHANNEL_NUM) &&
4394                                (chplan_sta[i].ChannelNum != 0) &&
4395                                (chplan_sta[i].ChannelNum <= 14)) {
4396                                chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4397                                chplan_new[k].ScanType = chplan_sta[i].ScanType;
4398                                i++;
4399                                k++;
4400                        }
4401
4402                        /*  skip AP 2.4G channel plan */
4403                        while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
4404                                j++;
4405                        }
4406                }
4407
4408                pmlmeext->update_channel_plan_by_ap_done = 1;
4409        }
4410
4411        /*  If channel is used by AP, set channel scan type to active */
4412        channel = bssid->configuration.ds_config;
4413        chplan_new = pmlmeext->channel_set;
4414        i = 0;
4415        while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
4416                if (chplan_new[i].ChannelNum == channel) {
4417                        if (chplan_new[i].ScanType == SCAN_PASSIVE) {
4418                                chplan_new[i].ScanType = SCAN_ACTIVE;
4419                        }
4420                        break;
4421                }
4422                i++;
4423        }
4424}
4425
4426/****************************************************************************
4427
4428Following are the functions to report events
4429
4430*****************************************************************************/
4431
4432void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame)
4433{
4434        struct cmd_obj *pcmd_obj;
4435        u8 *pevtcmd;
4436        u32 cmdsz;
4437        struct survey_event     *psurvey_evt;
4438        struct C2HEvent_Header *pc2h_evt_hdr;
4439        struct mlme_ext_priv *pmlmeext;
4440        struct cmd_priv *pcmdpriv;
4441        /* u8 *pframe = precv_frame->u.hdr.rx_data; */
4442        /* uint len = precv_frame->u.hdr.len; */
4443
4444        if (!padapter)
4445                return;
4446
4447        pmlmeext = &padapter->mlmeextpriv;
4448        pcmdpriv = &padapter->cmdpriv;
4449
4450        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4451        if (!pcmd_obj)
4452                return;
4453
4454        cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
4455        pevtcmd = rtw_zmalloc(cmdsz);
4456        if (!pevtcmd) {
4457                kfree(pcmd_obj);
4458                return;
4459        }
4460
4461        INIT_LIST_HEAD(&pcmd_obj->list);
4462
4463        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4464        pcmd_obj->cmdsz = cmdsz;
4465        pcmd_obj->parmbuf = pevtcmd;
4466
4467        pcmd_obj->rsp = NULL;
4468        pcmd_obj->rspsz  = 0;
4469
4470        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4471        pc2h_evt_hdr->len = sizeof(struct survey_event);
4472        pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
4473        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4474
4475        psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4476
4477        if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
4478                kfree(pcmd_obj);
4479                kfree(pevtcmd);
4480                return;
4481        }
4482
4483        process_80211d(padapter, &psurvey_evt->bss);
4484
4485        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4486
4487        pmlmeext->sitesurvey_res.bss_cnt++;
4488
4489        return;
4490
4491}
4492
4493void report_surveydone_event(struct adapter *padapter)
4494{
4495        struct cmd_obj *pcmd_obj;
4496        u8 *pevtcmd;
4497        u32 cmdsz;
4498        struct surveydone_event *psurveydone_evt;
4499        struct C2HEvent_Header  *pc2h_evt_hdr;
4500        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4501        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4502
4503        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4504        if (!pcmd_obj)
4505                return;
4506
4507        cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
4508        pevtcmd = rtw_zmalloc(cmdsz);
4509        if (!pevtcmd) {
4510                kfree(pcmd_obj);
4511                return;
4512        }
4513
4514        INIT_LIST_HEAD(&pcmd_obj->list);
4515
4516        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4517        pcmd_obj->cmdsz = cmdsz;
4518        pcmd_obj->parmbuf = pevtcmd;
4519
4520        pcmd_obj->rsp = NULL;
4521        pcmd_obj->rspsz  = 0;
4522
4523        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4524        pc2h_evt_hdr->len = sizeof(struct surveydone_event);
4525        pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
4526        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4527
4528        psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4529        psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
4530
4531        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4532
4533        return;
4534
4535}
4536
4537void report_join_res(struct adapter *padapter, int res)
4538{
4539        struct cmd_obj *pcmd_obj;
4540        u8 *pevtcmd;
4541        u32 cmdsz;
4542        struct joinbss_event            *pjoinbss_evt;
4543        struct C2HEvent_Header  *pc2h_evt_hdr;
4544        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4545        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4546        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4547
4548        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4549        if (!pcmd_obj)
4550                return;
4551
4552        cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
4553        pevtcmd = rtw_zmalloc(cmdsz);
4554        if (!pevtcmd) {
4555                kfree(pcmd_obj);
4556                return;
4557        }
4558
4559        INIT_LIST_HEAD(&pcmd_obj->list);
4560
4561        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4562        pcmd_obj->cmdsz = cmdsz;
4563        pcmd_obj->parmbuf = pevtcmd;
4564
4565        pcmd_obj->rsp = NULL;
4566        pcmd_obj->rspsz  = 0;
4567
4568        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4569        pc2h_evt_hdr->len = sizeof(struct joinbss_event);
4570        pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
4571        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4572
4573        pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4574        memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
4575        pjoinbss_evt->network.join_res  = pjoinbss_evt->network.aid = res;
4576
4577
4578        rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
4579
4580
4581        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4582
4583        return;
4584
4585}
4586
4587void report_wmm_edca_update(struct adapter *padapter)
4588{
4589        struct cmd_obj *pcmd_obj;
4590        u8 *pevtcmd;
4591        u32 cmdsz;
4592        struct wmm_event                *pwmm_event;
4593        struct C2HEvent_Header  *pc2h_evt_hdr;
4594        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4595        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4596
4597        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4598        if (!pcmd_obj)
4599                return;
4600
4601        cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));
4602        pevtcmd = rtw_zmalloc(cmdsz);
4603        if (!pevtcmd) {
4604                kfree(pcmd_obj);
4605                return;
4606        }
4607
4608        INIT_LIST_HEAD(&pcmd_obj->list);
4609
4610        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4611        pcmd_obj->cmdsz = cmdsz;
4612        pcmd_obj->parmbuf = pevtcmd;
4613
4614        pcmd_obj->rsp = NULL;
4615        pcmd_obj->rspsz  = 0;
4616
4617        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4618        pc2h_evt_hdr->len = sizeof(struct wmm_event);
4619        pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM);
4620        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4621
4622        pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4623        pwmm_event->wmm = 0;
4624
4625        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4626
4627        return;
4628
4629}
4630
4631void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
4632{
4633        struct cmd_obj *pcmd_obj;
4634        u8 *pevtcmd;
4635        u32 cmdsz;
4636        struct sta_info *psta;
4637        int     mac_id;
4638        struct stadel_event                     *pdel_sta_evt;
4639        struct C2HEvent_Header  *pc2h_evt_hdr;
4640        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4641        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4642
4643        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4644        if (pcmd_obj == NULL) {
4645                return;
4646        }
4647
4648        cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
4649        pevtcmd = rtw_zmalloc(cmdsz);
4650        if (pevtcmd == NULL) {
4651                kfree(pcmd_obj);
4652                return;
4653        }
4654
4655        INIT_LIST_HEAD(&pcmd_obj->list);
4656
4657        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4658        pcmd_obj->cmdsz = cmdsz;
4659        pcmd_obj->parmbuf = pevtcmd;
4660
4661        pcmd_obj->rsp = NULL;
4662        pcmd_obj->rspsz  = 0;
4663
4664        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4665        pc2h_evt_hdr->len = sizeof(struct stadel_event);
4666        pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
4667        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4668
4669        pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4670        memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
4671        memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
4672
4673
4674        psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
4675        if (psta)
4676                mac_id = (int)psta->mac_id;
4677        else
4678                mac_id = (-1);
4679
4680        pdel_sta_evt->mac_id = mac_id;
4681
4682        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4683}
4684
4685void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
4686{
4687        struct cmd_obj *pcmd_obj;
4688        u8 *pevtcmd;
4689        u32 cmdsz;
4690        struct stassoc_event            *padd_sta_evt;
4691        struct C2HEvent_Header  *pc2h_evt_hdr;
4692        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4693        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
4694
4695        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
4696        if (pcmd_obj == NULL)
4697                return;
4698
4699        cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
4700        pevtcmd = rtw_zmalloc(cmdsz);
4701        if (pevtcmd == NULL) {
4702                kfree(pcmd_obj);
4703                return;
4704        }
4705
4706        INIT_LIST_HEAD(&pcmd_obj->list);
4707
4708        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
4709        pcmd_obj->cmdsz = cmdsz;
4710        pcmd_obj->parmbuf = pevtcmd;
4711
4712        pcmd_obj->rsp = NULL;
4713        pcmd_obj->rspsz  = 0;
4714
4715        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
4716        pc2h_evt_hdr->len = sizeof(struct stassoc_event);
4717        pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
4718        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
4719
4720        padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
4721        memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
4722        padd_sta_evt->cam_id = cam_idx;
4723
4724        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
4725}
4726
4727/****************************************************************************
4728
4729Following are the event callback functions
4730
4731*****************************************************************************/
4732
4733/* for sta/adhoc mode */
4734void update_sta_info(struct adapter *padapter, struct sta_info *psta)
4735{
4736        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4737        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4738        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4739
4740        /* ERP */
4741        VCS_update(padapter, psta);
4742
4743        /* HT */
4744        if (pmlmepriv->htpriv.ht_option) {
4745                psta->htpriv.ht_option = true;
4746
4747                psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
4748
4749                psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2;
4750
4751                if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))
4752                        psta->htpriv.sgi_20m = true;
4753
4754                if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))
4755                        psta->htpriv.sgi_40m = true;
4756
4757                psta->qos_option = true;
4758
4759                psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;
4760                psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;
4761                psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
4762
4763                memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct ieee80211_ht_cap));
4764        } else {
4765                psta->htpriv.ht_option = false;
4766
4767                psta->htpriv.ampdu_enable = false;
4768
4769                psta->htpriv.sgi_20m = false;
4770                psta->htpriv.sgi_40m = false;
4771                psta->qos_option = false;
4772
4773        }
4774
4775        psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
4776
4777        psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
4778        psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
4779
4780        psta->bw_mode = pmlmeext->cur_bwmode;
4781
4782        /* QoS */
4783        if (pmlmepriv->qospriv.qos_option)
4784                psta->qos_option = true;
4785
4786        update_ldpc_stbc_cap(psta);
4787
4788        spin_lock_bh(&psta->lock);
4789        psta->state = _FW_LINKED;
4790        spin_unlock_bh(&psta->lock);
4791
4792}
4793
4794static void rtw_mlmeext_disconnect(struct adapter *padapter)
4795{
4796        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
4797        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4798        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4799        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4800
4801        /* set_opmode_cmd(padapter, infra_client_with_mlme); */
4802
4803        /* For safety, prevent from keeping macid sleep.
4804         * If we can sure all power mode enter/leave are paired,
4805         * this check can be removed.
4806         * Lucas@20131113
4807         */
4808        /* wakeup macid after disconnect. */
4809        {
4810                struct sta_info *psta;
4811
4812                psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
4813                if (psta)
4814                        rtw_hal_macid_wakeup(padapter, psta->mac_id);
4815        }
4816
4817        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
4818        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
4819
4820        /* set MSR to no link state -> infra. mode */
4821        Set_MSR(padapter, _HW_STATE_STATION_);
4822
4823        pmlmeinfo->state = WIFI_FW_NULL_STATE;
4824
4825        /* switch to the 20M Hz mode after disconnect */
4826        pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
4827        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4828
4829        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4830
4831        flush_all_cam_entry(padapter);
4832
4833        del_timer_sync(&pmlmeext->link_timer);
4834
4835        /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */
4836        pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
4837        pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
4838
4839}
4840
4841void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
4842{
4843        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4844        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4845        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
4846        struct sta_priv         *pstapriv = &padapter->stapriv;
4847        u8 join_type;
4848        struct sta_info *psta;
4849
4850        if (join_res < 0) {
4851                join_type = 1;
4852                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4853                rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
4854
4855                return;
4856        }
4857
4858        if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
4859                /* update bc/mc sta_info */
4860                update_bmc_sta(padapter);
4861
4862
4863        /* turn on dynamic functions */
4864        Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
4865
4866        /*  update IOT-related issue */
4867        update_IOT_info(padapter);
4868
4869        rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->supported_rates);
4870
4871        /* BCN interval */
4872        rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
4873
4874        /* update capability */
4875        update_capinfo(padapter, pmlmeinfo->capability);
4876
4877        /* WMM, Update EDCA param */
4878        WMMOnAssocRsp(padapter);
4879
4880        /* HT */
4881        HTOnAssocRsp(padapter);
4882
4883        /* Set cur_channel&cur_bwmode&cur_ch_offset */
4884        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4885
4886        psta = rtw_get_stainfo(pstapriv, cur_network->mac_address);
4887        if (psta) { /* only for infra. mode */
4888
4889                pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
4890
4891                psta->wireless_mode = pmlmeext->cur_wireless_mode;
4892
4893                /* set per sta rate after updating HT cap. */
4894                set_sta_rate(padapter, psta);
4895
4896                rtw_sta_media_status_rpt(padapter, psta, 1);
4897
4898                /* wakeup macid after join bss successfully to ensure
4899                        the subsequent data frames can be sent out normally */
4900                rtw_hal_macid_wakeup(padapter, psta->mac_id);
4901        }
4902
4903        join_type = 2;
4904        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4905
4906        if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
4907                /*  correcting TSF */
4908                correct_TSF(padapter, pmlmeext);
4909
4910                /* set_link_timer(pmlmeext, DISCONNECT_TO); */
4911        }
4912
4913        if (get_iface_type(padapter) == IFACE_PORT0)
4914                rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
4915}
4916
4917/* currently only adhoc mode will go here */
4918void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
4919{
4920        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
4921        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4922        u8 join_type;
4923
4924        if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
4925                if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */
4926
4927                        /* nothing to do */
4928                } else { /* adhoc client */
4929                        /* update TSF Value */
4930                        /* update_TSF(pmlmeext, pframe, len); */
4931
4932                        /*  correcting TSF */
4933                        correct_TSF(padapter, pmlmeext);
4934
4935                        /* start beacon */
4936                        if (send_beacon(padapter) == _FAIL) {
4937                                pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
4938
4939                                pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
4940
4941                                return;
4942                        }
4943
4944                        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4945
4946                }
4947
4948                join_type = 2;
4949                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4950        }
4951
4952        pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
4953
4954        psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates);
4955        memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen);
4956
4957        /* update adhoc sta_info */
4958        update_sta_info(padapter, psta);
4959
4960        rtw_hal_update_sta_rate_mask(padapter, psta);
4961
4962        /*  ToDo: HT for Ad-hoc */
4963        psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);
4964        psta->raid = networktype_to_raid_ex(padapter, psta);
4965
4966        /* rate radaptive */
4967        Update_RA_Entry(padapter, psta);
4968}
4969
4970void mlmeext_sta_del_event_callback(struct adapter *padapter)
4971{
4972        if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
4973                rtw_mlmeext_disconnect(padapter);
4974}
4975
4976/****************************************************************************
4977
4978Following are the functions for the timer handlers
4979
4980*****************************************************************************/
4981void _linked_info_dump(struct adapter *padapter)
4982{
4983        int i;
4984        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
4985        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4986        int UndecoratedSmoothedPWDB;
4987        struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
4988
4989        if (padapter->bLinkInfoDump) {
4990
4991                if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
4992                        rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
4993
4994                for (i = 0; i < NUM_STA; i++) {
4995                        if (pdvobj->macid[i]) {
4996                                if (i != 1) /* skip bc/mc sta */
4997                                        /*   tx info ============ */
4998                                        rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i);
4999                        }
5000                }
5001                rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL);
5002        }
5003}
5004
5005static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
5006{
5007        u8 ret = false;
5008
5009        if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
5010                && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
5011                && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
5012        ) {
5013                ret = false;
5014        } else {
5015                ret = true;
5016        }
5017
5018        sta_update_last_rx_pkts(psta);
5019
5020        return ret;
5021}
5022
5023void linked_status_chk(struct adapter *padapter)
5024{
5025        u32 i;
5026        struct sta_info         *psta;
5027        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
5028        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5029        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5030        struct sta_priv         *pstapriv = &padapter->stapriv;
5031
5032
5033        if (is_client_associated_to_ap(padapter)) {
5034                /* linked infrastructure client mode */
5035
5036                int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
5037                int rx_chk_limit;
5038                int link_count_limit;
5039
5040                #if defined(DBG_ROAMING_TEST)
5041                rx_chk_limit = 1;
5042                #else
5043                rx_chk_limit = 8;
5044                #endif
5045                link_count_limit = 7; /*  16 sec */
5046
5047                /*  Marked by Kurt 20130715 */
5048                /*  For WiDi 3.5 and latered on, they don't ask WiDi sink to do roaming, so we could not check rx limit that strictly. */
5049                /*  todo: To check why we under miracast session, rx_chk would be false */
5050                psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.mac_address);
5051                if (psta) {
5052                        if (chk_ap_is_alive(padapter, psta) == false)
5053                                rx_chk = _FAIL;
5054
5055                        if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
5056                                tx_chk = _FAIL;
5057
5058                        {
5059                                if (rx_chk != _SUCCESS) {
5060                                        if (pmlmeext->retry == 0) {
5061                                                issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, pmlmeinfo->network.mac_address, 0, 0, 0, 0);
5062                                                issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, pmlmeinfo->network.mac_address, 0, 0, 0, 0);
5063                                                issue_probereq_ex(padapter, &pmlmeinfo->network.ssid, pmlmeinfo->network.mac_address, 0, 0, 0, 0);
5064                                        }
5065                                }
5066
5067                                if (tx_chk != _SUCCESS &&
5068                                    pmlmeinfo->link_count++ == link_count_limit)
5069                                        tx_chk = issue_nulldata_in_interrupt(padapter, NULL);
5070                        }
5071
5072                        if (rx_chk == _FAIL) {
5073                                pmlmeext->retry++;
5074                                if (pmlmeext->retry > rx_chk_limit) {
5075                                        netdev_dbg(padapter->pnetdev,
5076                                                   FUNC_ADPT_FMT " disconnect or roaming\n",
5077                                                   FUNC_ADPT_ARG(padapter));
5078                                        receive_disconnect(padapter, pmlmeinfo->network.mac_address
5079                                                , WLAN_REASON_EXPIRATION_CHK);
5080                                        return;
5081                                }
5082                        } else {
5083                                pmlmeext->retry = 0;
5084                        }
5085
5086                        if (tx_chk == _FAIL) {
5087                                pmlmeinfo->link_count %= (link_count_limit+1);
5088                        } else {
5089                                pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5090                                pmlmeinfo->link_count = 0;
5091                        }
5092
5093                } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.mac_address)) != NULL) */
5094        } else if (is_client_associated_to_ibss(padapter)) {
5095                /* linked IBSS mode */
5096                /* for each assoc list entry to check the rx pkt counter */
5097                for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5098                        if (pmlmeinfo->FW_sta_info[i].status == 1) {
5099                                psta = pmlmeinfo->FW_sta_info[i].psta;
5100
5101                                if (NULL == psta)
5102                                        continue;
5103
5104                                if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
5105
5106                                        if (pmlmeinfo->FW_sta_info[i].retry < 3) {
5107                                                pmlmeinfo->FW_sta_info[i].retry++;
5108                                        } else {
5109                                                pmlmeinfo->FW_sta_info[i].retry = 0;
5110                                                pmlmeinfo->FW_sta_info[i].status = 0;
5111                                                report_del_sta_event(padapter, psta->hwaddr
5112                                                        , 65535/*  indicate disconnect caused by no rx */
5113                                                );
5114                                        }
5115                                } else {
5116                                        pmlmeinfo->FW_sta_info[i].retry = 0;
5117                                        pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5118                                }
5119                        }
5120                }
5121
5122                /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5123
5124        }
5125
5126}
5127
5128void survey_timer_hdl(struct timer_list *t)
5129{
5130        struct adapter *padapter =
5131                from_timer(padapter, t, mlmeextpriv.survey_timer);
5132        struct cmd_obj  *ph2c;
5133        struct sitesurvey_parm  *psurveyPara;
5134        struct cmd_priv                                 *pcmdpriv = &padapter->cmdpriv;
5135        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5136
5137        /* issue rtw_sitesurvey_cmd */
5138        if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5139                if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS) {
5140                        pmlmeext->sitesurvey_res.channel_idx++;
5141                }
5142
5143                if (pmlmeext->scan_abort) {
5144                        pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
5145
5146                        pmlmeext->scan_abort = false;/* reset */
5147                }
5148
5149                ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
5150                if (ph2c == NULL) {
5151                        goto exit_survey_timer_hdl;
5152                }
5153
5154                psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm));
5155                if (psurveyPara == NULL) {
5156                        kfree(ph2c);
5157                        goto exit_survey_timer_hdl;
5158                }
5159
5160                init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
5161                rtw_enqueue_cmd(pcmdpriv, ph2c);
5162        }
5163
5164
5165exit_survey_timer_hdl:
5166
5167        return;
5168}
5169
5170void link_timer_hdl(struct timer_list *t)
5171{
5172        struct adapter *padapter =
5173                from_timer(padapter, t, mlmeextpriv.link_timer);
5174        /* static unsigned int          rx_pkt = 0; */
5175        /* static u64                           tx_cnt = 0; */
5176        /* struct xmit_priv     *pxmitpriv = &(padapter->xmitpriv); */
5177        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5178        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5179        /* struct sta_priv      *pstapriv = &padapter->stapriv; */
5180
5181
5182        if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
5183                pmlmeinfo->state = WIFI_FW_NULL_STATE;
5184                report_join_res(padapter, -3);
5185        } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
5186                /* re-auth timer */
5187                if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
5188                        /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
5189                        /*  */
5190                                pmlmeinfo->state = 0;
5191                                report_join_res(padapter, -1);
5192                                return;
5193                        /*  */
5194                        /* else */
5195                        /*  */
5196                        /*      pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
5197                        /*      pmlmeinfo->reauth_count = 0; */
5198                        /*  */
5199                }
5200
5201                pmlmeinfo->auth_seq = 1;
5202                issue_auth(padapter, NULL, 0);
5203                set_link_timer(pmlmeext, REAUTH_TO);
5204        } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
5205                /* re-assoc timer */
5206                if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
5207                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
5208                        report_join_res(padapter, -2);
5209                        return;
5210                }
5211
5212                issue_assocreq(padapter);
5213                set_link_timer(pmlmeext, REASSOC_TO);
5214        }
5215}
5216
5217void addba_timer_hdl(struct timer_list *t)
5218{
5219        struct sta_info *psta = from_timer(psta, t, addba_retry_timer);
5220        struct ht_priv *phtpriv;
5221
5222        if (!psta)
5223                return;
5224
5225        phtpriv = &psta->htpriv;
5226
5227        if (phtpriv->ht_option && phtpriv->ampdu_enable) {
5228                if (phtpriv->candidate_tid_bitmap)
5229                        phtpriv->candidate_tid_bitmap = 0x0;
5230
5231        }
5232}
5233
5234void sa_query_timer_hdl(struct timer_list *t)
5235{
5236        struct adapter *padapter =
5237                from_timer(padapter, t, mlmeextpriv.sa_query_timer);
5238        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5239        /* disconnect */
5240        spin_lock_bh(&pmlmepriv->lock);
5241
5242        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
5243                rtw_disassoc_cmd(padapter, 0, true);
5244                rtw_indicate_disconnect(padapter);
5245                rtw_free_assoc_resources(padapter, 1);
5246        }
5247
5248        spin_unlock_bh(&pmlmepriv->lock);
5249}
5250
5251u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
5252{
5253        return H2C_SUCCESS;
5254}
5255
5256u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
5257{
5258        u8 type;
5259        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5260        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5261        struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
5262
5263        if (psetop->mode == Ndis802_11APMode) {
5264                pmlmeinfo->state = WIFI_FW_AP_STATE;
5265                type = _HW_STATE_AP_;
5266                /* start_ap_mode(padapter); */
5267        } else if (psetop->mode == Ndis802_11Infrastructure) {
5268                pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
5269                pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to     STATION_STATE */
5270                type = _HW_STATE_STATION_;
5271        } else if (psetop->mode == Ndis802_11IBSS) {
5272                type = _HW_STATE_ADHOC_;
5273        } else {
5274                type = _HW_STATE_NOLINK_;
5275        }
5276
5277        rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
5278        /* Set_MSR(padapter, type); */
5279
5280        if (psetop->mode == Ndis802_11APMode) {
5281                /*  Do this after port switch to */
5282                /*  prevent from downloading rsvd page to wrong port */
5283                rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */
5284        }
5285
5286        return H2C_SUCCESS;
5287
5288}
5289
5290u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
5291{
5292        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5293        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5294        struct wlan_bssid_ex    *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5295        struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
5296        /* u32 initialgain; */
5297
5298        if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
5299                start_bss_network(padapter);
5300                return H2C_SUCCESS;
5301        }
5302
5303        /* below is for ad-hoc master */
5304        if (pparm->network.infrastructure_mode == Ndis802_11IBSS) {
5305                rtw_joinbss_reset(padapter);
5306
5307                pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5308                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5309                pmlmeinfo->ERP_enable = 0;
5310                pmlmeinfo->WMM_enable = 0;
5311                pmlmeinfo->HT_enable = 0;
5312                pmlmeinfo->HT_caps_enable = 0;
5313                pmlmeinfo->HT_info_enable = 0;
5314                pmlmeinfo->agg_enable_bitmap = 0;
5315                pmlmeinfo->candidate_tid_bitmap = 0;
5316
5317                /* disable dynamic functions, such as high power, DIG */
5318                Save_DM_Func_Flag(padapter);
5319                Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
5320
5321                /* config the initial gain under linking, need to write the BB registers */
5322                /* initialgain = 0x1E; */
5323                /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
5324
5325                /* cancel link timer */
5326                del_timer_sync(&pmlmeext->link_timer);
5327
5328                /* clear CAM */
5329                flush_all_cam_entry(padapter);
5330
5331                memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, ie_length));
5332                pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
5333
5334                if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
5335                        return H2C_PARAMETERS_ERROR;
5336
5337                memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
5338
5339                start_create_ibss(padapter);
5340
5341        }
5342
5343        return H2C_SUCCESS;
5344
5345}
5346
5347u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
5348{
5349        u8 join_type;
5350        struct ndis_80211_var_ie *pIE;
5351        struct registry_priv *pregpriv = &padapter->registrypriv;
5352        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5353        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5354        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5355        u32 i;
5356        u8 cbw40_enable = 0;
5357        /* u32 initialgain; */
5358        /* u32 acparm; */
5359        u8 ch, bw, offset;
5360
5361        /* check already connecting to AP or not */
5362        if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
5363                if (pmlmeinfo->state & WIFI_FW_STATION_STATE) {
5364                        issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
5365                }
5366                pmlmeinfo->state = WIFI_FW_NULL_STATE;
5367
5368                /* clear CAM */
5369                flush_all_cam_entry(padapter);
5370
5371                del_timer_sync(&pmlmeext->link_timer);
5372
5373                /* set MSR to nolink -> infra. mode */
5374                /* Set_MSR(padapter, _HW_STATE_NOLINK_); */
5375                Set_MSR(padapter, _HW_STATE_STATION_);
5376
5377
5378                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
5379        }
5380
5381        rtw_joinbss_reset(padapter);
5382
5383        pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5384        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5385        pmlmeinfo->ERP_enable = 0;
5386        pmlmeinfo->WMM_enable = 0;
5387        pmlmeinfo->HT_enable = 0;
5388        pmlmeinfo->HT_caps_enable = 0;
5389        pmlmeinfo->HT_info_enable = 0;
5390        pmlmeinfo->agg_enable_bitmap = 0;
5391        pmlmeinfo->candidate_tid_bitmap = 0;
5392        pmlmeinfo->bwmode_updated = false;
5393        /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
5394        pmlmeinfo->VHT_enable = 0;
5395
5396        memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, ie_length));
5397        pnetwork->ie_length = ((struct wlan_bssid_ex *)pbuf)->ie_length;
5398
5399        if (pnetwork->ie_length > MAX_IE_SZ)/* Check pbuf->ie_length */
5400                return H2C_PARAMETERS_ERROR;
5401
5402        memcpy(pnetwork->ies, ((struct wlan_bssid_ex *)pbuf)->ies, pnetwork->ie_length);
5403
5404        pmlmeext->cur_channel = (u8)pnetwork->configuration.ds_config;
5405        pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
5406
5407        /* Check AP vendor to move rtw_joinbss_cmd() */
5408        /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->ies, pnetwork->ie_length); */
5409
5410        /* sizeof(struct ndis_802_11_fix_ie) */
5411        for (i = _FIXED_IE_LENGTH_; i < pnetwork->ie_length;) {
5412                pIE = (struct ndis_80211_var_ie *)(pnetwork->ies + i);
5413
5414                switch (pIE->element_id) {
5415                case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */
5416                        if (!memcmp(pIE->data, WMM_OUI, 4))
5417                                WMM_param_handler(padapter, pIE);
5418                        break;
5419
5420                case WLAN_EID_HT_CAPABILITY:    /* Get HT Cap IE. */
5421                        pmlmeinfo->HT_caps_enable = 1;
5422                        break;
5423
5424                case WLAN_EID_HT_OPERATION:     /* Get HT Info IE. */
5425                        pmlmeinfo->HT_info_enable = 1;
5426
5427                        /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
5428                        {
5429                                struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
5430
5431                                if (pnetwork->configuration.ds_config <= 14) {
5432                                        if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20)
5433                                                cbw40_enable = 1;
5434                                }
5435
5436                                if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
5437                                        /* switch to the 40M Hz mode according to the AP */
5438                                        pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
5439                                        switch (pht_info->infos[0] & 0x3) {
5440                                        case 1:
5441                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
5442                                                break;
5443
5444                                        case 3:
5445                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
5446                                                break;
5447
5448                                        default:
5449                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5450                                                pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5451                                                break;
5452                                        }
5453                                }
5454                        }
5455                        break;
5456                default:
5457                        break;
5458                }
5459
5460                i += (pIE->length + 2);
5461        }
5462
5463        /* check channel, bandwidth, offset and switch */
5464        if (rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) {
5465                report_join_res(padapter, (-4));
5466                return H2C_SUCCESS;
5467        }
5468
5469        /* disable dynamic functions, such as high power, DIG */
5470        /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */
5471
5472        /* config the initial gain under linking, need to write the BB registers */
5473        /* initialgain = 0x1E; */
5474        /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
5475
5476        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.mac_address);
5477        join_type = 0;
5478        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5479        rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
5480
5481        set_channel_bwmode(padapter, ch, offset, bw);
5482
5483        /* cancel link timer */
5484        del_timer_sync(&pmlmeext->link_timer);
5485
5486        start_clnt_join(padapter);
5487
5488        return H2C_SUCCESS;
5489
5490}
5491
5492u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
5493{
5494        struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
5495        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5496        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5497        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5498        u8 val8;
5499
5500        if (is_client_associated_to_ap(padapter)) {
5501                        issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
5502        }
5503
5504        if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
5505                /* Stop BCN */
5506                val8 = 0;
5507                rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
5508        }
5509
5510        rtw_mlmeext_disconnect(padapter);
5511
5512        rtw_free_uc_swdec_pending_queue(padapter);
5513
5514        return  H2C_SUCCESS;
5515}
5516
5517static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
5518        u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
5519{
5520        int i, j;
5521        int set_idx;
5522        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5523
5524        /* clear first */
5525        memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
5526
5527        /* acquire channels from in */
5528        j = 0;
5529        for (i = 0; i < in_num; i++) {
5530
5531                set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
5532                if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED)
5533                        && set_idx >= 0
5534                ) {
5535                        if (j >= out_num) {
5536                                netdev_dbg(padapter->pnetdev,
5537                                           FUNC_ADPT_FMT " out_num:%u not enough\n",
5538                                           FUNC_ADPT_ARG(padapter), out_num);
5539                                break;
5540                        }
5541
5542                        memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
5543
5544                        if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
5545                                out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
5546
5547                        j++;
5548                }
5549                if (j >= out_num)
5550                        break;
5551        }
5552
5553        /* if out is empty, use channel_set as default */
5554        if (j == 0) {
5555                for (i = 0; i < pmlmeext->max_chan_nums; i++) {
5556
5557                        if (j >= out_num) {
5558                                netdev_dbg(padapter->pnetdev,
5559                                           FUNC_ADPT_FMT " out_num:%u not enough\n",
5560                                           FUNC_ADPT_ARG(padapter),
5561                                           out_num);
5562                                break;
5563                        }
5564
5565                        out[j].hw_value = pmlmeext->channel_set[i].ChannelNum;
5566
5567                        if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
5568                                out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
5569
5570                        j++;
5571                }
5572        }
5573
5574        return j;
5575}
5576
5577u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
5578{
5579        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5580        struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
5581        u8 bdelayscan = false;
5582        u8 val8;
5583        u32 initialgain;
5584        u32 i;
5585
5586        if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
5587                pmlmeext->sitesurvey_res.state = SCAN_START;
5588                pmlmeext->sitesurvey_res.bss_cnt = 0;
5589                pmlmeext->sitesurvey_res.channel_idx = 0;
5590
5591                for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
5592                        if (pparm->ssid[i].ssid_length) {
5593                                memcpy(pmlmeext->sitesurvey_res.ssid[i].ssid, pparm->ssid[i].ssid, IW_ESSID_MAX_SIZE);
5594                                pmlmeext->sitesurvey_res.ssid[i].ssid_length = pparm->ssid[i].ssid_length;
5595                        } else {
5596                                pmlmeext->sitesurvey_res.ssid[i].ssid_length = 0;
5597                        }
5598                }
5599
5600                pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
5601                        , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
5602                        , pparm->ch, pparm->ch_num
5603                );
5604
5605                pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
5606
5607                /* issue null data if associating to the AP */
5608                if (is_client_associated_to_ap(padapter)) {
5609                        pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
5610
5611                        issue_nulldata(padapter, NULL, 1, 3, 500);
5612
5613                        bdelayscan = true;
5614                }
5615                if (bdelayscan) {
5616                        /* delay 50ms to protect nulldata(1). */
5617                        set_survey_timer(pmlmeext, 50);
5618                        return H2C_SUCCESS;
5619                }
5620        }
5621
5622        if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
5623                /* disable dynamic functions, such as high power, DIG */
5624                Save_DM_Func_Flag(padapter);
5625                Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
5626
5627                /* config the initial gain under scanning, need to write the BB
5628                 * registers
5629                 */
5630                initialgain = 0x1e;
5631
5632                rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
5633
5634                /* set MSR to no link state */
5635                Set_MSR(padapter, _HW_STATE_NOLINK_);
5636
5637                val8 = 1; /* under site survey */
5638                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
5639
5640                pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
5641        }
5642
5643        site_survey(padapter);
5644
5645        return H2C_SUCCESS;
5646
5647}
5648
5649u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
5650{
5651        struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
5652        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5653        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5654
5655        if (pparm->mode < 4)
5656                pmlmeinfo->auth_algo = pparm->mode;
5657
5658        return  H2C_SUCCESS;
5659}
5660
5661u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
5662{
5663        u16 ctrl = 0;
5664        s16 cam_id = 0;
5665        struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
5666        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5667        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5668        unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
5669        u8 *addr;
5670
5671        /* main tx key for wep. */
5672        if (pparm->set_tx)
5673                pmlmeinfo->key_index = pparm->keyid;
5674
5675        cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid);
5676
5677        if (cam_id < 0) {
5678        } else {
5679                if (cam_id > 3) /* not default key, searched by A2 */
5680                        addr = get_bssid(&padapter->mlmepriv);
5681                else
5682                        addr = null_addr;
5683
5684                ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid;
5685                write_cam(padapter, cam_id, ctrl, addr, pparm->key);
5686                netdev_dbg(padapter->pnetdev,
5687                           "set group key camid:%d, addr:%pM, kid:%d, type:%s\n",
5688                           cam_id, MAC_ARG(addr), pparm->keyid,
5689                           security_type_str(pparm->algorithm));
5690        }
5691
5692        if (cam_id >= 0 && cam_id <= 3)
5693                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true);
5694
5695        /* allow multicast packets to driver */
5696        padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
5697
5698        return H2C_SUCCESS;
5699}
5700
5701u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
5702{
5703        u16 ctrl = 0;
5704        s16 cam_id = 0;
5705        u8 ret = H2C_SUCCESS;
5706        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5707        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5708        struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
5709        struct sta_priv *pstapriv = &padapter->stapriv;
5710        struct sta_info *psta;
5711
5712        if (pparm->algorithm == _NO_PRIVACY_)
5713                goto write_to_cam;
5714
5715        psta = rtw_get_stainfo(pstapriv, pparm->addr);
5716        if (!psta) {
5717                netdev_dbg(padapter->pnetdev, "%s sta:%pM not found\n",
5718                           __func__, MAC_ARG(pparm->addr));
5719                ret = H2C_REJECTED;
5720                goto exit;
5721        }
5722
5723        pmlmeinfo->enc_algo = pparm->algorithm;
5724        cam_id = rtw_camid_alloc(padapter, psta, 0);
5725        if (cam_id < 0)
5726                goto exit;
5727
5728write_to_cam:
5729        if (pparm->algorithm == _NO_PRIVACY_) {
5730                while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) {
5731                        netdev_dbg(padapter->pnetdev,
5732                                   "clear key for addr:%pM, camid:%d\n",
5733                                   MAC_ARG(pparm->addr), cam_id);
5734                        clear_cam_entry(padapter, cam_id);
5735                        rtw_camid_free(padapter, cam_id);
5736                }
5737        } else {
5738                netdev_dbg(padapter->pnetdev,
5739                           "set pairwise key camid:%d, addr:%pM, kid:%d, type:%s\n",
5740                           cam_id, MAC_ARG(pparm->addr), pparm->keyid,
5741                           security_type_str(pparm->algorithm));
5742                ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
5743                write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
5744        }
5745        ret = H2C_SUCCESS_RSP;
5746
5747exit:
5748        return ret;
5749}
5750
5751u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
5752{
5753        struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
5754        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5755        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5756
5757        struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
5758
5759        if (!psta)
5760                return  H2C_SUCCESS;
5761
5762        if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
5763                ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
5764                /* pmlmeinfo->ADDBA_retry_count = 0; */
5765                /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */
5766                /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */
5767                issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
5768                /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */
5769                _set_timer(&psta->addba_retry_timer, ADDBA_TO);
5770        } else {
5771                psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
5772        }
5773        return  H2C_SUCCESS;
5774}
5775
5776
5777u8 chk_bmc_sleepq_cmd(struct adapter *padapter)
5778{
5779        struct cmd_obj *ph2c;
5780        struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
5781        u8 res = _SUCCESS;
5782
5783        ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
5784        if (ph2c == NULL) {
5785                res = _FAIL;
5786                goto exit;
5787        }
5788
5789        init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));
5790
5791        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5792
5793exit:
5794        return res;
5795}
5796
5797u8 set_tx_beacon_cmd(struct adapter *padapter)
5798{
5799        struct cmd_obj  *ph2c;
5800        struct Tx_Beacon_param  *ptxBeacon_parm;
5801        struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
5802        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5803        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5804        u8 res = _SUCCESS;
5805        int len_diff = 0;
5806
5807        ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
5808        if (ph2c == NULL) {
5809                res = _FAIL;
5810                goto exit;
5811        }
5812
5813        ptxBeacon_parm = rtw_zmalloc(sizeof(struct Tx_Beacon_param));
5814        if (ptxBeacon_parm == NULL) {
5815                kfree(ph2c);
5816                res = _FAIL;
5817                goto exit;
5818        }
5819
5820        memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
5821
5822        len_diff = update_hidden_ssid(ptxBeacon_parm->network.ies+_BEACON_IE_OFFSET_,
5823                                      ptxBeacon_parm->network.ie_length-_BEACON_IE_OFFSET_,
5824                                      pmlmeinfo->hidden_ssid_mode);
5825        ptxBeacon_parm->network.ie_length += len_diff;
5826
5827        init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
5828
5829        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
5830
5831exit:
5832        return res;
5833}
5834
5835static struct fwevent wlanevents[] = {
5836        {0, rtw_dummy_event_callback},  /*0*/
5837        {0, NULL},
5838        {0, NULL},
5839        {0, NULL},
5840        {0, NULL},
5841        {0, NULL},
5842        {0, NULL},
5843        {0, NULL},
5844        {0, &rtw_survey_event_callback},                /*8*/
5845        {sizeof(struct surveydone_event), &rtw_surveydone_event_callback},      /*9*/
5846
5847        {0, &rtw_joinbss_event_callback},               /*10*/
5848        {sizeof(struct stassoc_event), &rtw_stassoc_event_callback},
5849        {sizeof(struct stadel_event), &rtw_stadel_event_callback},
5850        {0, &rtw_atimdone_event_callback},
5851        {0, rtw_dummy_event_callback},
5852        {0, NULL},      /*15*/
5853        {0, NULL},
5854        {0, NULL},
5855        {0, NULL},
5856        {0, rtw_fwdbg_event_callback},
5857        {0, NULL},       /*20*/
5858        {0, NULL},
5859        {0, NULL},
5860        {0, &rtw_cpwm_event_callback},
5861        {0, NULL},
5862        {0, &rtw_wmm_event_callback},
5863
5864};
5865
5866u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
5867{
5868        u8 evt_code;
5869        u16 evt_sz;
5870        uint    *peventbuf;
5871        void (*event_callback)(struct adapter *dev, u8 *pbuf);
5872        struct evt_priv *pevt_priv = &(padapter->evtpriv);
5873
5874        if (pbuf == NULL)
5875                goto _abort_event_;
5876
5877        peventbuf = (uint *)pbuf;
5878        evt_sz = (u16)(*peventbuf&0xffff);
5879        evt_code = (u8)((*peventbuf>>16)&0xff);
5880
5881        /*  checking if event code is valid */
5882        if (evt_code >= MAX_C2HEVT)
5883                goto _abort_event_;
5884
5885        /*  checking if event size match the event parm size */
5886        if ((wlanevents[evt_code].parmsize != 0) &&
5887                        (wlanevents[evt_code].parmsize != evt_sz))
5888                goto _abort_event_;
5889
5890        atomic_inc(&pevt_priv->event_seq);
5891
5892        peventbuf += 2;
5893
5894        if (peventbuf) {
5895                event_callback = wlanevents[evt_code].event_callback;
5896                event_callback(padapter, (u8 *)peventbuf);
5897
5898                pevt_priv->evt_done_cnt++;
5899        }
5900
5901
5902_abort_event_:
5903
5904
5905        return H2C_SUCCESS;
5906
5907}
5908
5909u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
5910{
5911        if (!pbuf)
5912                return H2C_PARAMETERS_ERROR;
5913
5914        return H2C_SUCCESS;
5915}
5916
5917u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
5918{
5919        struct sta_info *psta_bmc;
5920        struct list_head *xmitframe_plist, *xmitframe_phead, *tmp;
5921        struct xmit_frame *pxmitframe = NULL;
5922        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
5923        struct sta_priv  *pstapriv = &padapter->stapriv;
5924
5925        /* for BC/MC Frames */
5926        psta_bmc = rtw_get_bcmc_stainfo(padapter);
5927        if (!psta_bmc)
5928                return H2C_SUCCESS;
5929
5930        if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
5931                msleep(10);/*  10ms, ATIM(HIQ) Windows */
5932
5933                /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
5934                spin_lock_bh(&pxmitpriv->lock);
5935
5936                xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
5937                list_for_each_safe(xmitframe_plist, tmp, xmitframe_phead) {
5938                        pxmitframe = list_entry(xmitframe_plist,
5939                                                struct xmit_frame, list);
5940
5941                        list_del_init(&pxmitframe->list);
5942
5943                        psta_bmc->sleepq_len--;
5944                        if (psta_bmc->sleepq_len > 0)
5945                                pxmitframe->attrib.mdata = 1;
5946                        else
5947                                pxmitframe->attrib.mdata = 0;
5948
5949                        pxmitframe->attrib.triggered = 1;
5950
5951                        if (xmitframe_hiq_filter(pxmitframe))
5952                                pxmitframe->attrib.qsel = 0x11;/* HIQ */
5953
5954                        rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
5955                }
5956
5957                /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
5958                spin_unlock_bh(&pxmitpriv->lock);
5959
5960                /* check hi queue and bmc_sleepq */
5961                rtw_chk_hi_queue_cmd(padapter);
5962        }
5963
5964        return H2C_SUCCESS;
5965}
5966
5967u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
5968{
5969        if (send_beacon(padapter) == _FAIL)
5970                return H2C_PARAMETERS_ERROR;
5971
5972        /* tx bc/mc frames after update TIM */
5973        chk_bmc_sleepq_hdl(padapter, NULL);
5974
5975        return H2C_SUCCESS;
5976}
5977
5978int rtw_chk_start_clnt_join(struct adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
5979{
5980        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5981        unsigned char cur_ch = pmlmeext->cur_channel;
5982        unsigned char cur_bw = pmlmeext->cur_bwmode;
5983        unsigned char cur_ch_offset = pmlmeext->cur_ch_offset;
5984        bool connect_allow = true;
5985
5986        if (!ch || !bw || !offset) {
5987                rtw_warn_on(1);
5988                connect_allow = false;
5989        }
5990
5991        if (connect_allow) {
5992                *ch = cur_ch;
5993                *bw = cur_bw;
5994                *offset = cur_ch_offset;
5995        }
5996
5997        return connect_allow ? _SUCCESS : _FAIL;
5998}
5999
6000/* Find union about ch, bw, ch_offset of all linked/linking interfaces */
6001int rtw_get_ch_setting_union(struct adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
6002{
6003        struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
6004        struct adapter *iface;
6005
6006        if (ch)
6007                *ch = 0;
6008        if (bw)
6009                *bw = CHANNEL_WIDTH_20;
6010        if (offset)
6011                *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6012
6013        iface = dvobj->padapters;
6014
6015        if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING))
6016                return 0;
6017
6018        return 1;
6019}
6020
6021u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
6022{
6023        struct set_ch_parm *set_ch_parm;
6024        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6025
6026        if (!pbuf)
6027                return H2C_PARAMETERS_ERROR;
6028
6029        set_ch_parm = (struct set_ch_parm *)pbuf;
6030
6031        pmlmeext->cur_channel = set_ch_parm->ch;
6032        pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
6033        pmlmeext->cur_bwmode = set_ch_parm->bw;
6034
6035        set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
6036
6037        return  H2C_SUCCESS;
6038}
6039
6040u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
6041{
6042        struct SetChannelPlan_param *setChannelPlan_param;
6043        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6044
6045        if (!pbuf)
6046                return H2C_PARAMETERS_ERROR;
6047
6048        setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
6049
6050        pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
6051        init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
6052
6053        if (padapter->rtw_wdev && padapter->rtw_wdev->wiphy) {
6054                struct regulatory_request request;
6055
6056                request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
6057                rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request);
6058        }
6059
6060        return  H2C_SUCCESS;
6061}
6062
6063u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
6064{
6065        return  H2C_REJECTED;
6066}
6067
6068/*  TDLS_ESTABLISHED    : write RCR DATA BIT */
6069/*  TDLS_CS_OFF         : go back to the channel linked with AP, terminating channel switch procedure */
6070/*  TDLS_INIT_CH_SEN    : init channel sensing, receive all data and mgnt frame */
6071/*  TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
6072/*  TDLS_OFF_CH         : first time set channel to off channel */
6073/*  TDLS_BASE_CH                : go back tp the channel linked with AP when set base channel as target channel */
6074/*  TDLS_P_OFF_CH       : periodically go to off channel */
6075/*  TDLS_P_BASE_CH      : periodically go back to base channel */
6076/*  TDLS_RS_RCR         : restore RCR */
6077/*  TDLS_TEAR_STA       : free tdls sta */
6078u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
6079{
6080        return H2C_REJECTED;
6081}
6082
6083u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf)
6084{
6085        struct RunInThread_param *p;
6086
6087
6088        if (NULL == pbuf)
6089                return H2C_PARAMETERS_ERROR;
6090        p = (struct RunInThread_param *)pbuf;
6091
6092        if (p->func)
6093                p->func(p->context);
6094
6095        return H2C_SUCCESS;
6096}
6097