linux/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 * more details.
  13 *
  14 * You should have received a copy of the GNU General Public License along with
  15 * this program; if not, write to the Free Software Foundation, Inc.,
  16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17 *
  18 *
  19 ******************************************************************************/
  20#define _RTW_MLME_EXT_C_
  21
  22#include <osdep_service.h>
  23#include <drv_types.h>
  24#include <wifi.h>
  25#include <rtw_mlme_ext.h>
  26#include <wlan_bssdef.h>
  27#include <mlme_osdep.h>
  28#include <recv_osdep.h>
  29
  30static struct mlme_handler mlme_sta_tbl[] = {
  31        {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
  32        {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
  33        {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
  34        {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
  35        {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
  36        {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
  37
  38        /*----------------------------------------------------------
  39                                        below 2 are reserved
  40        -----------------------------------------------------------*/
  41        {0,                                     "DoReserved",           &DoReserved},
  42        {0,                                     "DoReserved",           &DoReserved},
  43        {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
  44        {WIFI_ATIM,                     "OnATIM",               &OnAtim},
  45        {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
  46        {WIFI_AUTH,                     "OnAuth",               &OnAuthClient},
  47        {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
  48        {WIFI_ACTION,           "OnAction",             &OnAction},
  49};
  50
  51static struct action_handler OnAction_tbl[] = {
  52        {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,        "ACTION_SPECTRUM_MGMT", on_action_spct},
  53        {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
  54        {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
  55        {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
  56        {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
  57        {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
  58        {RTW_WLAN_CATEGORY_FT, "ACTION_FT",     &DoReserved},
  59        {RTW_WLAN_CATEGORY_HT,  "ACTION_HT",    &OnAction_ht},
  60        {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
  61        {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
  62        {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},
  63};
  64
  65
  66static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
  67
  68/**************************************************
  69OUI definitions for the vendor specific IE
  70***************************************************/
  71unsigned char   RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
  72unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
  73unsigned char   WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
  74unsigned char   P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
  75unsigned char   WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
  76
  77unsigned char   WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
  78unsigned char   WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
  79
  80unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
  81unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
  82
  83extern unsigned char REALTEK_96B_IE[];
  84
  85/********************************************************
  86MCS rate definitions
  87*********************************************************/
  88unsigned char   MCS_rate_2R[16] = {0xff, 0xff, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
  89unsigned char   MCS_rate_1R[16] = {0xff, 0x00, 0x0, 0x0, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
  90
  91/********************************************************
  92ChannelPlan definitions
  93*********************************************************/
  94static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
  95        {{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 */
  96        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
  97        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},                      /*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
  98        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
  99        {{10, 11, 12, 13}, 4},                                  /*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
 100        {{}, 0},                                                                        /*  0x05, RT_CHANNEL_DOMAIN_2G_NULL */
 101};
 102
 103static struct rt_channel_plan_map       RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
 104        /*  0x00 ~ 0x1F , Old Define ===== */
 105        {0x02}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */
 106        {0x02}, /* 0x01, RT_CHANNEL_DOMAIN_IC */
 107        {0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
 108        {0x01}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
 109        {0x01}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
 110        {0x03}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */
 111        {0x03}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
 112        {0x01}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
 113        {0x03}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
 114        {0x03}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
 115        {0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
 116        {0x02}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
 117        {0x01}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
 118        {0x02}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
 119        {0x02}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
 120        {0x02}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
 121        {0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
 122        {0x02}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
 123        {0x01}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
 124        {0x00}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
 125        {0x02}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
 126        {0x00}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
 127        {0x00}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
 128        {0x03}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
 129        {0x05}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
 130        {0x02}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
 131        {0x00}, /* 0x1A, */
 132        {0x00}, /* 0x1B, */
 133        {0x00}, /* 0x1C, */
 134        {0x00}, /* 0x1D, */
 135        {0x00}, /* 0x1E, */
 136        {0x05}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
 137        /*  0x20 ~ 0x7F , New Define ===== */
 138        {0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
 139        {0x01}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
 140        {0x02}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
 141        {0x03}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
 142        {0x04}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
 143        {0x02}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
 144        {0x00}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
 145        {0x03}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
 146        {0x00}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
 147        {0x00}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
 148        {0x00}, /* 0x2A, */
 149        {0x00}, /* 0x2B, */
 150        {0x00}, /* 0x2C, */
 151        {0x00}, /* 0x2D, */
 152        {0x00}, /* 0x2E, */
 153        {0x00}, /* 0x2F, */
 154        {0x00}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
 155        {0x00}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
 156        {0x00}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
 157        {0x00}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
 158        {0x02}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
 159        {0x00}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
 160        {0x00}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
 161        {0x03}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
 162        {0x03}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
 163        {0x02}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
 164        {0x00}, /* 0x3A, */
 165        {0x00}, /* 0x3B, */
 166        {0x00}, /* 0x3C, */
 167        {0x00}, /* 0x3D, */
 168        {0x00}, /* 0x3E, */
 169        {0x00}, /* 0x3F, */
 170        {0x02}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
 171        {0x03}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G */
 172};
 173
 174static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03}; /* use the conbination for max channel numbers */
 175
 176/*
 177 * Search the @param channel_num in given @param channel_set
 178 * @ch_set: the given channel set
 179 * @ch: the given channel number
 180 *
 181 * return the index of channel_num in channel_set, -1 if not found
 182 */
 183int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch)
 184{
 185        int i;
 186        for (i = 0; ch_set[i].ChannelNum != 0; i++) {
 187                if (ch == ch_set[i].ChannelNum)
 188                        break;
 189        }
 190
 191        if (i >= ch_set[i].ChannelNum)
 192                return -1;
 193        return i;
 194}
 195
 196/****************************************************************************
 197
 198Following are the initialization functions for WiFi MLME
 199
 200*****************************************************************************/
 201
 202int init_hw_mlme_ext(struct adapter *padapter)
 203{
 204        struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 205
 206        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
 207        return _SUCCESS;
 208}
 209
 210static void init_mlme_ext_priv_value(struct adapter *padapter)
 211{
 212        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 213        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 214        unsigned char   mixed_datarate[NumRates] = {
 215                _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
 216                _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_,
 217                 _48M_RATE_, _54M_RATE_, 0xff
 218        };
 219        unsigned char   mixed_basicrate[NumRates] = {
 220                _1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,
 221                _12M_RATE_, _24M_RATE_, 0xff,
 222        };
 223
 224        ATOMIC_SET(&pmlmeext->event_seq, 0);
 225        pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
 226
 227        pmlmeext->cur_channel = padapter->registrypriv.channel;
 228        pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
 229        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 230        pmlmeext->oper_channel = pmlmeext->cur_channel ;
 231        pmlmeext->oper_bwmode = pmlmeext->cur_bwmode;
 232        pmlmeext->oper_ch_offset = pmlmeext->cur_ch_offset;
 233        pmlmeext->retry = 0;
 234
 235        pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
 236
 237        memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
 238        memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
 239
 240        pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
 241
 242        pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
 243        pmlmeext->sitesurvey_res.channel_idx = 0;
 244        pmlmeext->sitesurvey_res.bss_cnt = 0;
 245        pmlmeext->scan_abort = false;
 246
 247        pmlmeinfo->state = WIFI_FW_NULL_STATE;
 248        pmlmeinfo->reauth_count = 0;
 249        pmlmeinfo->reassoc_count = 0;
 250        pmlmeinfo->link_count = 0;
 251        pmlmeinfo->auth_seq = 0;
 252        pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
 253        pmlmeinfo->key_index = 0;
 254        pmlmeinfo->iv = 0;
 255
 256        pmlmeinfo->enc_algo = _NO_PRIVACY_;
 257        pmlmeinfo->authModeToggle = 0;
 258
 259        _rtw_memset(pmlmeinfo->chg_txt, 0, 128);
 260
 261        pmlmeinfo->slotTime = SHORT_SLOT_TIME;
 262        pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
 263
 264        pmlmeinfo->dialogToken = 0;
 265
 266        pmlmeext->action_public_rxseq = 0xffff;
 267        pmlmeext->action_public_dialog_token = 0xff;
 268}
 269
 270static int has_channel(struct rt_channel_info *channel_set,
 271                                           u8 chanset_size,
 272                                           u8 chan) {
 273        int i;
 274
 275        for (i = 0; i < chanset_size; i++) {
 276                if (channel_set[i].ChannelNum == chan)
 277                        return 1;
 278        }
 279        return 0;
 280}
 281
 282static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set,
 283                                                          u8 chanset_size,
 284                                                          struct p2p_channels *channel_list) {
 285        struct p2p_oper_class_map op_class[] = {
 286                { IEEE80211G,  81,   1,  13,  1, BW20 },
 287                { IEEE80211G,  82,  14,  14,  1, BW20 },
 288                { -1, 0, 0, 0, 0, BW20 }
 289        };
 290
 291        int cla, op;
 292
 293        cla = 0;
 294
 295        for (op = 0; op_class[op].op_class; op++) {
 296                u8 ch;
 297                struct p2p_oper_class_map *o = &op_class[op];
 298                struct p2p_reg_class *reg = NULL;
 299
 300                for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
 301                        if (!has_channel(channel_set, chanset_size, ch)) {
 302                                continue;
 303                        }
 304
 305                        if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
 306                                continue;
 307
 308                        if ((0 == (padapter->registrypriv.cbw40_enable & BIT(1))) &&
 309                            ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
 310                                continue;
 311
 312                        if (reg == NULL) {
 313                                reg = &channel_list->reg_class[cla];
 314                                cla++;
 315                                reg->reg_class = o->op_class;
 316                                reg->channels = 0;
 317                        }
 318                        reg->channel[reg->channels] = ch;
 319                        reg->channels++;
 320                }
 321        }
 322        channel_list->reg_classes = cla;
 323}
 324
 325static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set)
 326{
 327        u8 index, chanset_size = 0;
 328        u8 b2_4GBand = false;
 329        u8 Index2G = 0;
 330
 331        _rtw_memset(channel_set, 0, sizeof(struct rt_channel_info) * MAX_CHANNEL_NUM);
 332
 333        if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
 334                DBG_88E("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
 335                return chanset_size;
 336        }
 337
 338        if (padapter->registrypriv.wireless_mode & WIRELESS_11G) {
 339                b2_4GBand = true;
 340                if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
 341                        Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
 342                else
 343                        Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
 344        }
 345
 346        if (b2_4GBand) {
 347                for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
 348                        channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
 349
 350                        if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */
 351                            (RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN_2G == ChannelPlan)) {
 352                                if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
 353                                        channel_set[chanset_size].ScanType = SCAN_ACTIVE;
 354                                else if ((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
 355                                        channel_set[chanset_size].ScanType  = SCAN_PASSIVE;
 356                        } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan ||
 357                                   RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) {/*  channel 12~13, passive scan */
 358                                if (channel_set[chanset_size].ChannelNum <= 11)
 359                                        channel_set[chanset_size].ScanType = SCAN_ACTIVE;
 360                                else
 361                                        channel_set[chanset_size].ScanType = SCAN_PASSIVE;
 362                        } else {
 363                                channel_set[chanset_size].ScanType = SCAN_ACTIVE;
 364                        }
 365
 366                        chanset_size++;
 367                }
 368        }
 369        return chanset_size;
 370}
 371
 372int     init_mlme_ext_priv(struct adapter *padapter)
 373{
 374        int     res = _SUCCESS;
 375        struct registry_priv *pregistrypriv = &padapter->registrypriv;
 376        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 377        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
 378        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 379
 380        pmlmeext->padapter = padapter;
 381
 382        init_mlme_ext_priv_value(padapter);
 383        pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
 384
 385        init_mlme_ext_timer(padapter);
 386
 387#ifdef CONFIG_88EU_AP_MODE
 388        init_mlme_ap_info(padapter);
 389#endif
 390
 391        pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
 392        init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
 393
 394        pmlmeext->chan_scan_time = SURVEY_TO;
 395        pmlmeext->mlmeext_init = true;
 396
 397
 398        pmlmeext->active_keep_alive_check = true;
 399
 400        return res;
 401}
 402
 403void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
 404{
 405        struct adapter *padapter = pmlmeext->padapter;
 406
 407        if (!padapter)
 408                return;
 409
 410        if (padapter->bDriverStopped) {
 411                _cancel_timer_ex(&pmlmeext->survey_timer);
 412                _cancel_timer_ex(&pmlmeext->link_timer);
 413                /* _cancel_timer_ex(&pmlmeext->ADDBA_timer); */
 414        }
 415}
 416
 417static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
 418{
 419        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 420        u8 *pframe = precv_frame->u.hdr.rx_data;
 421
 422          if (ptable->func) {
 423         /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
 424                if (!_rtw_memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
 425                    !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
 426                        return;
 427                ptable->func(padapter, precv_frame);
 428        }
 429}
 430
 431void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
 432{
 433        int index;
 434        struct mlme_handler *ptable;
 435#ifdef CONFIG_88EU_AP_MODE
 436        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 437#endif /* CONFIG_88EU_AP_MODE */
 438        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 439        u8 *pframe = precv_frame->u.hdr.rx_data;
 440        struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
 441
 442        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 443                 ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n",
 444                  GetFrameType(pframe), GetFrameSubType(pframe)));
 445
 446        if (GetFrameType(pframe) != WIFI_MGT_TYPE) {
 447                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe)));
 448                return;
 449        }
 450
 451        /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
 452        if (!_rtw_memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
 453            !_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
 454                return;
 455
 456        ptable = mlme_sta_tbl;
 457
 458        index = GetFrameSubType(pframe) >> 4;
 459
 460        if (index > 13) {
 461                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type=%d\n", index));
 462                return;
 463        }
 464        ptable += index;
 465
 466        if (psta != NULL) {
 467                if (GetRetry(pframe)) {
 468                        if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {
 469                                /* drop the duplicate management frame */
 470                                DBG_88E("Drop duplicate management frame with seq_num=%d.\n", precv_frame->u.hdr.attrib.seq_num);
 471                                return;
 472                        }
 473                }
 474                psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
 475        }
 476
 477#ifdef CONFIG_88EU_AP_MODE
 478        switch (GetFrameSubType(pframe)) {
 479        case WIFI_AUTH:
 480                if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 481                        ptable->func = &OnAuth;
 482                else
 483                        ptable->func = &OnAuthClient;
 484                /* fall through */
 485        case WIFI_ASSOCREQ:
 486        case WIFI_REASSOCREQ:
 487                _mgt_dispatcher(padapter, ptable, precv_frame);
 488                break;
 489        case WIFI_PROBEREQ:
 490                if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 491                        _mgt_dispatcher(padapter, ptable, precv_frame);
 492                else
 493                        _mgt_dispatcher(padapter, ptable, precv_frame);
 494                break;
 495        case WIFI_BEACON:
 496                _mgt_dispatcher(padapter, ptable, precv_frame);
 497                break;
 498        case WIFI_ACTION:
 499                _mgt_dispatcher(padapter, ptable, precv_frame);
 500                break;
 501        default:
 502                _mgt_dispatcher(padapter, ptable, precv_frame);
 503                if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 504                        rtw_hostapd_mlme_rx(padapter, precv_frame);
 505                break;
 506        }
 507#else
 508        _mgt_dispatcher(padapter, ptable, precv_frame);
 509#endif
 510}
 511
 512#ifdef CONFIG_88EU_P2P
 513static u32 p2p_listen_state_process(struct adapter *padapter, unsigned char *da)
 514{
 515        bool response = true;
 516
 517        /*      do nothing if the device name is empty */
 518        if (!padapter->wdinfo.device_name_len)
 519                response = false;
 520
 521        if (response)
 522                issue_probersp_p2p(padapter, da);
 523
 524        return _SUCCESS;
 525}
 526#endif /* CONFIG_88EU_P2P */
 527
 528
 529/****************************************************************************
 530
 531Following are the callback functions for each subtype of the management frames
 532
 533*****************************************************************************/
 534
 535unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
 536{
 537        unsigned int    ielen;
 538        unsigned char   *p;
 539        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 540        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 541        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 542        struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
 543        u8 *pframe = precv_frame->u.hdr.rx_data;
 544        uint len = precv_frame->u.hdr.len;
 545        u8 is_valid_p2p_probereq = false;
 546
 547#ifdef CONFIG_88EU_P2P
 548        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
 549        u8 wifi_test_chk_rate = 1;
 550
 551        if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
 552            !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) &&
 553            !rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
 554            !rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
 555            !rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)) {
 556                /*      mcs_rate = 0 -> CCK 1M rate */
 557                /*      mcs_rate = 1 -> CCK 2M rate */
 558                /*      mcs_rate = 2 -> CCK 5.5M rate */
 559                /*      mcs_rate = 3 -> CCK 11M rate */
 560                /*      In the P2P mode, the driver should not support the CCK rate */
 561
 562                /*      Commented by Kurt 2012/10/16 */
 563                /*      IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client */
 564                if (wifi_test_chk_rate == 1) {
 565                        is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len);
 566                        if (is_valid_p2p_probereq) {
 567                                if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE)) {
 568                                        /*  FIXME */
 569                                        report_survey_event(padapter, precv_frame);
 570                                        p2p_listen_state_process(padapter,  get_sa(pframe));
 571
 572                                        return _SUCCESS;
 573                                }
 574
 575                                if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
 576                                        goto _continue;
 577                        }
 578                }
 579        }
 580
 581_continue:
 582#endif /* CONFIG_88EU_P2P */
 583
 584        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 585                return _SUCCESS;
 586
 587        if (!check_fwstate(pmlmepriv, _FW_LINKED) &&
 588            !check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
 589                return _SUCCESS;
 590
 591        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
 592                        len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
 593
 594        /* check (wildcard) SSID */
 595        if (p != NULL) {
 596                if (is_valid_p2p_probereq)
 597                        goto _issue_probersp;
 598
 599                if ((ielen != 0 && !_rtw_memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) ||
 600                    (ielen == 0 && pmlmeinfo->hidden_ssid_mode))
 601                        return _SUCCESS;
 602
 603_issue_probersp:
 604
 605                if (check_fwstate(pmlmepriv, _FW_LINKED) &&
 606                    pmlmepriv->cur_network.join_res)
 607                        issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
 608        }
 609        return _SUCCESS;
 610}
 611
 612unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
 613{
 614        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 615#ifdef CONFIG_88EU_P2P
 616        struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
 617        u8 *pframe = precv_frame->u.hdr.rx_data;
 618#endif
 619
 620#ifdef CONFIG_88EU_P2P
 621        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
 622                if (pwdinfo->tx_prov_disc_info.benable) {
 623                        if (_rtw_memcmp(pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
 624                                if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
 625                                        pwdinfo->tx_prov_disc_info.benable = false;
 626                                        issue_p2p_provision_request(padapter,
 627                                                                    pwdinfo->tx_prov_disc_info.ssid.Ssid,
 628                                                                    pwdinfo->tx_prov_disc_info.ssid.SsidLength,
 629                                                                    pwdinfo->tx_prov_disc_info.peerDevAddr);
 630                                } else if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
 631                                        pwdinfo->tx_prov_disc_info.benable = false;
 632                                        issue_p2p_provision_request(padapter, NULL, 0,
 633                                                                    pwdinfo->tx_prov_disc_info.peerDevAddr);
 634                                }
 635                        }
 636                }
 637                return _SUCCESS;
 638        } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
 639                if (pwdinfo->nego_req_info.benable) {
 640                        DBG_88E("[%s] P2P State is GONEGO ING!\n", __func__);
 641                        if (_rtw_memcmp(pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
 642                                pwdinfo->nego_req_info.benable = false;
 643                                issue_p2p_GO_request(padapter, pwdinfo->nego_req_info.peerDevAddr);
 644                        }
 645                }
 646        } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ)) {
 647                if (pwdinfo->invitereq_info.benable) {
 648                        DBG_88E("[%s] P2P_STATE_TX_INVITE_REQ!\n", __func__);
 649                        if (_rtw_memcmp(pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN)) {
 650                                pwdinfo->invitereq_info.benable = false;
 651                                issue_p2p_invitation_request(padapter, pwdinfo->invitereq_info.peer_macaddr);
 652                        }
 653                }
 654        }
 655#endif
 656
 657
 658        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
 659                report_survey_event(padapter, precv_frame);
 660                return _SUCCESS;
 661        }
 662
 663        return _SUCCESS;
 664}
 665
 666unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
 667{
 668        int cam_idx;
 669        struct sta_info *psta;
 670        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 671        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 672        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 673        struct sta_priv *pstapriv = &padapter->stapriv;
 674        u8 *pframe = precv_frame->u.hdr.rx_data;
 675        uint len = precv_frame->u.hdr.len;
 676        struct wlan_bssid_ex *pbss;
 677        int ret = _SUCCESS;
 678
 679        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
 680                report_survey_event(padapter, precv_frame);
 681                return _SUCCESS;
 682        }
 683
 684        if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
 685                if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
 686                        /* we should update current network before auth, or some IE is wrong */
 687                        pbss = (struct wlan_bssid_ex *)rtw_malloc(sizeof(struct wlan_bssid_ex));
 688                        if (pbss) {
 689                                if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
 690                                        update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
 691                                        rtw_get_bcn_info(&(pmlmepriv->cur_network));
 692                                }
 693                                kfree(pbss);
 694                        }
 695
 696                        /* check the vendor of the assoc AP */
 697                        pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), len-sizeof(struct rtw_ieee80211_hdr_3addr));
 698
 699                        /* update TSF Value */
 700                        update_TSF(pmlmeext, pframe, len);
 701
 702                        /* start auth */
 703                        start_clnt_auth(padapter);
 704
 705                        return _SUCCESS;
 706                }
 707
 708                if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
 709                        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
 710                        if (psta != NULL) {
 711                                ret = rtw_check_bcn_info(padapter, pframe, len);
 712                                if (!ret) {
 713                                                DBG_88E_LEVEL(_drv_info_, "ap has changed, disconnect now\n ");
 714                                                receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 65535);
 715                                                return _SUCCESS;
 716                                }
 717                                /* update WMM, ERP in the beacon */
 718                                /* todo: the timer is used instead of the number of the beacon received */
 719                                if ((sta_rx_pkts(psta) & 0xf) == 0)
 720                                        update_beacon_info(padapter, pframe, len, psta);
 721                                process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
 722                        }
 723                } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
 724                        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
 725                        if (psta != NULL) {
 726                                /* update WMM, ERP in the beacon */
 727                                /* todo: the timer is used instead of the number of the beacon received */
 728                                if ((sta_rx_pkts(psta) & 0xf) == 0)
 729                                        update_beacon_info(padapter, pframe, len, psta);
 730                        } else {
 731                                /* allocate a new CAM entry for IBSS station */
 732                                cam_idx = allocate_fw_sta_entry(padapter);
 733                                if (cam_idx == NUM_STA)
 734                                        goto _END_ONBEACON_;
 735
 736                                /* get supported rate */
 737                                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) {
 738                                        pmlmeinfo->FW_sta_info[cam_idx].status = 0;
 739                                        goto _END_ONBEACON_;
 740                                }
 741
 742                                /* update TSF Value */
 743                                update_TSF(pmlmeext, pframe, len);
 744
 745                                /* report sta add event */
 746                                report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
 747                        }
 748                }
 749        }
 750
 751_END_ONBEACON_:
 752
 753        return _SUCCESS;
 754}
 755
 756unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
 757{
 758#ifdef CONFIG_88EU_AP_MODE
 759        unsigned long irqL;
 760        unsigned int    auth_mode, ie_len;
 761        u16 seq;
 762        unsigned char   *sa, *p;
 763        u16 algorithm;
 764        int     status;
 765        static struct sta_info stat;
 766        struct  sta_info        *pstat = NULL;
 767        struct  sta_priv *pstapriv = &padapter->stapriv;
 768        struct security_priv *psecuritypriv = &padapter->securitypriv;
 769        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 770        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 771        u8 *pframe = precv_frame->u.hdr.rx_data;
 772        uint len = precv_frame->u.hdr.len;
 773
 774        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
 775                return _FAIL;
 776
 777        DBG_88E("+OnAuth\n");
 778
 779        sa = GetAddr2Ptr(pframe);
 780
 781        auth_mode = psecuritypriv->dot11AuthAlgrthm;
 782        seq = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + 2));
 783        algorithm = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN));
 784
 785        DBG_88E("auth alg=%x, seq=%X\n", algorithm, seq);
 786
 787        if (auth_mode == 2 && psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
 788            psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
 789                auth_mode = 0;
 790
 791        if ((algorithm > 0 && auth_mode == 0) ||        /*  rx a shared-key auth but shared not enabled */
 792            (algorithm == 0 && auth_mode == 1)) {       /*  rx a open-system auth but shared-key is enabled */
 793                DBG_88E("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",
 794                        algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
 795
 796                status = _STATS_NO_SUPP_ALG_;
 797
 798                goto auth_fail;
 799        }
 800
 801        if (!rtw_access_ctrl(padapter, sa)) {
 802                status = _STATS_UNABLE_HANDLE_STA_;
 803                goto auth_fail;
 804        }
 805
 806        pstat = rtw_get_stainfo(pstapriv, sa);
 807        if (pstat == NULL) {
 808                /*  allocate a new one */
 809                DBG_88E("going to alloc stainfo for sa=%pM\n", sa);
 810                pstat = rtw_alloc_stainfo(pstapriv, sa);
 811                if (pstat == NULL) {
 812                        DBG_88E(" Exceed the upper limit of supported clients...\n");
 813                        status = _STATS_UNABLE_HANDLE_STA_;
 814                        goto auth_fail;
 815                }
 816
 817                pstat->state = WIFI_FW_AUTH_NULL;
 818                pstat->auth_seq = 0;
 819        } else {
 820                _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
 821                if (!rtw_is_list_empty(&pstat->asoc_list)) {
 822                        rtw_list_delete(&pstat->asoc_list);
 823                        pstapriv->asoc_list_cnt--;
 824                }
 825                _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
 826
 827                if (seq == 1) {
 828                        /* TODO: STA re_auth and auth timeout */
 829                }
 830        }
 831
 832        _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
 833        if (rtw_is_list_empty(&pstat->auth_list)) {
 834                rtw_list_insert_tail(&pstat->auth_list, &pstapriv->auth_list);
 835                pstapriv->auth_list_cnt++;
 836        }
 837        _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
 838
 839        if (pstat->auth_seq == 0)
 840                pstat->expire_to = pstapriv->auth_to;
 841
 842        if ((pstat->auth_seq + 1) != seq) {
 843                DBG_88E("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
 844                        seq, pstat->auth_seq+1);
 845                status = _STATS_OUT_OF_AUTH_SEQ_;
 846                goto auth_fail;
 847        }
 848
 849        if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2)) {
 850                if (seq == 1) {
 851                        pstat->state &= ~WIFI_FW_AUTH_NULL;
 852                        pstat->state |= WIFI_FW_AUTH_SUCCESS;
 853                        pstat->expire_to = pstapriv->assoc_to;
 854                        pstat->authalg = algorithm;
 855                } else {
 856                        DBG_88E("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
 857                                seq, pstat->auth_seq+1);
 858                        status = _STATS_OUT_OF_AUTH_SEQ_;
 859                        goto auth_fail;
 860                }
 861        } else { /*  shared system or auto authentication */
 862                if (seq == 1) {
 863                        /* prepare for the challenging txt... */
 864
 865                        pstat->state &= ~WIFI_FW_AUTH_NULL;
 866                        pstat->state |= WIFI_FW_AUTH_STATE;
 867                        pstat->authalg = algorithm;
 868                        pstat->auth_seq = 2;
 869                } else if (seq == 3) {
 870                        /* checking for challenging txt... */
 871                        DBG_88E("checking for challenging txt...\n");
 872
 873                        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len,
 874                                        len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
 875
 876                        if ((p == NULL) || (ie_len <= 0)) {
 877                                DBG_88E("auth rejected because challenge failure!(1)\n");
 878                                status = _STATS_CHALLENGE_FAIL_;
 879                                goto auth_fail;
 880                        }
 881
 882                        if (_rtw_memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
 883                                pstat->state &= (~WIFI_FW_AUTH_STATE);
 884                                pstat->state |= WIFI_FW_AUTH_SUCCESS;
 885                                /*  challenging txt is correct... */
 886                                pstat->expire_to =  pstapriv->assoc_to;
 887                        } else {
 888                                DBG_88E("auth rejected because challenge failure!\n");
 889                                status = _STATS_CHALLENGE_FAIL_;
 890                                goto auth_fail;
 891                        }
 892                } else {
 893                        DBG_88E("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
 894                                seq, pstat->auth_seq+1);
 895                        status = _STATS_OUT_OF_AUTH_SEQ_;
 896                        goto auth_fail;
 897                }
 898        }
 899
 900        /*  Now, we are going to issue_auth... */
 901        pstat->auth_seq = seq + 1;
 902
 903#ifdef CONFIG_88EU_AP_MODE
 904        issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
 905#endif
 906
 907        if (pstat->state & WIFI_FW_AUTH_SUCCESS)
 908                pstat->auth_seq = 0;
 909
 910        return _SUCCESS;
 911
 912auth_fail:
 913
 914        if (pstat)
 915                rtw_free_stainfo(padapter , pstat);
 916
 917        pstat = &stat;
 918        _rtw_memset((char *)pstat, '\0', sizeof(stat));
 919        pstat->auth_seq = 2;
 920        memcpy(pstat->hwaddr, sa, 6);
 921
 922#ifdef CONFIG_88EU_AP_MODE
 923        issue_auth(padapter, pstat, (unsigned short)status);
 924#endif
 925
 926#endif
 927        return _FAIL;
 928}
 929
 930unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame)
 931{
 932        unsigned int    seq, len, status, offset;
 933        unsigned char   *p;
 934        unsigned int    go2asoc = 0;
 935        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
 936        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
 937        u8 *pframe = precv_frame->u.hdr.rx_data;
 938        uint pkt_len = precv_frame->u.hdr.len;
 939
 940        DBG_88E("%s\n", __func__);
 941
 942        /* check A1 matches or not */
 943        if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
 944                return _SUCCESS;
 945
 946        if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
 947                return _SUCCESS;
 948
 949        offset = (GetPrivacy(pframe)) ? 4 : 0;
 950
 951        seq     = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 2));
 952        status  = le16_to_cpu(*(__le16 *)((size_t)pframe + WLAN_HDR_A3_LEN + offset + 4));
 953
 954        if (status != 0) {
 955                DBG_88E("clnt auth fail, status: %d\n", status);
 956                if (status == 13) { /*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
 957                        if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
 958                                pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
 959                        else
 960                                pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
 961                }
 962
 963                set_link_timer(pmlmeext, 1);
 964                goto authclnt_fail;
 965        }
 966
 967        if (seq == 2) {
 968                if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
 969                         /*  legendary shared system */
 970                        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
 971                                pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
 972
 973                        if (p == NULL)
 974                                goto authclnt_fail;
 975
 976                        memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
 977                        pmlmeinfo->auth_seq = 3;
 978                        issue_auth(padapter, NULL, 0);
 979                        set_link_timer(pmlmeext, REAUTH_TO);
 980
 981                        return _SUCCESS;
 982                } else {
 983                        /*  open system */
 984                        go2asoc = 1;
 985                }
 986        } else if (seq == 4) {
 987                if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
 988                        go2asoc = 1;
 989                else
 990                        goto authclnt_fail;
 991        } else {
 992                /*  this is also illegal */
 993                goto authclnt_fail;
 994        }
 995
 996        if (go2asoc) {
 997                DBG_88E_LEVEL(_drv_info_, "auth success, start assoc\n");
 998                start_clnt_assoc(padapter);
 999                return _SUCCESS;
1000        }
1001authclnt_fail:
1002        return _FAIL;
1003}
1004
1005unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
1006{
1007#ifdef CONFIG_88EU_AP_MODE
1008        unsigned long irqL;
1009        u16 capab_info;
1010        struct rtw_ieee802_11_elems elems;
1011        struct sta_info *pstat;
1012        unsigned char           reassoc, *p, *pos, *wpa_ie;
1013        unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
1014        int             i, ie_len, wpa_ie_len, left;
1015        unsigned char           supportRate[16];
1016        int                                     supportRateNum;
1017        unsigned short          status = _STATS_SUCCESSFUL_;
1018        unsigned short          frame_type, ie_offset = 0;
1019        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1020        struct security_priv *psecuritypriv = &padapter->securitypriv;
1021        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1022        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1023        struct wlan_bssid_ex *cur = &(pmlmeinfo->network);
1024        struct sta_priv *pstapriv = &padapter->stapriv;
1025        u8 *pframe = precv_frame->u.hdr.rx_data;
1026        uint pkt_len = precv_frame->u.hdr.len;
1027#ifdef CONFIG_88EU_P2P
1028        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
1029        u8 p2p_status_code = P2P_STATUS_SUCCESS;
1030        u8 *p2pie;
1031        u32 p2pielen = 0;
1032#endif /* CONFIG_88EU_P2P */
1033
1034        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1035                return _FAIL;
1036
1037        frame_type = GetFrameSubType(pframe);
1038        if (frame_type == WIFI_ASSOCREQ) {
1039                reassoc = 0;
1040                ie_offset = _ASOCREQ_IE_OFFSET_;
1041        } else { /*  WIFI_REASSOCREQ */
1042                reassoc = 1;
1043                ie_offset = _REASOCREQ_IE_OFFSET_;
1044        }
1045
1046
1047        if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
1048                DBG_88E("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
1049                       "\n", reassoc, (unsigned long)pkt_len);
1050                return _FAIL;
1051        }
1052
1053        pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1054        if (pstat == (struct sta_info *)NULL) {
1055                status = _RSON_CLS2_;
1056                goto asoc_class2_error;
1057        }
1058
1059        capab_info = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN);
1060
1061        left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
1062        pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
1063
1064
1065        DBG_88E("%s\n", __func__);
1066
1067        /*  check if this stat has been successfully authenticated/assocated */
1068        if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
1069                if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
1070                        status = _RSON_CLS2_;
1071                        goto asoc_class2_error;
1072                } else {
1073                        pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1074                        pstat->state |= WIFI_FW_ASSOC_STATE;
1075                }
1076        } else {
1077                pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1078                pstat->state |= WIFI_FW_ASSOC_STATE;
1079        }
1080        pstat->capability = capab_info;
1081        /* now parse all ieee802_11 ie to point to elems */
1082        if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
1083            !elems.ssid) {
1084                DBG_88E("STA %pM sent invalid association request\n",
1085                        pstat->hwaddr);
1086                status = _STATS_FAILURE_;
1087                goto OnAssocReqFail;
1088        }
1089
1090
1091        /*  now we should check all the fields... */
1092        /*  checking SSID */
1093        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
1094                pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1095        if (p == NULL)
1096                status = _STATS_FAILURE_;
1097
1098        if (ie_len == 0) { /*  broadcast ssid, however it is not allowed in assocreq */
1099                status = _STATS_FAILURE_;
1100        } else {
1101                /*  check if ssid match */
1102                if (!_rtw_memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
1103                        status = _STATS_FAILURE_;
1104
1105                if (ie_len != cur->Ssid.SsidLength)
1106                        status = _STATS_FAILURE_;
1107        }
1108
1109        if (_STATS_SUCCESSFUL_ != status)
1110                goto OnAssocReqFail;
1111
1112        /*  check if the supported rate is ok */
1113        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1114        if (p == NULL) {
1115                DBG_88E("Rx a sta assoc-req which supported rate is empty!\n");
1116                /*  use our own rate set as statoin used */
1117                /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1118                /* supportRateNum = AP_BSSRATE_LEN; */
1119
1120                status = _STATS_FAILURE_;
1121                goto OnAssocReqFail;
1122        } else {
1123                memcpy(supportRate, p+2, ie_len);
1124                supportRateNum = ie_len;
1125
1126                p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &ie_len,
1127                                pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1128                if (p !=  NULL) {
1129                        if (supportRateNum <= sizeof(supportRate)) {
1130                                memcpy(supportRate+supportRateNum, p+2, ie_len);
1131                                supportRateNum += ie_len;
1132                        }
1133                }
1134        }
1135
1136        /* todo: mask supportRate between AP & STA -> move to update raid */
1137        /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1138
1139        /* update station supportRate */
1140        pstat->bssratelen = supportRateNum;
1141        memcpy(pstat->bssrateset, supportRate, supportRateNum);
1142        UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1143
1144        /* check RSN/WPA/WPS */
1145        pstat->dot8021xalg = 0;
1146        pstat->wpa_psk = 0;
1147        pstat->wpa_group_cipher = 0;
1148        pstat->wpa2_group_cipher = 0;
1149        pstat->wpa_pairwise_cipher = 0;
1150        pstat->wpa2_pairwise_cipher = 0;
1151        _rtw_memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1152        if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1153                int group_cipher = 0, pairwise_cipher = 0;
1154
1155                wpa_ie = elems.rsn_ie;
1156                wpa_ie_len = elems.rsn_ie_len;
1157
1158                if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1159                        pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1160                        pstat->wpa_psk |= BIT(1);
1161
1162                        pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
1163                        pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
1164
1165                        if (!pstat->wpa2_group_cipher)
1166                                status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1167
1168                        if (!pstat->wpa2_pairwise_cipher)
1169                                status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1170                } else {
1171                        status = WLAN_STATUS_INVALID_IE;
1172                }
1173        } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1174                int group_cipher = 0, pairwise_cipher = 0;
1175
1176                wpa_ie = elems.wpa_ie;
1177                wpa_ie_len = elems.wpa_ie_len;
1178
1179                if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1180                        pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1181                        pstat->wpa_psk |= BIT(0);
1182
1183                        pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
1184                        pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
1185
1186                        if (!pstat->wpa_group_cipher)
1187                                status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1188
1189                        if (!pstat->wpa_pairwise_cipher)
1190                                status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1191                } else {
1192                        status = WLAN_STATUS_INVALID_IE;
1193                }
1194        } else {
1195                wpa_ie = NULL;
1196                wpa_ie_len = 0;
1197        }
1198
1199        if (_STATS_SUCCESSFUL_ != status)
1200                goto OnAssocReqFail;
1201
1202        pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1203        if (wpa_ie == NULL) {
1204                if (elems.wps_ie) {
1205                        DBG_88E("STA included WPS IE in "
1206                                   "(Re)Association Request - assume WPS is "
1207                                   "used\n");
1208                        pstat->flags |= WLAN_STA_WPS;
1209                        /* wpabuf_free(sta->wps_ie); */
1210                        /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
1211                        /*                              elems.wps_ie_len - 4); */
1212                } else {
1213                        DBG_88E("STA did not include WPA/RSN IE "
1214                                   "in (Re)Association Request - possible WPS "
1215                                   "use\n");
1216                        pstat->flags |= WLAN_STA_MAYBE_WPS;
1217                }
1218
1219
1220                /*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1221                /*  that the selected registrar of AP is _FLASE */
1222                if ((psecuritypriv->wpa_psk > 0) && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
1223                        if (pmlmepriv->wps_beacon_ie) {
1224                                u8 selected_registrar = 0;
1225
1226                                rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR , &selected_registrar, NULL);
1227
1228                                if (!selected_registrar) {
1229                                        DBG_88E("selected_registrar is false , or AP is not ready to do WPS\n");
1230
1231                                        status = _STATS_UNABLE_HANDLE_STA_;
1232
1233                                        goto OnAssocReqFail;
1234                                }
1235                        }
1236                }
1237        } else {
1238                int copy_len;
1239
1240                if (psecuritypriv->wpa_psk == 0) {
1241                        DBG_88E("STA %pM: WPA/RSN IE in association "
1242                        "request, but AP don't support WPA/RSN\n", pstat->hwaddr);
1243
1244                        status = WLAN_STATUS_INVALID_IE;
1245
1246                        goto OnAssocReqFail;
1247                }
1248
1249                if (elems.wps_ie) {
1250                        DBG_88E("STA included WPS IE in "
1251                                   "(Re)Association Request - WPS is "
1252                                   "used\n");
1253                        pstat->flags |= WLAN_STA_WPS;
1254                        copy_len = 0;
1255                } else {
1256                        copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)) : (wpa_ie_len+2);
1257                }
1258                if (copy_len > 0)
1259                        memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
1260        }
1261        /*  check if there is WMM IE & support WWM-PS */
1262        pstat->flags &= ~WLAN_STA_WME;
1263        pstat->qos_option = 0;
1264        pstat->qos_info = 0;
1265        pstat->has_legacy_ac = true;
1266        pstat->uapsd_vo = 0;
1267        pstat->uapsd_vi = 0;
1268        pstat->uapsd_be = 0;
1269        pstat->uapsd_bk = 0;
1270        if (pmlmepriv->qospriv.qos_option) {
1271                p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
1272                for (;;) {
1273                        p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1274                        if (p != NULL) {
1275                                if (_rtw_memcmp(p+2, WMM_IE, 6)) {
1276                                        pstat->flags |= WLAN_STA_WME;
1277
1278                                        pstat->qos_option = 1;
1279                                        pstat->qos_info = *(p+8);
1280
1281                                        pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
1282
1283                                        if ((pstat->qos_info&0xf) != 0xf)
1284                                                pstat->has_legacy_ac = true;
1285                                        else
1286                                                pstat->has_legacy_ac = false;
1287
1288                                        if (pstat->qos_info&0xf) {
1289                                                if (pstat->qos_info&BIT(0))
1290                                                        pstat->uapsd_vo = BIT(0)|BIT(1);
1291                                                else
1292                                                        pstat->uapsd_vo = 0;
1293
1294                                                if (pstat->qos_info&BIT(1))
1295                                                        pstat->uapsd_vi = BIT(0)|BIT(1);
1296                                                else
1297                                                        pstat->uapsd_vi = 0;
1298
1299                                                if (pstat->qos_info&BIT(2))
1300                                                        pstat->uapsd_bk = BIT(0)|BIT(1);
1301                                                else
1302                                                        pstat->uapsd_bk = 0;
1303
1304                                                if (pstat->qos_info&BIT(3))
1305                                                        pstat->uapsd_be = BIT(0)|BIT(1);
1306                                                else
1307                                                        pstat->uapsd_be = 0;
1308                                        }
1309                                        break;
1310                                }
1311                        } else {
1312                                break;
1313                        }
1314                        p = p + ie_len + 2;
1315                }
1316        }
1317
1318        /* save HT capabilities in the sta object */
1319        _rtw_memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
1320        if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) {
1321                pstat->flags |= WLAN_STA_HT;
1322
1323                pstat->flags |= WLAN_STA_WME;
1324
1325                memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));
1326        } else {
1327                pstat->flags &= ~WLAN_STA_HT;
1328        }
1329        if ((!pmlmepriv->htpriv.ht_option) && (pstat->flags&WLAN_STA_HT)) {
1330                status = _STATS_FAILURE_;
1331                goto OnAssocReqFail;
1332        }
1333
1334        if ((pstat->flags & WLAN_STA_HT) &&
1335            ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1336            (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) {
1337                DBG_88E("HT: %pM tried to "
1338                        "use TKIP with HT association\n", pstat->hwaddr);
1339
1340                /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1341                /* goto OnAssocReqFail; */
1342        }
1343
1344        pstat->flags |= WLAN_STA_NONERP;
1345        for (i = 0; i < pstat->bssratelen; i++) {
1346                if ((pstat->bssrateset[i] & 0x7f) > 22) {
1347                        pstat->flags &= ~WLAN_STA_NONERP;
1348                        break;
1349                }
1350        }
1351
1352        if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1353                pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1354        else
1355                pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1356
1357
1358
1359        if (status != _STATS_SUCCESSFUL_)
1360                goto OnAssocReqFail;
1361
1362#ifdef CONFIG_88EU_P2P
1363        pstat->is_p2p_device = false;
1364        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
1365                p2pie = rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , NULL, &p2pielen);
1366                if (p2pie) {
1367                        pstat->is_p2p_device = true;
1368                        p2p_status_code = (u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat);
1369                        if (p2p_status_code > 0) {
1370                                pstat->p2p_status_code = p2p_status_code;
1371                                status = _STATS_CAP_FAIL_;
1372                                goto OnAssocReqFail;
1373                        }
1374                }
1375        }
1376        pstat->p2p_status_code = p2p_status_code;
1377#endif /* CONFIG_88EU_P2P */
1378
1379        /* TODO: identify_proprietary_vendor_ie(); */
1380        /*  Realtek proprietary IE */
1381        /*  identify if this is Broadcom sta */
1382        /*  identify if this is ralink sta */
1383        /*  Customer proprietary IE */
1384
1385        /* get a unique AID */
1386        if (pstat->aid > 0) {
1387                DBG_88E("  old AID %d\n", pstat->aid);
1388        } else {
1389                for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1390                        if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1391                                break;
1392
1393                /* if (pstat->aid > NUM_STA) { */
1394                if (pstat->aid > pstapriv->max_num_sta) {
1395                        pstat->aid = 0;
1396
1397                        DBG_88E("  no room for more AIDs\n");
1398
1399                        status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1400
1401                        goto OnAssocReqFail;
1402                } else {
1403                        pstapriv->sta_aid[pstat->aid - 1] = pstat;
1404                        DBG_88E("allocate new AID=(%d)\n", pstat->aid);
1405                }
1406        }
1407
1408        pstat->state &= (~WIFI_FW_ASSOC_STATE);
1409        pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1410
1411        _enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
1412        if (!rtw_is_list_empty(&pstat->auth_list)) {
1413                rtw_list_delete(&pstat->auth_list);
1414                pstapriv->auth_list_cnt--;
1415        }
1416        _exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
1417
1418        _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1419        if (rtw_is_list_empty(&pstat->asoc_list)) {
1420                pstat->expire_to = pstapriv->expire_to;
1421                rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1422                pstapriv->asoc_list_cnt++;
1423        }
1424        _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1425
1426        /*  now the station is qualified to join our BSS... */
1427        if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
1428#ifdef CONFIG_88EU_AP_MODE
1429                /* 1 bss_cap_update & sta_info_update */
1430                bss_cap_update_on_sta_join(padapter, pstat);
1431                sta_info_update(padapter, pstat);
1432
1433                /* issue assoc rsp before notify station join event. */
1434                if (frame_type == WIFI_ASSOCREQ)
1435                        issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1436                else
1437                        issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1438
1439                /* 2 - report to upper layer */
1440                DBG_88E("indicate_sta_join_event to upper layer - hostapd\n");
1441                rtw_indicate_sta_assoc_event(padapter, pstat);
1442
1443                /* 3-(1) report sta add event */
1444                report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
1445#endif
1446        }
1447
1448        return _SUCCESS;
1449
1450asoc_class2_error:
1451
1452#ifdef CONFIG_88EU_AP_MODE
1453        issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1454#endif
1455
1456        return _FAIL;
1457
1458OnAssocReqFail:
1459
1460
1461#ifdef CONFIG_88EU_AP_MODE
1462        pstat->aid = 0;
1463        if (frame_type == WIFI_ASSOCREQ)
1464                issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1465        else
1466                issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1467#endif
1468
1469
1470#endif /* CONFIG_88EU_AP_MODE */
1471
1472        return _FAIL;
1473}
1474
1475unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
1476{
1477        uint i;
1478        int res;
1479        unsigned short  status;
1480        struct ndis_802_11_var_ie *pIE;
1481        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1482        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1483        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1484        /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */
1485        u8 *pframe = precv_frame->u.hdr.rx_data;
1486        uint pkt_len = precv_frame->u.hdr.len;
1487
1488        DBG_88E("%s\n", __func__);
1489
1490        /* check A1 matches or not */
1491        if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1492                return _SUCCESS;
1493
1494        if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1495                return _SUCCESS;
1496
1497        if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1498                return _SUCCESS;
1499
1500        _cancel_timer_ex(&pmlmeext->link_timer);
1501
1502        /* status */
1503        status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
1504        if (status > 0) {
1505                DBG_88E("assoc reject, status code: %d\n", status);
1506                pmlmeinfo->state = WIFI_FW_NULL_STATE;
1507                res = -4;
1508                goto report_assoc_result;
1509        }
1510
1511        /* get capabilities */
1512        pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1513
1514        /* set slot time */
1515        pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
1516
1517        /* AID */
1518        pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
1519        res = pmlmeinfo->aid;
1520
1521        /* following are moved to join event callback function */
1522        /* to handle HT, WMM, rate adaptive, update MAC reg */
1523        /* for not to handle the synchronous IO in the tasklet */
1524        for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
1525                pIE = (struct ndis_802_11_var_ie *)(pframe + i);
1526
1527                switch (pIE->ElementID) {
1528                case _VENDOR_SPECIFIC_IE_:
1529                        if (_rtw_memcmp(pIE->data, WMM_PARA_OUI, 6))    /* WMM */
1530                                WMM_param_handler(padapter, pIE);
1531                        break;
1532                case _HT_CAPABILITY_IE_:        /* HT caps */
1533                        HT_caps_handler(padapter, pIE);
1534                        break;
1535                case _HT_EXTRA_INFO_IE_:        /* HT info */
1536                        HT_info_handler(padapter, pIE);
1537                        break;
1538                case _ERPINFO_IE_:
1539                        ERP_IE_handler(padapter, pIE);
1540                default:
1541                        break;
1542                }
1543
1544                i += (pIE->Length + 2);
1545        }
1546
1547        pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1548        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1549
1550        /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1551        UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
1552
1553report_assoc_result:
1554        if (res > 0) {
1555                rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
1556        } else {
1557                rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
1558        }
1559
1560        report_join_res(padapter, res);
1561
1562        return _SUCCESS;
1563}
1564
1565unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
1566{
1567        unsigned short  reason;
1568        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1569        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1570        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1571        u8 *pframe = precv_frame->u.hdr.rx_data;
1572#ifdef CONFIG_88EU_P2P
1573        struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
1574#endif /* CONFIG_88EU_P2P */
1575
1576        /* check A3 */
1577        if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
1578                return _SUCCESS;
1579
1580#ifdef CONFIG_88EU_P2P
1581        if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
1582                _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
1583                _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
1584        }
1585#endif /* CONFIG_88EU_P2P */
1586
1587        reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1588
1589        DBG_88E("%s Reason code(%d)\n", __func__, reason);
1590
1591#ifdef CONFIG_88EU_AP_MODE
1592        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1593                unsigned long irqL;
1594                struct sta_info *psta;
1595                struct sta_priv *pstapriv = &padapter->stapriv;
1596
1597                DBG_88E_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
1598                              reason, GetAddr2Ptr(pframe));
1599
1600                psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1601                if (psta) {
1602                        u8 updated = 0;
1603
1604                        _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1605                        if (!rtw_is_list_empty(&psta->asoc_list)) {
1606                                rtw_list_delete(&psta->asoc_list);
1607                                pstapriv->asoc_list_cnt--;
1608                                updated = ap_free_sta(padapter, psta, false, reason);
1609                        }
1610                        _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1611
1612                        associated_clients_update(padapter, updated);
1613                }
1614
1615
1616                return _SUCCESS;
1617        } else
1618#endif
1619        {
1620                DBG_88E_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM\n",
1621                              reason, GetAddr3Ptr(pframe));
1622
1623                receive_disconnect(padapter, GetAddr3Ptr(pframe) , reason);
1624        }
1625        pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1626        return _SUCCESS;
1627}
1628
1629unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame)
1630{
1631        u16 reason;
1632        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1633        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1634        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1635        u8 *pframe = precv_frame->u.hdr.rx_data;
1636#ifdef CONFIG_88EU_P2P
1637        struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
1638#endif /* CONFIG_88EU_P2P */
1639
1640        /* check A3 */
1641        if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
1642                return _SUCCESS;
1643
1644#ifdef CONFIG_88EU_P2P
1645        if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
1646                _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
1647                _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
1648        }
1649#endif /* CONFIG_88EU_P2P */
1650
1651        reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1652
1653        DBG_88E("%s Reason code(%d)\n", __func__, reason);
1654
1655#ifdef CONFIG_88EU_AP_MODE
1656        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1657                unsigned long irqL;
1658                struct sta_info *psta;
1659                struct sta_priv *pstapriv = &padapter->stapriv;
1660
1661                /* _enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
1662                /* rtw_free_stainfo(padapter, psta); */
1663                /* _exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL); */
1664
1665                DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
1666                              reason, GetAddr2Ptr(pframe));
1667
1668                psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1669                if (psta) {
1670                        u8 updated = 0;
1671
1672                        _enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1673                        if (!rtw_is_list_empty(&psta->asoc_list)) {
1674                                rtw_list_delete(&psta->asoc_list);
1675                                pstapriv->asoc_list_cnt--;
1676                                updated = ap_free_sta(padapter, psta, false, reason);
1677                        }
1678                        _exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
1679
1680                        associated_clients_update(padapter, updated);
1681                }
1682
1683                return _SUCCESS;
1684        } else
1685#endif
1686        {
1687                DBG_88E_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
1688                              reason, GetAddr3Ptr(pframe));
1689
1690                receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1691        }
1692        pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1693        return _SUCCESS;
1694}
1695
1696unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame)
1697{
1698        DBG_88E("%s\n", __func__);
1699        return _SUCCESS;
1700}
1701
1702unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame)
1703{
1704        unsigned int ret = _FAIL;
1705        struct sta_info *psta = NULL;
1706        struct sta_priv *pstapriv = &padapter->stapriv;
1707        u8 *pframe = precv_frame->u.hdr.rx_data;
1708        u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
1709        u8 category;
1710        u8 action;
1711
1712        DBG_88E(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
1713
1714        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1715
1716        if (!psta)
1717                goto exit;
1718
1719        category = frame_body[0];
1720        if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
1721                goto exit;
1722
1723        action = frame_body[1];
1724        switch (action) {
1725        case RTW_WLAN_ACTION_SPCT_MSR_REQ:
1726        case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
1727        case RTW_WLAN_ACTION_SPCT_TPC_REQ:
1728        case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
1729                break;
1730        case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
1731                break;
1732        default:
1733                break;
1734        }
1735
1736exit:
1737        return ret;
1738}
1739
1740unsigned int OnAction_qos(struct adapter *padapter, union recv_frame *precv_frame)
1741{
1742        return _SUCCESS;
1743}
1744
1745unsigned int OnAction_dls(struct adapter *padapter, union recv_frame *precv_frame)
1746{
1747        return _SUCCESS;
1748}
1749
1750unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame)
1751{
1752        u8 *addr;
1753        struct sta_info *psta = NULL;
1754        struct recv_reorder_ctrl *preorder_ctrl;
1755        unsigned char           *frame_body;
1756        unsigned char           category, action;
1757        unsigned short  tid, status, reason_code = 0;
1758        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
1759        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
1760        u8 *pframe = precv_frame->u.hdr.rx_data;
1761        struct sta_priv *pstapriv = &padapter->stapriv;
1762        /* check RA matches or not */
1763        if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
1764                return _SUCCESS;
1765
1766        DBG_88E("%s\n", __func__);
1767
1768        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1769                if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1770                        return _SUCCESS;
1771
1772        addr = GetAddr2Ptr(pframe);
1773        psta = rtw_get_stainfo(pstapriv, addr);
1774
1775        if (psta == NULL)
1776                return _SUCCESS;
1777
1778        frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
1779
1780        category = frame_body[0];
1781        if (category == RTW_WLAN_CATEGORY_BACK) { /*  representing Block Ack */
1782                if (!pmlmeinfo->HT_enable)
1783                        return _SUCCESS;
1784                action = frame_body[1];
1785                DBG_88E("%s, action=%d\n", __func__, action);
1786                switch (action) {
1787                case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
1788                        memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
1789                        process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
1790
1791                        if (pmlmeinfo->bAcceptAddbaReq)
1792                                issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
1793                        else
1794                                issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
1795                        break;
1796                case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
1797                        status = RTW_GET_LE16(&frame_body[3]);
1798                        tid = ((frame_body[5] >> 2) & 0x7);
1799                        if (status == 0) {      /* successful */
1800                                DBG_88E("agg_enable for TID=%d\n", tid);
1801                                psta->htpriv.agg_enable_bitmap |= 1 << tid;
1802                                psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1803                        } else {
1804                                psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1805                        }
1806                        break;
1807                case RTW_WLAN_ACTION_DELBA: /* DELBA */
1808                        if ((frame_body[3] & BIT(3)) == 0) {
1809                                psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
1810                                psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
1811                                reason_code = RTW_GET_LE16(&frame_body[4]);
1812                        } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
1813                                tid = (frame_body[3] >> 4) & 0x0F;
1814                                preorder_ctrl =  &psta->recvreorder_ctrl[tid];
1815                                preorder_ctrl->enable = false;
1816                                preorder_ctrl->indicate_seq = 0xffff;
1817                        }
1818                        DBG_88E("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code);
1819                        /* todo: how to notify the host while receiving DELETE BA */
1820                        break;
1821                default:
1822                        break;
1823                }
1824        }
1825        return _SUCCESS;
1826}
1827
1828#ifdef CONFIG_88EU_P2P
1829
1830static int get_reg_classes_full_count(struct p2p_channels *channel_list)
1831{
1832        int cnt = 0;
1833        int i;
1834
1835        for (i = 0; i < channel_list->reg_classes; i++) {
1836                cnt += channel_list->reg_class[i].channels;
1837        }
1838
1839        return cnt;
1840}
1841
1842void issue_p2p_GO_request(struct adapter *padapter, u8 *raddr)
1843{
1844        unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
1845        u8 action = P2P_PUB_ACTION_ACTION;
1846        __be32 p2poui = cpu_to_be32(P2POUI);
1847        u8 oui_subtype = P2P_GO_NEGO_REQ;
1848        u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
1849        u8 wpsielen = 0, p2pielen = 0;
1850        u16 len_channellist_attr = 0;
1851        struct xmit_frame *pmgntframe;
1852        struct pkt_attrib *pattrib;
1853        unsigned char *pframe;
1854        struct rtw_ieee80211_hdr        *pwlanhdr;
1855        unsigned short *fctrl;
1856        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
1857        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
1858        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
1859
1860        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
1861        if (pmgntframe == NULL)
1862                return;
1863
1864        DBG_88E("[%s] In\n", __func__);
1865        /* update attribute */
1866        pattrib = &pmgntframe->attrib;
1867        update_mgntframe_attrib(padapter, pattrib);
1868
1869        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
1870
1871        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
1872        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
1873
1874        fctrl = &(pwlanhdr->frame_ctl);
1875        *(fctrl) = 0;
1876
1877        memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
1878        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
1879        memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
1880
1881        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
1882        pmlmeext->mgnt_seq++;
1883        SetFrameSubType(pframe, WIFI_ACTION);
1884
1885        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
1886        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
1887
1888        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
1889        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
1890        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
1891        pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
1892        pwdinfo->negotiation_dialog_token = 1;  /*      Initialize the dialog value */
1893        pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &(pattrib->pktlen));
1894
1895
1896
1897        /*      WPS Section */
1898        wpsielen = 0;
1899        /*      WPS OUI */
1900        *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
1901        wpsielen += 4;
1902
1903        /*      WPS version */
1904        /*      Type: */
1905        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
1906        wpsielen += 2;
1907
1908        /*      Length: */
1909        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
1910        wpsielen += 2;
1911
1912        /*      Value: */
1913        wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
1914
1915        /*      Device Password ID */
1916        /*      Type: */
1917        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
1918        wpsielen += 2;
1919
1920        /*      Length: */
1921        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
1922        wpsielen += 2;
1923
1924        /*      Value: */
1925
1926        if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN)
1927                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
1928        else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN)
1929                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
1930        else if (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC)
1931                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
1932
1933        wpsielen += 2;
1934
1935        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
1936
1937
1938        /*      P2P IE Section. */
1939
1940        /*      P2P OUI */
1941        p2pielen = 0;
1942        p2pie[p2pielen++] = 0x50;
1943        p2pie[p2pielen++] = 0x6F;
1944        p2pie[p2pielen++] = 0x9A;
1945        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
1946
1947        /*      Commented by Albert 20110306 */
1948        /*      According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes */
1949        /*      1. P2P Capability */
1950        /*      2. Group Owner Intent */
1951        /*      3. Configuration Timeout */
1952        /*      4. Listen Channel */
1953        /*      5. Extended Listen Timing */
1954        /*      6. Intended P2P Interface Address */
1955        /*      7. Channel List */
1956        /*      8. P2P Device Info */
1957        /*      9. Operating Channel */
1958
1959
1960        /*      P2P Capability */
1961        /*      Type: */
1962        p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
1963
1964        /*      Length: */
1965        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
1966        p2pielen += 2;
1967
1968        /*      Value: */
1969        /*      Device Capability Bitmap, 1 byte */
1970        p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
1971
1972        /*      Group Capability Bitmap, 1 byte */
1973        if (pwdinfo->persistent_supported)
1974                p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
1975        else
1976                p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
1977
1978        /*      Group Owner Intent */
1979        /*      Type: */
1980        p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
1981
1982        /*      Length: */
1983        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
1984        p2pielen += 2;
1985
1986        /*      Value: */
1987        /*      Todo the tie breaker bit. */
1988        p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
1989
1990        /*      Configuration Timeout */
1991        /*      Type: */
1992        p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
1993
1994        /*      Length: */
1995        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
1996        p2pielen += 2;
1997
1998        /*      Value: */
1999        p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P GO */
2000        p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P Client */
2001
2002
2003        /*      Listen Channel */
2004        /*      Type: */
2005        p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
2006
2007        /*      Length: */
2008        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2009        p2pielen += 2;
2010
2011        /*      Value: */
2012        /*      Country String */
2013        p2pie[p2pielen++] = 'X';
2014        p2pie[p2pielen++] = 'X';
2015
2016        /*      The third byte should be set to 0x04. */
2017        /*      Described in the "Operating Channel Attribute" section. */
2018        p2pie[p2pielen++] = 0x04;
2019
2020        /*      Operating Class */
2021        p2pie[p2pielen++] = 0x51;       /*      Copy from SD7 */
2022
2023        /*      Channel Number */
2024        p2pie[p2pielen++] = pwdinfo->listen_channel;    /*      listening channel number */
2025
2026
2027        /*      Extended Listen Timing ATTR */
2028        /*      Type: */
2029        p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
2030
2031        /*      Length: */
2032        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
2033        p2pielen += 2;
2034
2035        /*      Value: */
2036        /*      Availability Period */
2037        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
2038        p2pielen += 2;
2039
2040        /*      Availability Interval */
2041        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
2042        p2pielen += 2;
2043
2044
2045        /*      Intended P2P Interface Address */
2046        /*      Type: */
2047        p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
2048
2049        /*      Length: */
2050        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2051        p2pielen += 2;
2052
2053        /*      Value: */
2054        memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2055        p2pielen += ETH_ALEN;
2056
2057
2058        /*      Channel List */
2059        /*      Type: */
2060        p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2061
2062        /*  Length: */
2063        /*  Country String(3) */
2064        /*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2065        /*  + number of channels in all classes */
2066        len_channellist_attr = 3
2067           + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
2068           + get_reg_classes_full_count(&pmlmeext->channel_list);
2069
2070        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2071        p2pielen += 2;
2072
2073        /*      Value: */
2074        /*      Country String */
2075        p2pie[p2pielen++] = 'X';
2076        p2pie[p2pielen++] = 'X';
2077
2078        /*      The third byte should be set to 0x04. */
2079        /*      Described in the "Operating Channel Attribute" section. */
2080        p2pie[p2pielen++] = 0x04;
2081
2082        /*      Channel Entry List */
2083
2084        {
2085                int i, j;
2086                for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2087                        /*      Operating Class */
2088                        p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2089
2090                        /*      Number of Channels */
2091                        p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2092
2093                        /*      Channel List */
2094                        for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2095                                p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2096                        }
2097                }
2098        }
2099
2100        /*      Device Info */
2101        /*      Type: */
2102        p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2103
2104        /*      Length: */
2105        /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2106        /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2107        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2108        p2pielen += 2;
2109
2110        /*      Value: */
2111        /*      P2P Device Address */
2112        memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2113        p2pielen += ETH_ALEN;
2114
2115        /*      Config Method */
2116        /*      This field should be big endian. Noted by P2P specification. */
2117
2118        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
2119
2120        p2pielen += 2;
2121
2122        /*      Primary Device Type */
2123        /*      Category ID */
2124        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2125        p2pielen += 2;
2126
2127        /*      OUI */
2128        *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2129        p2pielen += 4;
2130
2131        /*      Sub Category ID */
2132        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2133        p2pielen += 2;
2134
2135        /*      Number of Secondary Device Types */
2136        p2pie[p2pielen++] = 0x00;       /*      No Secondary Device Type List */
2137
2138        /*      Device Name */
2139        /*      Type: */
2140        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2141        p2pielen += 2;
2142
2143        /*      Length: */
2144        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2145        p2pielen += 2;
2146
2147        /*      Value: */
2148        memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);
2149        p2pielen += pwdinfo->device_name_len;
2150
2151
2152        /*      Operating Channel */
2153        /*      Type: */
2154        p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2155
2156        /*      Length: */
2157        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2158        p2pielen += 2;
2159
2160        /*      Value: */
2161        /*      Country String */
2162        p2pie[p2pielen++] = 'X';
2163        p2pie[p2pielen++] = 'X';
2164
2165        /*      The third byte should be set to 0x04. */
2166        /*      Described in the "Operating Channel Attribute" section. */
2167        p2pie[p2pielen++] = 0x04;
2168
2169        /*      Operating Class */
2170        p2pie[p2pielen++] = 0x51;
2171
2172        /*      Channel Number */
2173        p2pie[p2pielen++] = pwdinfo->operating_channel; /*      operating channel number */
2174
2175        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2176
2177        pattrib->last_txcmdsz = pattrib->pktlen;
2178
2179        dump_mgntframe(padapter, pmgntframe);
2180
2181        return;
2182}
2183
2184static void issue_p2p_GO_response(struct adapter *padapter, u8 *raddr, u8 *frame_body, uint len, u8 result)
2185{
2186        unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
2187        u8 action = P2P_PUB_ACTION_ACTION;
2188        __be32                  p2poui = cpu_to_be32(P2POUI);
2189        u8 oui_subtype = P2P_GO_NEGO_RESP;
2190        u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
2191        u8 p2pielen = 0;
2192        uint                    wpsielen = 0;
2193        u16 wps_devicepassword_id = 0x0000;
2194        __be16                  be_tmp;
2195        uint                    wps_devicepassword_id_len = 0;
2196        u16 len_channellist_attr = 0;
2197
2198        struct xmit_frame                       *pmgntframe;
2199        struct pkt_attrib                       *pattrib;
2200        unsigned char                                   *pframe;
2201        struct rtw_ieee80211_hdr        *pwlanhdr;
2202        unsigned short                          *fctrl;
2203        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
2204        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2205        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
2206
2207        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2208        if (pmgntframe == NULL)
2209                return;
2210
2211        DBG_88E("[%s] In, result=%d\n", __func__,  result);
2212        /* update attribute */
2213        pattrib = &pmgntframe->attrib;
2214        update_mgntframe_attrib(padapter, pattrib);
2215
2216        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2217
2218        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2219        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
2220
2221        fctrl = &(pwlanhdr->frame_ctl);
2222        *(fctrl) = 0;
2223
2224        memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2225        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2226        memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
2227
2228        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2229        pmlmeext->mgnt_seq++;
2230        SetFrameSubType(pframe, WIFI_ACTION);
2231
2232        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
2233        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
2234
2235        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
2236        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
2237        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
2238        pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
2239        pwdinfo->negotiation_dialog_token = frame_body[7];      /*      The Dialog Token of provisioning discovery request frame. */
2240        pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
2241
2242        /*      Commented by Albert 20110328 */
2243        /*      Try to get the device password ID from the WPS IE of group negotiation request frame */
2244        /*      WiFi Direct test plan 5.1.15 */
2245        rtw_get_wps_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
2246        rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8 *)&be_tmp, &wps_devicepassword_id_len);
2247        wps_devicepassword_id = be16_to_cpu(be_tmp);
2248
2249        _rtw_memset(wpsie, 0x00, 255);
2250        wpsielen = 0;
2251
2252        /*      WPS Section */
2253        wpsielen = 0;
2254        /*      WPS OUI */
2255        *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
2256        wpsielen += 4;
2257
2258        /*      WPS version */
2259        /*      Type: */
2260        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
2261        wpsielen += 2;
2262
2263        /*      Length: */
2264        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
2265        wpsielen += 2;
2266
2267        /*      Value: */
2268        wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
2269
2270        /*      Device Password ID */
2271        /*      Type: */
2272        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
2273        wpsielen += 2;
2274
2275        /*      Length: */
2276        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
2277        wpsielen += 2;
2278
2279        /*      Value: */
2280        if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2281                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);
2282        else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2283                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_USER_SPEC);
2284        else
2285                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_PBC);
2286        wpsielen += 2;
2287
2288        /*      Commented by Kurt 20120113 */
2289        /*      If some device wants to do p2p handshake without sending prov_disc_req */
2290        /*      We have to get peer_req_cm from here. */
2291        if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3)) {
2292                if (wps_devicepassword_id == WPS_DPID_USER_SPEC)
2293                        memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3);
2294                else if (wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC)
2295                        memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3);
2296                else
2297                        memcpy(pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3);
2298        }
2299
2300        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
2301
2302
2303        /*      P2P IE Section. */
2304
2305        /*      P2P OUI */
2306        p2pielen = 0;
2307        p2pie[p2pielen++] = 0x50;
2308        p2pie[p2pielen++] = 0x6F;
2309        p2pie[p2pielen++] = 0x9A;
2310        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
2311
2312        /*      Commented by Albert 20100908 */
2313        /*      According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes */
2314        /*      1. Status */
2315        /*      2. P2P Capability */
2316        /*      3. Group Owner Intent */
2317        /*      4. Configuration Timeout */
2318        /*      5. Operating Channel */
2319        /*      6. Intended P2P Interface Address */
2320        /*      7. Channel List */
2321        /*      8. Device Info */
2322        /*      9. Group ID     (Only GO) */
2323
2324
2325        /*      ToDo: */
2326
2327        /*      P2P Status */
2328        /*      Type: */
2329        p2pie[p2pielen++] = P2P_ATTR_STATUS;
2330
2331        /*      Length: */
2332        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2333        p2pielen += 2;
2334
2335        /*      Value: */
2336        p2pie[p2pielen++] = result;
2337
2338        /*      P2P Capability */
2339        /*      Type: */
2340        p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2341
2342        /*      Length: */
2343        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2344        p2pielen += 2;
2345
2346        /*      Value: */
2347        /*      Device Capability Bitmap, 1 byte */
2348
2349        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2350                /*      Commented by Albert 2011/03/08 */
2351                /*      According to the P2P specification */
2352                /*      if the sending device will be client, the P2P Capability should be reserved of group negotation response frame */
2353                p2pie[p2pielen++] = 0;
2354        } else {
2355                /*      Be group owner or meet the error case */
2356                p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2357        }
2358
2359        /*      Group Capability Bitmap, 1 byte */
2360        if (pwdinfo->persistent_supported) {
2361                p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2362        } else {
2363                p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2364        }
2365
2366        /*      Group Owner Intent */
2367        /*      Type: */
2368        p2pie[p2pielen++] = P2P_ATTR_GO_INTENT;
2369
2370        /*      Length: */
2371        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2372        p2pielen += 2;
2373
2374        /*      Value: */
2375        if (pwdinfo->peer_intent & 0x01) {
2376                /*      Peer's tie breaker bit is 1, our tie breaker bit should be 0 */
2377                p2pie[p2pielen++] = (pwdinfo->intent << 1);
2378        } else {
2379                /*      Peer's tie breaker bit is 0, our tie breaker bit should be 1 */
2380                p2pie[p2pielen++] = ((pwdinfo->intent << 1) | BIT(0));
2381        }
2382
2383
2384        /*      Configuration Timeout */
2385        /*      Type: */
2386        p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2387
2388        /*      Length: */
2389        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2390        p2pielen += 2;
2391
2392        /*      Value: */
2393        p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P GO */
2394        p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P Client */
2395
2396        /*      Operating Channel */
2397        /*      Type: */
2398        p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2399
2400        /*      Length: */
2401        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2402        p2pielen += 2;
2403
2404        /*      Value: */
2405        /*      Country String */
2406        p2pie[p2pielen++] = 'X';
2407        p2pie[p2pielen++] = 'X';
2408
2409        /*      The third byte should be set to 0x04. */
2410        /*      Described in the "Operating Channel Attribute" section. */
2411        p2pie[p2pielen++] = 0x04;
2412
2413        /*      Operating Class */
2414        p2pie[p2pielen++] = 0x51;
2415
2416        /*      Channel Number */
2417        p2pie[p2pielen++] = pwdinfo->operating_channel; /*      operating channel number */
2418
2419        /*      Intended P2P Interface Address */
2420        /*      Type: */
2421        p2pie[p2pielen++] = P2P_ATTR_INTENTED_IF_ADDR;
2422
2423        /*      Length: */
2424        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2425        p2pielen += 2;
2426
2427        /*      Value: */
2428        memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2429        p2pielen += ETH_ALEN;
2430
2431        /*      Channel List */
2432        /*      Type: */
2433        p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2434
2435        /*  Country String(3) */
2436        /*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2437        /*  + number of channels in all classes */
2438        len_channellist_attr = 3
2439           + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
2440           + get_reg_classes_full_count(&pmlmeext->channel_list);
2441
2442        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2443
2444        p2pielen += 2;
2445
2446        /*      Value: */
2447        /*      Country String */
2448        p2pie[p2pielen++] = 'X';
2449        p2pie[p2pielen++] = 'X';
2450
2451        /*      The third byte should be set to 0x04. */
2452        /*      Described in the "Operating Channel Attribute" section. */
2453        p2pie[p2pielen++] = 0x04;
2454
2455        /*      Channel Entry List */
2456
2457        {
2458                int i, j;
2459                for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2460                        /*      Operating Class */
2461                        p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2462
2463                        /*      Number of Channels */
2464                        p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2465
2466                        /*      Channel List */
2467                        for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2468                                p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2469                        }
2470                }
2471        }
2472
2473        /*      Device Info */
2474        /*      Type: */
2475        p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2476
2477        /*      Length: */
2478        /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2479        /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2480        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2481        p2pielen += 2;
2482
2483        /*      Value: */
2484        /*      P2P Device Address */
2485        memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2486        p2pielen += ETH_ALEN;
2487
2488        /*      Config Method */
2489        /*      This field should be big endian. Noted by P2P specification. */
2490
2491        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
2492
2493        p2pielen += 2;
2494
2495        /*      Primary Device Type */
2496        /*      Category ID */
2497        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2498        p2pielen += 2;
2499
2500        /*      OUI */
2501        *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2502        p2pielen += 4;
2503
2504        /*      Sub Category ID */
2505        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2506        p2pielen += 2;
2507
2508        /*      Number of Secondary Device Types */
2509        p2pie[p2pielen++] = 0x00;       /*      No Secondary Device Type List */
2510
2511        /*      Device Name */
2512        /*      Type: */
2513        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2514        p2pielen += 2;
2515
2516        /*      Length: */
2517        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2518        p2pielen += 2;
2519
2520        /*      Value: */
2521        memcpy(p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len);
2522        p2pielen += pwdinfo->device_name_len;
2523
2524        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2525                /*      Group ID Attribute */
2526                /*      Type: */
2527                p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2528
2529                /*      Length: */
2530                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
2531                p2pielen += 2;
2532
2533                /*      Value: */
2534                /*      p2P Device Address */
2535                memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);
2536                p2pielen += ETH_ALEN;
2537
2538                /*      SSID */
2539                memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2540                p2pielen += pwdinfo->nego_ssidlen;
2541        }
2542
2543        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2544
2545        pattrib->last_txcmdsz = pattrib->pktlen;
2546
2547        dump_mgntframe(padapter, pmgntframe);
2548        return;
2549}
2550
2551static void issue_p2p_GO_confirm(struct adapter *padapter, u8 *raddr, u8 result)
2552{
2553        unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
2554        u8 action = P2P_PUB_ACTION_ACTION;
2555        __be32                  p2poui = cpu_to_be32(P2POUI);
2556        u8 oui_subtype = P2P_GO_NEGO_CONF;
2557        u8 p2pie[255] = { 0x00 };
2558        u8 p2pielen = 0;
2559
2560        struct xmit_frame                       *pmgntframe;
2561        struct pkt_attrib                       *pattrib;
2562        unsigned char                                   *pframe;
2563        struct rtw_ieee80211_hdr        *pwlanhdr;
2564        unsigned short                          *fctrl;
2565        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
2566        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2567        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
2568
2569        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2570        if (pmgntframe == NULL)
2571                return;
2572
2573        DBG_88E("[%s] In\n", __func__);
2574        /* update attribute */
2575        pattrib = &pmgntframe->attrib;
2576        update_mgntframe_attrib(padapter, pattrib);
2577
2578        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2579
2580        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2581        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
2582
2583        fctrl = &(pwlanhdr->frame_ctl);
2584        *(fctrl) = 0;
2585
2586        memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2587        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2588        memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
2589
2590        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2591        pmlmeext->mgnt_seq++;
2592        SetFrameSubType(pframe, WIFI_ACTION);
2593
2594        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
2595        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
2596
2597        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
2598        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
2599        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
2600        pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
2601        pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
2602
2603
2604
2605        /*      P2P IE Section. */
2606
2607        /*      P2P OUI */
2608        p2pielen = 0;
2609        p2pie[p2pielen++] = 0x50;
2610        p2pie[p2pielen++] = 0x6F;
2611        p2pie[p2pielen++] = 0x9A;
2612        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
2613
2614        /*      Commented by Albert 20110306 */
2615        /*      According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes */
2616        /*      1. Status */
2617        /*      2. P2P Capability */
2618        /*      3. Operating Channel */
2619        /*      4. Channel List */
2620        /*      5. Group ID     (if this WiFi is GO) */
2621
2622        /*      P2P Status */
2623        /*      Type: */
2624        p2pie[p2pielen++] = P2P_ATTR_STATUS;
2625
2626        /*      Length: */
2627        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2628        p2pielen += 2;
2629
2630        /*      Value: */
2631        p2pie[p2pielen++] = result;
2632
2633        /*      P2P Capability */
2634        /*      Type: */
2635        p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
2636
2637        /*      Length: */
2638        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2639        p2pielen += 2;
2640
2641        /*      Value: */
2642        /*      Device Capability Bitmap, 1 byte */
2643        p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
2644
2645        /*      Group Capability Bitmap, 1 byte */
2646        if (pwdinfo->persistent_supported)
2647                p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
2648        else
2649                p2pie[p2pielen++] = P2P_GRPCAP_CROSS_CONN;
2650
2651        /*      Operating Channel */
2652        /*      Type: */
2653        p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2654
2655        /*      Length: */
2656        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2657        p2pielen += 2;
2658
2659        /*      Value: */
2660        /*      Country String */
2661        p2pie[p2pielen++] = 'X';
2662        p2pie[p2pielen++] = 'X';
2663
2664        /*      The third byte should be set to 0x04. */
2665        /*      Described in the "Operating Channel Attribute" section. */
2666        p2pie[p2pielen++] = 0x04;
2667
2668
2669        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT)) {
2670                /*      Operating Class */
2671                p2pie[p2pielen++] = 0x51;
2672                p2pie[p2pielen++] = pwdinfo->peer_operating_ch;
2673        } else {
2674                /*      Operating Class */
2675                p2pie[p2pielen++] = 0x51;
2676
2677                /*      Channel Number */
2678                p2pie[p2pielen++] = pwdinfo->operating_channel;         /*      Use the listen channel as the operating channel */
2679        }
2680
2681
2682        /*      Channel List */
2683        /*      Type: */
2684        p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2685
2686        /*      Length: */
2687        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(pwdinfo->channel_list_attr_len);
2688        p2pielen += 2;
2689
2690        /*      Value: */
2691        memcpy(p2pie + p2pielen, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len);
2692        p2pielen += pwdinfo->channel_list_attr_len;
2693
2694        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
2695                /*      Group ID Attribute */
2696                /*      Type: */
2697                p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2698
2699                /*      Length: */
2700                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN + pwdinfo->nego_ssidlen);
2701                p2pielen += 2;
2702
2703                /*      Value: */
2704                /*      p2P Device Address */
2705                memcpy(p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN);
2706                p2pielen += ETH_ALEN;
2707
2708                /*      SSID */
2709                memcpy(p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen);
2710                p2pielen += pwdinfo->nego_ssidlen;
2711        }
2712        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2713        pattrib->last_txcmdsz = pattrib->pktlen;
2714        dump_mgntframe(padapter, pmgntframe);
2715        return;
2716}
2717
2718void issue_p2p_invitation_request(struct adapter *padapter, u8 *raddr)
2719{
2720        unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
2721        u8 action = P2P_PUB_ACTION_ACTION;
2722        __be32                  p2poui = cpu_to_be32(P2POUI);
2723        u8 oui_subtype = P2P_INVIT_REQ;
2724        u8 p2pie[255] = { 0x00 };
2725        u8 p2pielen = 0;
2726        u8 dialogToken = 3;
2727        u16 len_channellist_attr = 0;
2728        struct xmit_frame                       *pmgntframe;
2729        struct pkt_attrib                       *pattrib;
2730        unsigned char                                   *pframe;
2731        struct rtw_ieee80211_hdr        *pwlanhdr;
2732        unsigned short                          *fctrl;
2733        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
2734        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2735        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
2736
2737        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2738        if (pmgntframe == NULL)
2739                return;
2740
2741        /* update attribute */
2742        pattrib = &pmgntframe->attrib;
2743        update_mgntframe_attrib(padapter, pattrib);
2744
2745        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2746
2747        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2748        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
2749
2750        fctrl = &(pwlanhdr->frame_ctl);
2751        *(fctrl) = 0;
2752
2753        memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
2754        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2755        memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
2756
2757        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2758        pmlmeext->mgnt_seq++;
2759        SetFrameSubType(pframe, WIFI_ACTION);
2760
2761        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
2762        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
2763
2764        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
2765        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
2766        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
2767        pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
2768        pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
2769
2770        /*      P2P IE Section. */
2771
2772        /*      P2P OUI */
2773        p2pielen = 0;
2774        p2pie[p2pielen++] = 0x50;
2775        p2pie[p2pielen++] = 0x6F;
2776        p2pie[p2pielen++] = 0x9A;
2777        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
2778
2779        /*      Commented by Albert 20101011 */
2780        /*      According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes */
2781        /*      1. Configuration Timeout */
2782        /*      2. Invitation Flags */
2783        /*      3. Operating Channel    (Only GO) */
2784        /*      4. P2P Group BSSID      (Should be included if I am the GO) */
2785        /*      5. Channel List */
2786        /*      6. P2P Group ID */
2787        /*      7. P2P Device Info */
2788
2789        /*      Configuration Timeout */
2790        /*      Type: */
2791        p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
2792
2793        /*      Length: */
2794        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
2795        p2pielen += 2;
2796
2797        /*      Value: */
2798        p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P GO */
2799        p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P Client */
2800
2801        /*      Invitation Flags */
2802        /*      Type: */
2803        p2pie[p2pielen++] = P2P_ATTR_INVITATION_FLAGS;
2804
2805        /*      Length: */
2806        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
2807        p2pielen += 2;
2808
2809        /*      Value: */
2810        p2pie[p2pielen++] = P2P_INVITATION_FLAGS_PERSISTENT;
2811
2812
2813        /*      Operating Channel */
2814        /*      Type: */
2815        p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
2816
2817        /*      Length: */
2818        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
2819        p2pielen += 2;
2820
2821        /*      Value: */
2822        /*      Country String */
2823        p2pie[p2pielen++] = 'X';
2824        p2pie[p2pielen++] = 'X';
2825
2826        /*      The third byte should be set to 0x04. */
2827        /*      Described in the "Operating Channel Attribute" section. */
2828        p2pie[p2pielen++] = 0x04;
2829
2830        /*      Operating Class */
2831        p2pie[p2pielen++] = 0x51;
2832
2833        /*      Channel Number */
2834        p2pie[p2pielen++] = pwdinfo->invitereq_info.operating_ch;       /*      operating channel number */
2835
2836        if (_rtw_memcmp(myid(&padapter->eeprompriv), pwdinfo->invitereq_info.go_bssid, ETH_ALEN)) {
2837                /*      P2P Group BSSID */
2838                /*      Type: */
2839                p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
2840
2841                /*      Length: */
2842                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
2843                p2pielen += 2;
2844
2845                /*      Value: */
2846                /*      P2P Device Address for GO */
2847                memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
2848                p2pielen += ETH_ALEN;
2849        }
2850
2851        /*      Channel List */
2852        /*      Type: */
2853        p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
2854
2855
2856        /*      Length: */
2857        /*  Country String(3) */
2858        /*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
2859        /*  + number of channels in all classes */
2860        len_channellist_attr = 3
2861           + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
2862           + get_reg_classes_full_count(&pmlmeext->channel_list);
2863
2864        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
2865
2866        p2pielen += 2;
2867
2868        /*      Value: */
2869        /*      Country String */
2870        p2pie[p2pielen++] = 'X';
2871        p2pie[p2pielen++] = 'X';
2872
2873        /*      The third byte should be set to 0x04. */
2874        /*      Described in the "Operating Channel Attribute" section. */
2875        p2pie[p2pielen++] = 0x04;
2876
2877        /*      Channel Entry List */
2878        {
2879                int i, j;
2880                for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
2881                        /*      Operating Class */
2882                        p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
2883
2884                        /*      Number of Channels */
2885                        p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
2886
2887                        /*      Channel List */
2888                        for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
2889                                p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
2890                        }
2891                }
2892        }
2893
2894
2895        /*      P2P Group ID */
2896        /*      Type: */
2897        p2pie[p2pielen++] = P2P_ATTR_GROUP_ID;
2898
2899        /*      Length: */
2900        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(6 + pwdinfo->invitereq_info.ssidlen);
2901        p2pielen += 2;
2902
2903        /*      Value: */
2904        /*      P2P Device Address for GO */
2905        memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN);
2906        p2pielen += ETH_ALEN;
2907
2908        /*      SSID */
2909        memcpy(p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen);
2910        p2pielen += pwdinfo->invitereq_info.ssidlen;
2911
2912
2913        /*      Device Info */
2914        /*      Type: */
2915        p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
2916
2917        /*      Length: */
2918        /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
2919        /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
2920        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
2921        p2pielen += 2;
2922
2923        /*      Value: */
2924        /*      P2P Device Address */
2925        memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
2926        p2pielen += ETH_ALEN;
2927
2928        /*      Config Method */
2929        /*      This field should be big endian. Noted by P2P specification. */
2930        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
2931        p2pielen += 2;
2932
2933        /*      Primary Device Type */
2934        /*      Category ID */
2935        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
2936        p2pielen += 2;
2937
2938        /*      OUI */
2939        *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
2940        p2pielen  += 4;
2941
2942        /*      Sub Category ID */
2943        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
2944        p2pielen += 2;
2945
2946        /*      Number of Secondary Device Types */
2947        p2pie[p2pielen++] = 0x00;       /*      No Secondary Device Type List */
2948
2949        /*      Device Name */
2950        /*      Type: */
2951        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
2952        p2pielen += 2;
2953
2954        /*      Length: */
2955        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
2956        p2pielen += 2;
2957
2958        /*      Value: */
2959        memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
2960        p2pielen += pwdinfo->device_name_len;
2961
2962        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
2963
2964        pattrib->last_txcmdsz = pattrib->pktlen;
2965
2966        dump_mgntframe(padapter, pmgntframe);
2967
2968        return;
2969}
2970
2971void issue_p2p_invitation_response(struct adapter *padapter, u8 *raddr, u8 dialogToken, u8 status_code)
2972{
2973        unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
2974        u8 action = P2P_PUB_ACTION_ACTION;
2975        __be32                  p2poui = cpu_to_be32(P2POUI);
2976        u8 oui_subtype = P2P_INVIT_RESP;
2977        u8 p2pie[255] = { 0x00 };
2978        u8 p2pielen = 0;
2979        u16 len_channellist_attr = 0;
2980        struct xmit_frame                       *pmgntframe;
2981        struct pkt_attrib                       *pattrib;
2982        unsigned char                                   *pframe;
2983        struct rtw_ieee80211_hdr        *pwlanhdr;
2984        unsigned short                          *fctrl;
2985        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
2986        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
2987        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
2988
2989        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2990        if (pmgntframe == NULL)
2991                return;
2992
2993        /* update attribute */
2994        pattrib = &pmgntframe->attrib;
2995        update_mgntframe_attrib(padapter, pattrib);
2996
2997        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2998
2999        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3000        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3001
3002        fctrl = &(pwlanhdr->frame_ctl);
3003        *(fctrl) = 0;
3004
3005        memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3006        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3007        memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
3008
3009        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3010        pmlmeext->mgnt_seq++;
3011        SetFrameSubType(pframe, WIFI_ACTION);
3012
3013        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3014        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3015
3016        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3017        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3018        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
3019        pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
3020        pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
3021
3022        /*      P2P IE Section. */
3023
3024        /*      P2P OUI */
3025        p2pielen = 0;
3026        p2pie[p2pielen++] = 0x50;
3027        p2pie[p2pielen++] = 0x6F;
3028        p2pie[p2pielen++] = 0x9A;
3029        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
3030
3031        /*      Commented by Albert 20101005 */
3032        /*      According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes */
3033        /*      1. Status */
3034        /*      2. Configuration Timeout */
3035        /*      3. Operating Channel    (Only GO) */
3036        /*      4. P2P Group BSSID      (Only GO) */
3037        /*      5. Channel List */
3038
3039        /*      P2P Status */
3040        /*      Type: */
3041        p2pie[p2pielen++] = P2P_ATTR_STATUS;
3042
3043        /*      Length: */
3044        *(__le16  *)(p2pie + p2pielen) = cpu_to_le16(0x0001);
3045        p2pielen += 2;
3046
3047        /*      Value: */
3048        /*      When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE. */
3049        /*      Sent the event receiving the P2P Invitation Req frame to DMP UI. */
3050        /*      DMP had to compare the MAC address to find out the profile. */
3051        /*      So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB. */
3052        /*      If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req */
3053        /*      to NB to rebuild the persistent group. */
3054        p2pie[p2pielen++] = status_code;
3055
3056        /*      Configuration Timeout */
3057        /*      Type: */
3058        p2pie[p2pielen++] = P2P_ATTR_CONF_TIMEOUT;
3059
3060        /*      Length: */
3061        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
3062        p2pielen += 2;
3063
3064        /*      Value: */
3065        p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P GO */
3066        p2pie[p2pielen++] = 200;        /*      2 seconds needed to be the P2P Client */
3067
3068        if (status_code == P2P_STATUS_SUCCESS) {
3069                if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3070                        /*      The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO */
3071                        /*      In this case, the P2P Invitation response frame should carry the two more P2P attributes. */
3072                        /*      First one is operating channel attribute. */
3073                        /*      Second one is P2P Group BSSID attribute. */
3074
3075                        /*      Operating Channel */
3076                        /*      Type: */
3077                        p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3078
3079                        /*      Length: */
3080                        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
3081                        p2pielen += 2;
3082
3083                        /*      Value: */
3084                        /*      Country String */
3085                        p2pie[p2pielen++] = 'X';
3086                        p2pie[p2pielen++] = 'X';
3087
3088                        /*      The third byte should be set to 0x04. */
3089                        /*      Described in the "Operating Channel Attribute" section. */
3090                        p2pie[p2pielen++] = 0x04;
3091
3092                        /*      Operating Class */
3093                        p2pie[p2pielen++] = 0x51;       /*      Copy from SD7 */
3094
3095                        /*      Channel Number */
3096                        p2pie[p2pielen++] = pwdinfo->operating_channel; /*      operating channel number */
3097
3098
3099                        /*      P2P Group BSSID */
3100                        /*      Type: */
3101                        p2pie[p2pielen++] = P2P_ATTR_GROUP_BSSID;
3102
3103                        /*      Length: */
3104                        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(ETH_ALEN);
3105                        p2pielen += 2;
3106
3107                        /*      Value: */
3108                        /*      P2P Device Address for GO */
3109                        memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
3110                        p2pielen += ETH_ALEN;
3111                }
3112
3113                /*      Channel List */
3114                /*      Type: */
3115                p2pie[p2pielen++] = P2P_ATTR_CH_LIST;
3116
3117                /*      Length: */
3118                /*  Country String(3) */
3119                /*  + (Operating Class (1) + Number of Channels(1)) * Operation Classes (?) */
3120                /*  + number of channels in all classes */
3121                len_channellist_attr = 3
3122                        + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
3123                        + get_reg_classes_full_count(&pmlmeext->channel_list);
3124
3125                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(len_channellist_attr);
3126                p2pielen += 2;
3127
3128                /*      Value: */
3129                /*      Country String */
3130                p2pie[p2pielen++] = 'X';
3131                p2pie[p2pielen++] = 'X';
3132
3133                /*      The third byte should be set to 0x04. */
3134                /*      Described in the "Operating Channel Attribute" section. */
3135                p2pie[p2pielen++] = 0x04;
3136
3137                /*      Channel Entry List */
3138                {
3139                        int i, j;
3140                        for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
3141                                /*      Operating Class */
3142                                p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
3143
3144                                /*      Number of Channels */
3145                                p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
3146
3147                                /*      Channel List */
3148                                for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
3149                                        p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
3150                                }
3151                        }
3152                }
3153        }
3154
3155        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
3156
3157        pattrib->last_txcmdsz = pattrib->pktlen;
3158
3159        dump_mgntframe(padapter, pmgntframe);
3160
3161        return;
3162}
3163
3164void issue_p2p_provision_request(struct adapter *padapter, u8 *pssid, u8 ussidlen, u8 *pdev_raddr)
3165{
3166        unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
3167        u8 action = P2P_PUB_ACTION_ACTION;
3168        u8 dialogToken = 1;
3169        u8 oui_subtype = P2P_PROVISION_DISC_REQ;
3170        u8 wpsie[100] = { 0x00 };
3171        u8 wpsielen = 0;
3172        __be32 p2poui = cpu_to_be32(P2POUI);
3173        u32                     p2pielen = 0;
3174        struct xmit_frame                       *pmgntframe;
3175        struct pkt_attrib                       *pattrib;
3176        unsigned char                                   *pframe;
3177        struct rtw_ieee80211_hdr        *pwlanhdr;
3178        unsigned short                          *fctrl;
3179        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
3180        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3181        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
3182
3183        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3184        if (pmgntframe == NULL)
3185                return;
3186
3187        DBG_88E("[%s] In\n", __func__);
3188        /* update attribute */
3189        pattrib = &pmgntframe->attrib;
3190        update_mgntframe_attrib(padapter, pattrib);
3191
3192        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3193
3194        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3195        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3196
3197        fctrl = &(pwlanhdr->frame_ctl);
3198        *(fctrl) = 0;
3199
3200        memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
3201        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3202        memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
3203
3204        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3205        pmlmeext->mgnt_seq++;
3206        SetFrameSubType(pframe, WIFI_ACTION);
3207
3208        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
3209        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3210
3211        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3212        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3213        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&(p2poui), &(pattrib->pktlen));
3214        pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));
3215        pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
3216
3217        p2pielen = build_prov_disc_request_p2p_ie(pwdinfo, pframe, pssid, ussidlen, pdev_raddr);
3218
3219        pframe += p2pielen;
3220        pattrib->pktlen += p2pielen;
3221
3222        wpsielen = 0;
3223        /*      WPS OUI */
3224        *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3225        wpsielen += 4;
3226
3227        /*      WPS version */
3228        /*      Type: */
3229        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3230        wpsielen += 2;
3231
3232        /*      Length: */
3233        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3234        wpsielen += 2;
3235
3236        /*      Value: */
3237        wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
3238
3239        /*      Config Method */
3240        /*      Type: */
3241        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3242        wpsielen += 2;
3243
3244        /*      Length: */
3245        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3246        wpsielen += 2;
3247
3248        /*      Value: */
3249        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->tx_prov_disc_info.wps_config_method_request);
3250        wpsielen += 2;
3251
3252        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3253
3254        pattrib->last_txcmdsz = pattrib->pktlen;
3255
3256        dump_mgntframe(padapter, pmgntframe);
3257
3258        return;
3259}
3260
3261static u8 is_matched_in_profilelist(u8 *peermacaddr, struct profile_info *profileinfo)
3262{
3263        u8 i, match_result = 0;
3264
3265        DBG_88E("[%s] peermac=%.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
3266                peermacaddr[0], peermacaddr[1], peermacaddr[2], peermacaddr[3], peermacaddr[4], peermacaddr[5]);
3267
3268        for (i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++) {
3269               DBG_88E("[%s] profileinfo_mac=%.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
3270                            profileinfo->peermac[0], profileinfo->peermac[1], profileinfo->peermac[2], profileinfo->peermac[3], profileinfo->peermac[4], profileinfo->peermac[5]);
3271                if (_rtw_memcmp(peermacaddr, profileinfo->peermac, ETH_ALEN)) {
3272                        match_result = 1;
3273                        DBG_88E("[%s] Match!\n", __func__);
3274                        break;
3275                }
3276        }
3277        return match_result;
3278}
3279
3280void issue_probersp_p2p(struct adapter *padapter, unsigned char *da)
3281{
3282        struct xmit_frame                       *pmgntframe;
3283        struct pkt_attrib                       *pattrib;
3284        unsigned char                                   *pframe;
3285        struct rtw_ieee80211_hdr        *pwlanhdr;
3286        unsigned short                          *fctrl;
3287        unsigned char                                   *mac;
3288        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3289        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3290        u16 beacon_interval = 100;
3291        u16 capInfo = 0;
3292        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
3293        u8 wpsie[255] = { 0x00 };
3294        u32                                     wpsielen = 0, p2pielen = 0;
3295
3296        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3297        if (pmgntframe == NULL)
3298                return;
3299
3300        /* update attribute */
3301        pattrib = &pmgntframe->attrib;
3302        update_mgntframe_attrib(padapter, pattrib);
3303
3304        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3305
3306        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3307        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3308
3309        mac = myid(&(padapter->eeprompriv));
3310
3311        fctrl = &(pwlanhdr->frame_ctl);
3312        *(fctrl) = 0;
3313        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3314        memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
3315
3316        /*      Use the device address for BSSID field. */
3317        memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
3318
3319        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3320        pmlmeext->mgnt_seq++;
3321        SetFrameSubType(fctrl, WIFI_PROBERSP);
3322
3323        pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
3324        pattrib->pktlen = pattrib->hdrlen;
3325        pframe += pattrib->hdrlen;
3326
3327        /* timestamp will be inserted by hardware */
3328        pframe += 8;
3329        pattrib->pktlen += 8;
3330
3331        /*  beacon interval: 2 bytes */
3332        memcpy(pframe, (unsigned char *)&beacon_interval, 2);
3333        pframe += 2;
3334        pattrib->pktlen += 2;
3335
3336        /*      capability info: 2 bytes */
3337        /*      ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec) */
3338        capInfo |= cap_ShortPremble;
3339        capInfo |= cap_ShortSlot;
3340
3341        memcpy(pframe, (unsigned char *)&capInfo, 2);
3342        pframe += 2;
3343        pattrib->pktlen += 2;
3344
3345
3346        /*  SSID */
3347        pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
3348
3349        /*  supported rates... */
3350        /*      Use the OFDM rate in the P2P probe response frame. (6(B), 9(B), 12, 18, 24, 36, 48, 54) */
3351        pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
3352
3353        /*  DS parameter set */
3354        pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
3355
3356        /*      Todo: WPS IE */
3357        /*      Noted by Albert 20100907 */
3358        /*      According to the WPS specification, all the WPS attribute is presented by Big Endian. */
3359
3360        wpsielen = 0;
3361        /*      WPS OUI */
3362        *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3363        wpsielen += 4;
3364
3365        /*      WPS version */
3366        /*      Type: */
3367        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3368        wpsielen += 2;
3369
3370        /*      Length: */
3371        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3372        wpsielen += 2;
3373
3374        /*      Value: */
3375        wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
3376
3377        /*      WiFi Simple Config State */
3378        /*      Type: */
3379        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SIMPLE_CONF_STATE);
3380        wpsielen += 2;
3381
3382        /*      Length: */
3383        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3384        wpsielen += 2;
3385
3386        /*      Value: */
3387        wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;   /*      Not Configured. */
3388
3389        /*      Response Type */
3390        /*      Type: */
3391        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_RESP_TYPE);
3392        wpsielen += 2;
3393
3394        /*      Length: */
3395        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3396        wpsielen += 2;
3397
3398        /*      Value: */
3399        wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
3400
3401        /*      UUID-E */
3402        /*      Type: */
3403        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
3404        wpsielen += 2;
3405
3406        /*      Length: */
3407        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
3408        wpsielen += 2;
3409
3410        /*      Value: */
3411        memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
3412        wpsielen += 0x10;
3413
3414        /*      Manufacturer */
3415        /*      Type: */
3416        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MANUFACTURER);
3417        wpsielen += 2;
3418
3419        /*      Length: */
3420        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0007);
3421        wpsielen += 2;
3422
3423        /*      Value: */
3424        memcpy(wpsie + wpsielen, "Realtek", 7);
3425        wpsielen += 7;
3426
3427        /*      Model Name */
3428        /*      Type: */
3429        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NAME);
3430        wpsielen += 2;
3431
3432        /*      Length: */
3433        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0006);
3434        wpsielen += 2;
3435
3436        /*      Value: */
3437        memcpy(wpsie + wpsielen, "8188EU", 6);
3438        wpsielen += 6;
3439
3440        /*      Model Number */
3441        /*      Type: */
3442        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_MODEL_NUMBER);
3443        wpsielen += 2;
3444
3445        /*      Length: */
3446        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3447        wpsielen += 2;
3448
3449        /*      Value: */
3450        wpsie[wpsielen++] = 0x31;               /*      character 1 */
3451
3452        /*      Serial Number */
3453        /*      Type: */
3454        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_SERIAL_NUMBER);
3455        wpsielen += 2;
3456
3457        /*      Length: */
3458        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(ETH_ALEN);
3459        wpsielen += 2;
3460
3461        /*      Value: */
3462        memcpy(wpsie + wpsielen, "123456" , ETH_ALEN);
3463        wpsielen += ETH_ALEN;
3464
3465        /*      Primary Device Type */
3466        /*      Type: */
3467        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
3468        wpsielen += 2;
3469
3470        /*      Length: */
3471        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
3472        wpsielen += 2;
3473
3474        /*      Value: */
3475        /*      Category ID */
3476        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
3477        wpsielen += 2;
3478
3479        /*      OUI */
3480        *(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
3481        wpsielen += 4;
3482
3483        /*      Sub Category ID */
3484        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
3485        wpsielen += 2;
3486
3487        /*      Device Name */
3488        /*      Type: */
3489        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
3490        wpsielen += 2;
3491
3492        /*      Length: */
3493        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
3494        wpsielen += 2;
3495
3496        /*      Value: */
3497        if (pwdinfo->device_name_len) {
3498                memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
3499                wpsielen += pwdinfo->device_name_len;
3500        }
3501
3502        /*      Config Method */
3503        /*      Type: */
3504        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3505        wpsielen += 2;
3506
3507        /*      Length: */
3508        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3509        wpsielen += 2;
3510
3511        /*      Value: */
3512        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
3513        wpsielen += 2;
3514
3515
3516        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3517
3518
3519        p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
3520        pframe += p2pielen;
3521        pattrib->pktlen += p2pielen;
3522
3523        pattrib->last_txcmdsz = pattrib->pktlen;
3524
3525        dump_mgntframe(padapter, pmgntframe);
3526
3527        return;
3528}
3529
3530static int _issue_probereq_p2p(struct adapter *padapter, u8 *da, int wait_ack)
3531{
3532        int ret = _FAIL;
3533        struct xmit_frame               *pmgntframe;
3534        struct pkt_attrib               *pattrib;
3535        unsigned char                   *pframe;
3536        struct rtw_ieee80211_hdr        *pwlanhdr;
3537        unsigned short          *fctrl;
3538        unsigned char                   *mac;
3539        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3540        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
3541        u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
3542        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
3543        u8 wpsie[255] = { 0x00 }, p2pie[255] = { 0x00 };
3544        u16 wpsielen = 0, p2pielen = 0;
3545        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3546
3547        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3548        if (pmgntframe == NULL)
3549                goto exit;
3550
3551        /* update attribute */
3552        pattrib = &pmgntframe->attrib;
3553        update_mgntframe_attrib(padapter, pattrib);
3554
3555
3556        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3557
3558        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3559        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
3560
3561        mac = myid(&(padapter->eeprompriv));
3562
3563        fctrl = &(pwlanhdr->frame_ctl);
3564        *(fctrl) = 0;
3565
3566        if (da) {
3567                memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3568                memcpy(pwlanhdr->addr3, da, ETH_ALEN);
3569        } else {
3570                if ((pwdinfo->p2p_info.scan_op_ch_only) || (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
3571                        /*      This two flags will be set when this is only the P2P client mode. */
3572                        memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
3573                        memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
3574                } else {
3575                        /*      broadcast probe request frame */
3576                        memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
3577                        memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
3578                }
3579        }
3580        memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
3581
3582        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3583        pmlmeext->mgnt_seq++;
3584        SetFrameSubType(pframe, WIFI_PROBEREQ);
3585
3586        pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
3587        pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
3588
3589        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
3590                pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &(pattrib->pktlen));
3591        else
3592                pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &(pattrib->pktlen));
3593
3594        /*      Use the OFDM rate in the P2P probe request frame. (6(B), 9(B), 12(B), 24(B), 36, 48, 54) */
3595        pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
3596
3597
3598        /*      WPS IE */
3599        /*      Noted by Albert 20110221 */
3600        /*      According to the WPS specification, all the WPS attribute is presented by Big Endian. */
3601
3602        wpsielen = 0;
3603        /*      WPS OUI */
3604        *(__be32 *)(wpsie) = cpu_to_be32(WPSOUI);
3605        wpsielen += 4;
3606
3607        /*      WPS version */
3608        /*      Type: */
3609        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_VER1);
3610        wpsielen += 2;
3611
3612        /*      Length: */
3613        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0001);
3614        wpsielen += 2;
3615
3616        /*      Value: */
3617        wpsie[wpsielen++] = WPS_VERSION_1;      /*      Version 1.0 */
3618
3619        if (pmlmepriv->wps_probe_req_ie == NULL) {
3620                /*      UUID-E */
3621                /*      Type: */
3622                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_UUID_E);
3623                wpsielen += 2;
3624
3625                /*      Length: */
3626                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0010);
3627                wpsielen += 2;
3628
3629                /*      Value: */
3630                memcpy(wpsie + wpsielen, myid(&padapter->eeprompriv), ETH_ALEN);
3631                wpsielen += 0x10;
3632
3633                /*      Config Method */
3634                /*      Type: */
3635                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_CONF_METHOD);
3636                wpsielen += 2;
3637
3638                /*      Length: */
3639                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3640                wpsielen += 2;
3641
3642                /*      Value: */
3643                *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->supported_wps_cm);
3644                wpsielen += 2;
3645        }
3646
3647        /*      Device Name */
3648        /*      Type: */
3649        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
3650        wpsielen += 2;
3651
3652        /*      Length: */
3653        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(pwdinfo->device_name_len);
3654        wpsielen += 2;
3655
3656        /*      Value: */
3657        memcpy(wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len);
3658        wpsielen += pwdinfo->device_name_len;
3659
3660        /*      Primary Device Type */
3661        /*      Type: */
3662        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
3663        wpsielen += 2;
3664
3665        /*      Length: */
3666        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0008);
3667        wpsielen += 2;
3668
3669        /*      Value: */
3670        /*      Category ID */
3671        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_CID_RTK_WIDI);
3672        wpsielen += 2;
3673
3674        /*      OUI */
3675        *(__be32 *)(wpsie + wpsielen) = cpu_to_be32(WPSOUI);
3676        wpsielen += 4;
3677
3678        /*      Sub Category ID */
3679        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_PDT_SCID_RTK_DMP);
3680        wpsielen += 2;
3681
3682        /*      Device Password ID */
3683        /*      Type: */
3684        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_ATTR_DEVICE_PWID);
3685        wpsielen += 2;
3686
3687        /*      Length: */
3688        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(0x0002);
3689        wpsielen += 2;
3690
3691        /*      Value: */
3692        *(__be16 *)(wpsie + wpsielen) = cpu_to_be16(WPS_DPID_REGISTRAR_SPEC);   /*      Registrar-specified */
3693        wpsielen += 2;
3694
3695        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *)wpsie, &pattrib->pktlen);
3696
3697        /*      P2P OUI */
3698        p2pielen = 0;
3699        p2pie[p2pielen++] = 0x50;
3700        p2pie[p2pielen++] = 0x6F;
3701        p2pie[p2pielen++] = 0x9A;
3702        p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
3703
3704        /*      Commented by Albert 20110221 */
3705        /*      According to the P2P Specification, the probe request frame should contain 5 P2P attributes */
3706        /*      1. P2P Capability */
3707        /*      2. P2P Device ID if this probe request wants to find the specific P2P device */
3708        /*      3. Listen Channel */
3709        /*      4. Extended Listen Timing */
3710        /*      5. Operating Channel if this WiFi is working as the group owner now */
3711
3712        /*      P2P Capability */
3713        /*      Type: */
3714        p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
3715
3716        /*      Length: */
3717        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
3718        p2pielen += 2;
3719
3720        /*      Value: */
3721        /*      Device Capability Bitmap, 1 byte */
3722        p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
3723
3724        /*      Group Capability Bitmap, 1 byte */
3725        if (pwdinfo->persistent_supported)
3726                p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
3727        else
3728                p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
3729
3730        /*      Listen Channel */
3731        /*      Type: */
3732        p2pie[p2pielen++] = P2P_ATTR_LISTEN_CH;
3733
3734        /*      Length: */
3735        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
3736        p2pielen += 2;
3737
3738        /*      Value: */
3739        /*      Country String */
3740        p2pie[p2pielen++] = 'X';
3741        p2pie[p2pielen++] = 'X';
3742
3743        /*      The third byte should be set to 0x04. */
3744        /*      Described in the "Operating Channel Attribute" section. */
3745        p2pie[p2pielen++] = 0x04;
3746
3747        /*      Operating Class */
3748        p2pie[p2pielen++] = 0x51;       /*      Copy from SD7 */
3749
3750        /*      Channel Number */
3751        p2pie[p2pielen++] = pwdinfo->listen_channel;    /*      listen channel */
3752
3753
3754        /*      Extended Listen Timing */
3755        /*      Type: */
3756        p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
3757
3758        /*      Length: */
3759        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
3760        p2pielen += 2;
3761
3762        /*      Value: */
3763        /*      Availability Period */
3764        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
3765        p2pielen += 2;
3766
3767        /*      Availability Interval */
3768        *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
3769        p2pielen += 2;
3770
3771        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
3772                /*      Operating Channel (if this WiFi is working as the group owner now) */
3773                /*      Type: */
3774                p2pie[p2pielen++] = P2P_ATTR_OPERATING_CH;
3775
3776                /*      Length: */
3777                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0005);
3778                p2pielen += 2;
3779
3780                /*      Value: */
3781                /*      Country String */
3782                p2pie[p2pielen++] = 'X';
3783                p2pie[p2pielen++] = 'X';
3784
3785                /*      The third byte should be set to 0x04. */
3786                /*      Described in the "Operating Channel Attribute" section. */
3787                p2pie[p2pielen++] = 0x04;
3788
3789                /*      Operating Class */
3790                p2pie[p2pielen++] = 0x51;       /*      Copy from SD7 */
3791
3792                /*      Channel Number */
3793                p2pie[p2pielen++] = pwdinfo->operating_channel; /*      operating channel number */
3794        }
3795
3796        pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
3797
3798        if (pmlmepriv->wps_probe_req_ie != NULL) {
3799                /* WPS IE */
3800                memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
3801                pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
3802                pframe += pmlmepriv->wps_probe_req_ie_len;
3803        }
3804
3805        pattrib->last_txcmdsz = pattrib->pktlen;
3806
3807        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
3808
3809        if (wait_ack) {
3810                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3811        } else {
3812                dump_mgntframe(padapter, pmgntframe);
3813                ret = _SUCCESS;
3814        }
3815
3816exit:
3817        return ret;
3818}
3819
3820inline void issue_probereq_p2p(struct adapter *adapter, u8 *da)
3821{
3822        _issue_probereq_p2p(adapter, da, false);
3823}
3824
3825int issue_probereq_p2p_ex(struct adapter *adapter, u8 *da, int try_cnt, int wait_ms)
3826{
3827        int ret;
3828        int i = 0;
3829        u32 start = rtw_get_current_time();
3830
3831        do {
3832                ret = _issue_probereq_p2p(adapter, da, wait_ms > 0 ? true : false);
3833
3834                i++;
3835
3836                if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
3837                        break;
3838
3839                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3840                        rtw_msleep_os(wait_ms);
3841        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3842
3843        if (ret != _FAIL) {
3844                ret = _SUCCESS;
3845                goto exit;
3846        }
3847
3848        if (try_cnt && wait_ms) {
3849                if (da)
3850                        DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
3851                                FUNC_ADPT_ARG(adapter), da, rtw_get_oper_ch(adapter),
3852                                ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
3853                else
3854                        DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
3855                                FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter),
3856                                ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
3857        }
3858exit:
3859        return ret;
3860}
3861
3862#endif /* CONFIG_88EU_P2P */
3863
3864static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
3865{
3866        struct adapter *adapter = recv_frame->u.hdr.adapter;
3867        struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
3868        u8 *frame = recv_frame->u.hdr.rx_data;
3869        u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
3870                (recv_frame->u.hdr.attrib.frag_num & 0xf);
3871
3872        if (GetRetry(frame)) {
3873                if (token >= 0) {
3874                        if ((seq_ctrl == mlmeext->action_public_rxseq) && (token == mlmeext->action_public_dialog_token)) {
3875                                DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n",
3876                                        FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
3877                                return _FAIL;
3878                        }
3879                } else {
3880                        if (seq_ctrl == mlmeext->action_public_rxseq) {
3881                                DBG_88E(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n",
3882                                        FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
3883                                return _FAIL;
3884                        }
3885                }
3886        }
3887
3888        mlmeext->action_public_rxseq = seq_ctrl;
3889
3890        if (token >= 0)
3891                mlmeext->action_public_dialog_token = token;
3892
3893        return _SUCCESS;
3894}
3895
3896static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
3897{
3898        u8 *pframe = precv_frame->u.hdr.rx_data;
3899        u8 *frame_body;
3900        u8 dialogToken = 0;
3901#ifdef CONFIG_88EU_P2P
3902        struct adapter *padapter = precv_frame->u.hdr.adapter;
3903        uint len = precv_frame->u.hdr.len;
3904        u8 *p2p_ie;
3905        u32     p2p_ielen;
3906        struct  wifidirect_info *pwdinfo = &(padapter->wdinfo);
3907        u8      result = P2P_STATUS_SUCCESS;
3908        u8      empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3909#endif /* CONFIG_88EU_P2P */
3910
3911        frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
3912
3913        dialogToken = frame_body[7];
3914
3915        if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
3916                return _FAIL;
3917
3918#ifdef CONFIG_88EU_P2P
3919        _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
3920        /*      Do nothing if the driver doesn't enable the P2P function. */
3921        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
3922                return _SUCCESS;
3923
3924        len -= sizeof(struct rtw_ieee80211_hdr_3addr);
3925
3926        switch (frame_body[6]) { /* OUI Subtype */
3927        case P2P_GO_NEGO_REQ:
3928                DBG_88E("[%s] Got GO Nego Req Frame\n", __func__);
3929                _rtw_memset(&pwdinfo->groupid_info, 0x00, sizeof(struct group_id_info));
3930
3931                if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
3932                        rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3933
3934                if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL)) {
3935                        /*      Commented by Albert 20110526 */
3936                        /*      In this case, this means the previous nego fail doesn't be reset yet. */
3937                        _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3938                        /*      Restore the previous p2p state */
3939                        rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
3940                        DBG_88E("[%s] Restore the previous p2p state to %d\n", __func__, rtw_p2p_state(pwdinfo));
3941                }
3942
3943                /*      Commented by Kurt 20110902 */
3944                /* Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
3945                if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
3946                        rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
3947
3948                /*      Commented by Kurt 20120113 */
3949                /*      Get peer_dev_addr here if peer doesn't issue prov_disc frame. */
3950                if (_rtw_memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN))
3951                        memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
3952
3953                result = process_p2p_group_negotation_req(pwdinfo, frame_body, len);
3954                issue_p2p_GO_response(padapter, GetAddr2Ptr(pframe), frame_body, len, result);
3955
3956                /*      Commented by Albert 20110718 */
3957                /*      No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer. */
3958                _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
3959                break;
3960        case P2P_GO_NEGO_RESP:
3961                DBG_88E("[%s] Got GO Nego Resp Frame\n", __func__);
3962
3963                if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING)) {
3964                        /*      Commented by Albert 20110425 */
3965                        /*      The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function. */
3966                        _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
3967                        pwdinfo->nego_req_info.benable = false;
3968                        result = process_p2p_group_negotation_resp(pwdinfo, frame_body, len);
3969                        issue_p2p_GO_confirm(pwdinfo->padapter, GetAddr2Ptr(pframe), result);
3970                        if (P2P_STATUS_SUCCESS == result) {
3971                                if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
3972                                        pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
3973                                        pwdinfo->p2p_info.scan_op_ch_only = 1;
3974                                        _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
3975                                }
3976                        }
3977                        /*      Reset the dialog token for group negotiation frames. */
3978                        pwdinfo->negotiation_dialog_token = 1;
3979                        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
3980                                _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
3981                } else {
3982                        DBG_88E("[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __func__);
3983                }
3984                break;
3985        case P2P_GO_NEGO_CONF:
3986                DBG_88E("[%s] Got GO Nego Confirm Frame\n", __func__);
3987                result = process_p2p_group_negotation_confirm(pwdinfo, frame_body, len);
3988                if (P2P_STATUS_SUCCESS == result) {
3989                        if (rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT) {
3990                                pwdinfo->p2p_info.operation_ch[0] = pwdinfo->peer_operating_ch;
3991                                pwdinfo->p2p_info.scan_op_ch_only = 1;
3992                                _set_timer(&pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH);
3993                        }
3994                }
3995                break;
3996        case P2P_INVIT_REQ:
3997                /*      Added by Albert 2010/10/05 */
3998                /*      Received the P2P Invite Request frame. */
3999
4000                DBG_88E("[%s] Got invite request frame!\n", __func__);
4001                p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
4002                if (p2p_ie) {
4003                        /*      Parse the necessary information from the P2P Invitation Request frame. */
4004                        /*      For example: The MAC address of sending this P2P Invitation Request frame. */
4005                        u32     attr_contentlen = 0;
4006                        u8      status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4007                        struct group_id_info group_id;
4008                        u8      invitation_flag = 0;
4009
4010                        rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
4011                        if (attr_contentlen) {
4012                                rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
4013                                /*      Commented by Albert 20120510 */
4014                                /*      Copy to the pwdinfo->p2p_peer_interface_addr. */
4015                                /*      So that the WFD UI (or Sigma) can get the peer interface address by using the following command. */
4016                                /*      #> iwpriv wlan0 p2p_get peer_ifa */
4017                                /*      After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant. */
4018
4019                                if (attr_contentlen) {
4020                                        DBG_88E("[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __func__,
4021                                                pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
4022                                                pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
4023                                                pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]);
4024                                }
4025
4026                                if (invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT) {
4027                                        /*      Re-invoke the persistent group. */
4028
4029                                        _rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));
4030                                        rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
4031                                        if (attr_contentlen) {
4032                                                if (_rtw_memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
4033                                                        /*      The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO. */
4034                                                        rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO);
4035                                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
4036                                                        status_code = P2P_STATUS_SUCCESS;
4037                                                } else {
4038                                                        /*      The p2p device sending this p2p invitation request wants to be the persistent GO. */
4039                                                        if (is_matched_in_profilelist(pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[0])) {
4040                                                                u8 operatingch_info[5] = { 0x00 };
4041                                                                if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen)) {
4042                                                                        if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4])) {
4043                                                                                /*      The operating channel is acceptable for this device. */
4044                                                                                pwdinfo->rx_invitereq_info.operation_ch[0] = operatingch_info[4];
4045                                                                                pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
4046                                                                                _set_timer(&pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH);
4047                                                                                rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
4048                                                                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4049                                                                                status_code = P2P_STATUS_SUCCESS;
4050                                                                        } else {
4051                                                                                /*      The operating channel isn't supported by this device. */
4052                                                                                rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4053                                                                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4054                                                                                status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
4055                                                                                _set_timer(&pwdinfo->restore_p2p_state_timer, 3000);
4056                                                                        }
4057                                                                } else {
4058                                                                        /*      Commented by Albert 20121130 */
4059                                                                        /*      Intel will use the different P2P IE to store the operating channel information */
4060                                                                        /*      Workaround for Intel WiDi 3.5 */
4061                                                                        rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH);
4062                                                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4063                                                                        status_code = P2P_STATUS_SUCCESS;
4064                                                                }
4065                                                        } else {
4066                                                                rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4067                                                                status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
4068                                                        }
4069                                                }
4070                                        } else {
4071                                                DBG_88E("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
4072                                                status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4073                                        }
4074                                } else {
4075                                        /*      Received the invitation to join a P2P group. */
4076
4077                                        _rtw_memset(&group_id, 0x00, sizeof(struct group_id_info));
4078                                        rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, (u8 *)&group_id, &attr_contentlen);
4079                                        if (attr_contentlen) {
4080                                                if (_rtw_memcmp(group_id.go_device_addr, myid(&padapter->eeprompriv), ETH_ALEN)) {
4081                                                        /*      In this case, the GO can't be myself. */
4082                                                        rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH);
4083                                                        status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4084                                                } else {
4085                                                        /*      The p2p device sending this p2p invitation request wants to join an existing P2P group */
4086                                                        /*      Commented by Albert 2012/06/28 */
4087                                                        /*      In this case, this Wi-Fi device should use the iwpriv command to get the peer device address. */
4088                                                        /*      The peer device address should be the destination address for the provisioning discovery request. */
4089                                                        /*      Then, this Wi-Fi device should use the iwpriv command to get the peer interface address. */
4090                                                        /*      The peer interface address should be the address for WPS mac address */
4091                                                        memcpy(pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN);
4092                                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4093                                                        rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN);
4094                                                        status_code = P2P_STATUS_SUCCESS;
4095                                                }
4096                                        } else {
4097                                                DBG_88E("[%s] P2P Group ID Attribute NOT FOUND!\n", __func__);
4098                                                status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4099                                        }
4100                                }
4101                        } else {
4102                                DBG_88E("[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __func__);
4103                                status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
4104                        }
4105
4106                        DBG_88E("[%s] status_code = %d\n", __func__, status_code);
4107
4108                        pwdinfo->inviteresp_info.token = frame_body[7];
4109                        issue_p2p_invitation_response(padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code);
4110                }
4111                break;
4112        case P2P_INVIT_RESP: {
4113                u8      attr_content = 0x00;
4114                u32     attr_contentlen = 0;
4115
4116                DBG_88E("[%s] Got invite response frame!\n", __func__);
4117                _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
4118                p2p_ie = rtw_get_p2p_ie(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen);
4119                if (p2p_ie) {
4120                        rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
4121
4122                        if (attr_contentlen == 1) {
4123                                DBG_88E("[%s] Status = %d\n", __func__, attr_content);
4124                                pwdinfo->invitereq_info.benable = false;
4125
4126                                if (attr_content == P2P_STATUS_SUCCESS) {
4127                                        if (_rtw_memcmp(pwdinfo->invitereq_info.go_bssid, myid(&padapter->eeprompriv), ETH_ALEN)) {
4128                                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
4129                                        } else {
4130                                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
4131                                        }
4132                                        rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_OK);
4133                                } else {
4134                                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4135                                        rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4136                                }
4137                        } else {
4138                                rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4139                                rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4140                        }
4141                } else {
4142                        rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
4143                        rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL);
4144                }
4145
4146                if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL))
4147                        _set_timer(&pwdinfo->restore_p2p_state_timer, 5000);
4148                break;
4149        }
4150        case P2P_DEVDISC_REQ:
4151                process_p2p_devdisc_req(pwdinfo, pframe, len);
4152                break;
4153        case P2P_DEVDISC_RESP:
4154                process_p2p_devdisc_resp(pwdinfo, pframe, len);
4155                break;
4156        case P2P_PROVISION_DISC_REQ:
4157                DBG_88E("[%s] Got Provisioning Discovery Request Frame\n", __func__);
4158                process_p2p_provdisc_req(pwdinfo, pframe, len);
4159                memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
4160
4161                /* 20110902 Kurt */
4162                /* Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered. */
4163                if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
4164                        rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
4165
4166                rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
4167                _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
4168                break;
4169        case P2P_PROVISION_DISC_RESP:
4170                /*      Commented by Albert 20110707 */
4171                /*      Should we check the pwdinfo->tx_prov_disc_info.bsent flag here?? */
4172                DBG_88E("[%s] Got Provisioning Discovery Response Frame\n", __func__);
4173                /*      Commented by Albert 20110426 */
4174                /*      The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function. */
4175                _cancel_timer_ex(&pwdinfo->restore_p2p_state_timer);
4176                rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
4177                process_p2p_provdisc_resp(pwdinfo, pframe);
4178                _set_timer(&pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT);
4179                break;
4180        }
4181#endif /* CONFIG_88EU_P2P */
4182
4183        return _SUCCESS;
4184}
4185
4186static unsigned int on_action_public_vendor(union recv_frame *precv_frame)
4187{
4188        unsigned int ret = _FAIL;
4189        u8 *pframe = precv_frame->u.hdr.rx_data;
4190        u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
4191
4192        if (_rtw_memcmp(frame_body + 2, P2P_OUI, 4) == true) {
4193                ret = on_action_public_p2p(precv_frame);
4194        }
4195
4196        return ret;
4197}
4198
4199static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
4200{
4201        unsigned int ret = _FAIL;
4202        u8 *pframe = precv_frame->u.hdr.rx_data;
4203        u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
4204        u8 token;
4205
4206        token = frame_body[2];
4207
4208        if (rtw_action_public_decache(precv_frame, token) == _FAIL)
4209                goto exit;
4210
4211        ret = _SUCCESS;
4212
4213exit:
4214        return ret;
4215}
4216
4217unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame)
4218{
4219        unsigned int ret = _FAIL;
4220        u8 *pframe = precv_frame->u.hdr.rx_data;
4221        u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
4222        u8 category, action;
4223
4224        /* check RA matches or not */
4225        if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
4226                goto exit;
4227
4228        category = frame_body[0];
4229        if (category != RTW_WLAN_CATEGORY_PUBLIC)
4230                goto exit;
4231
4232        action = frame_body[1];
4233        switch (action) {
4234        case ACT_PUBLIC_VENDOR:
4235                ret = on_action_public_vendor(precv_frame);
4236                break;
4237        default:
4238                ret = on_action_public_default(precv_frame, action);
4239                break;
4240        }
4241
4242exit:
4243        return ret;
4244}
4245
4246unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame)
4247{
4248        return _SUCCESS;
4249}
4250
4251unsigned int OnAction_wmm(struct adapter *padapter, union recv_frame *precv_frame)
4252{
4253        return _SUCCESS;
4254}
4255
4256unsigned int OnAction_p2p(struct adapter *padapter, union recv_frame *precv_frame)
4257{
4258#ifdef CONFIG_88EU_P2P
4259        u8 *frame_body;
4260        u8 category, OUI_Subtype;
4261        u8 *pframe = precv_frame->u.hdr.rx_data;
4262        uint len = precv_frame->u.hdr.len;
4263        struct  wifidirect_info *pwdinfo = &(padapter->wdinfo);
4264
4265
4266        DBG_88E("%s\n", __func__);
4267
4268        /* check RA matches or not */
4269        if (!_rtw_memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
4270                return _SUCCESS;
4271
4272        frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
4273
4274        category = frame_body[0];
4275        if (category != RTW_WLAN_CATEGORY_P2P)
4276                return _SUCCESS;
4277
4278        if (be32_to_cpu(*((__be32 *)(frame_body + 1))) != P2POUI)
4279                return _SUCCESS;
4280
4281        len -= sizeof(struct rtw_ieee80211_hdr_3addr);
4282        OUI_Subtype = frame_body[5];
4283
4284        switch (OUI_Subtype) {
4285        case P2P_NOTICE_OF_ABSENCE:
4286                break;
4287        case P2P_PRESENCE_REQUEST:
4288                process_p2p_presence_req(pwdinfo, pframe, len);
4289                break;
4290        case P2P_PRESENCE_RESPONSE:
4291                break;
4292        case P2P_GO_DISC_REQUEST:
4293                break;
4294        default:
4295                break;
4296        }
4297#endif /* CONFIG_88EU_P2P */
4298        return _SUCCESS;
4299}
4300
4301unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame)
4302{
4303        int i;
4304        unsigned char   category;
4305        struct action_handler *ptable;
4306        unsigned char   *frame_body;
4307        u8 *pframe = precv_frame->u.hdr.rx_data;
4308
4309        frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
4310
4311        category = frame_body[0];
4312
4313        for (i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++) {
4314                ptable = &OnAction_tbl[i];
4315                if (category == ptable->num)
4316                        ptable->func(padapter, precv_frame);
4317        }
4318        return _SUCCESS;
4319}
4320
4321unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame)
4322{
4323        return _SUCCESS;
4324}
4325
4326struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
4327{
4328        struct xmit_frame                       *pmgntframe;
4329        struct xmit_buf                         *pxmitbuf;
4330
4331        pmgntframe = rtw_alloc_xmitframe(pxmitpriv);
4332        if (pmgntframe == NULL) {
4333                DBG_88E("%s, alloc xmitframe fail\n", __func__);
4334                return NULL;
4335        }
4336
4337        pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
4338        if (pxmitbuf == NULL) {
4339                DBG_88E("%s, alloc xmitbuf fail\n", __func__);
4340                rtw_free_xmitframe(pxmitpriv, pmgntframe);
4341                return NULL;
4342        }
4343        pmgntframe->frame_tag = MGNT_FRAMETAG;
4344        pmgntframe->pxmitbuf = pxmitbuf;
4345        pmgntframe->buf_addr = pxmitbuf->pbuf;
4346        pxmitbuf->priv_data = pmgntframe;
4347        return pmgntframe;
4348}
4349
4350/****************************************************************************
4351
4352Following are some TX fuctions for WiFi MLME
4353
4354*****************************************************************************/
4355
4356void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
4357{
4358        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4359
4360        pmlmeext->tx_rate = rate;
4361        DBG_88E("%s(): rate = %x\n", __func__, rate);
4362}
4363
4364void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
4365{
4366        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4367
4368        _rtw_memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
4369
4370        pattrib->hdrlen = 24;
4371        pattrib->nr_frags = 1;
4372        pattrib->priority = 7;
4373        pattrib->mac_id = 0;
4374        pattrib->qsel = 0x12;
4375
4376        pattrib->pktlen = 0;
4377
4378        if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
4379                pattrib->raid = 6;/* b mode */
4380        else
4381                pattrib->raid = 5;/* a/g mode */
4382
4383        pattrib->encrypt = _NO_PRIVACY_;
4384        pattrib->bswenc = false;
4385
4386        pattrib->qos_en = false;
4387        pattrib->ht_en = false;
4388        pattrib->bwmode = HT_CHANNEL_WIDTH_20;
4389        pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
4390        pattrib->sgi = false;
4391
4392        pattrib->seqnum = pmlmeext->mgnt_seq;
4393
4394        pattrib->retry_ctrl = true;
4395}
4396
4397void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
4398{
4399        if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4400                return;
4401
4402        rtw_hal_mgnt_xmit(padapter, pmgntframe);
4403}
4404
4405s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
4406{
4407        s32 ret = _FAIL;
4408        struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
4409        struct submit_ctx sctx;
4410
4411        if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4412                return ret;
4413
4414        rtw_sctx_init(&sctx, timeout_ms);
4415        pxmitbuf->sctx = &sctx;
4416
4417        ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
4418
4419        if (ret == _SUCCESS)
4420                ret = rtw_sctx_wait(&sctx);
4421
4422         return ret;
4423}
4424
4425s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
4426{
4427        s32 ret = _FAIL;
4428        u32 timeout_ms = 500;/*   500ms */
4429        struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
4430
4431        if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
4432                return -1;
4433
4434        _enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
4435        pxmitpriv->ack_tx = true;
4436
4437        pmgntframe->ack_report = 1;
4438        if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
4439                ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
4440        }
4441
4442        pxmitpriv->ack_tx = false;
4443        _exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
4444
4445         return ret;
4446}
4447
4448static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
4449{
4450        u8 *ssid_ie;
4451        int ssid_len_ori;
4452        int len_diff = 0;
4453
4454        ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
4455
4456        if (ssid_ie && ssid_len_ori > 0) {
4457                switch (hidden_ssid_mode) {
4458                case 1: {
4459                        u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
4460                        u32 remain_len = 0;
4461
4462                        remain_len = ies_len - (next_ie - ies);
4463
4464                        ssid_ie[1] = 0;
4465                        memcpy(ssid_ie+2, next_ie, remain_len);
4466                        len_diff -= ssid_len_ori;
4467
4468                        break;
4469                }
4470                case 2:
4471                        _rtw_memset(&ssid_ie[2], 0, ssid_len_ori);
4472                        break;
4473                default:
4474                        break;
4475                }
4476        }
4477
4478        return len_diff;
4479}
4480
4481void issue_beacon(struct adapter *padapter, int timeout_ms)
4482{
4483        struct xmit_frame       *pmgntframe;
4484        struct pkt_attrib       *pattrib;
4485        unsigned char   *pframe;
4486        struct rtw_ieee80211_hdr *pwlanhdr;
4487        unsigned short *fctrl;
4488        unsigned int    rate_len;
4489        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
4490#if defined(CONFIG_88EU_AP_MODE)
4491        unsigned long irqL;
4492#endif /* if defined (CONFIG_88EU_AP_MODE) */
4493        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4494        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4495        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4496        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
4497        u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4498#ifdef CONFIG_88EU_P2P
4499        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4500#endif /* CONFIG_88EU_P2P */
4501
4502        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4503        if (pmgntframe == NULL) {
4504                DBG_88E("%s, alloc mgnt frame fail\n", __func__);
4505                return;
4506        }
4507#if defined (CONFIG_88EU_AP_MODE)
4508        _enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
4509#endif /* if defined (CONFIG_88EU_AP_MODE) */
4510
4511        /* update attribute */
4512        pattrib = &pmgntframe->attrib;
4513        update_mgntframe_attrib(padapter, pattrib);
4514        pattrib->qsel = 0x10;
4515
4516        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4517
4518        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4519        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4520
4521
4522        fctrl = &(pwlanhdr->frame_ctl);
4523        *(fctrl) = 0;
4524
4525        memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
4526        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4527        memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
4528
4529        SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
4530        /* pmlmeext->mgnt_seq++; */
4531        SetFrameSubType(pframe, WIFI_BEACON);
4532
4533        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
4534        pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
4535
4536        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
4537#ifdef CONFIG_88EU_P2P
4538                /*  for P2P : Primary Device Type & Device Name */
4539                u32 wpsielen = 0, insert_len = 0;
4540                u8 *wpsie = NULL;
4541                wpsie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wpsielen);
4542
4543                if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen > 0) {
4544                        uint wps_offset, remainder_ielen;
4545                        u8 *premainder_ie, *pframe_wscie;
4546
4547                        wps_offset = (uint)(wpsie - cur_network->IEs);
4548                        premainder_ie = wpsie + wpsielen;
4549                        remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
4550                        pframe_wscie = pframe + wps_offset;
4551                        memcpy(pframe, cur_network->IEs, wps_offset+wpsielen);
4552                        pframe += (wps_offset + wpsielen);
4553                        pattrib->pktlen += (wps_offset + wpsielen);
4554
4555                        /* now pframe is end of wsc ie, insert Primary Device Type & Device Name */
4556                        /*      Primary Device Type */
4557                        /*      Type: */
4558                        *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_PRIMARY_DEV_TYPE);
4559                        insert_len += 2;
4560
4561                        /*      Length: */
4562                        *(__be16 *)(pframe + insert_len) = cpu_to_be16(0x0008);
4563                        insert_len += 2;
4564
4565                        /*      Value: */
4566                        /*      Category ID */
4567                        *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
4568                        insert_len += 2;
4569
4570                        /*      OUI */
4571                        *(__be32 *)(pframe + insert_len) = cpu_to_be32(WPSOUI);
4572                        insert_len += 4;
4573
4574                        /*      Sub Category ID */
4575                        *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
4576                        insert_len += 2;
4577
4578                        /*      Device Name */
4579                        /*      Type: */
4580                        *(__be16 *)(pframe + insert_len) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
4581                        insert_len += 2;
4582
4583                        /*      Length: */
4584                        *(__be16 *)(pframe + insert_len) = cpu_to_be16(pwdinfo->device_name_len);
4585                        insert_len += 2;
4586
4587                        /*      Value: */
4588                        memcpy(pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len);
4589                        insert_len += pwdinfo->device_name_len;
4590
4591                        /* update wsc ie length */
4592                        *(pframe_wscie+1) = (wpsielen-2) + insert_len;
4593
4594                        /* pframe move to end */
4595                        pframe += insert_len;
4596                        pattrib->pktlen += insert_len;
4597
4598                        /* copy remainder_ie to pframe */
4599                        memcpy(pframe, premainder_ie, remainder_ielen);
4600                        pframe += remainder_ielen;
4601                        pattrib->pktlen += remainder_ielen;
4602                } else
4603#endif /* CONFIG_88EU_P2P */
4604                {
4605                        int len_diff;
4606                        memcpy(pframe, cur_network->IEs, cur_network->IELength);
4607                        len_diff = update_hidden_ssid(
4608                                pframe+_BEACON_IE_OFFSET_
4609                                , cur_network->IELength-_BEACON_IE_OFFSET_
4610                                , pmlmeinfo->hidden_ssid_mode
4611                        );
4612                        pframe += (cur_network->IELength+len_diff);
4613                        pattrib->pktlen += (cur_network->IELength+len_diff);
4614                }
4615
4616                {
4617                        u8 *wps_ie;
4618                        uint wps_ielen;
4619                        u8 sr = 0;
4620                        wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof (struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
4621                                pattrib->pktlen-sizeof (struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
4622                        if (wps_ie && wps_ielen > 0)
4623                                rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
4624                        if (sr != 0)
4625                                set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
4626                        else
4627                                _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
4628                }
4629
4630#ifdef CONFIG_88EU_P2P
4631                if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
4632                        u32 len;
4633                        len = build_beacon_p2p_ie(pwdinfo, pframe);
4634
4635                        pframe += len;
4636                        pattrib->pktlen += len;
4637                }
4638#endif /* CONFIG_88EU_P2P */
4639
4640                goto _issue_bcn;
4641        }
4642
4643        /* below for ad-hoc mode */
4644
4645        /* timestamp will be inserted by hardware */
4646        pframe += 8;
4647        pattrib->pktlen += 8;
4648
4649        /*  beacon interval: 2 bytes */
4650
4651        memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
4652
4653        pframe += 2;
4654        pattrib->pktlen += 2;
4655
4656        /*  capability info: 2 bytes */
4657
4658        memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
4659
4660        pframe += 2;
4661        pattrib->pktlen += 2;
4662
4663        /*  SSID */
4664        pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
4665
4666        /*  supported rates... */
4667        rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
4668        pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
4669
4670        /*  DS parameter set */
4671        pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
4672
4673        {
4674                u8 erpinfo = 0;
4675                u32 ATIMWindow;
4676                /*  IBSS Parameter Set... */
4677                ATIMWindow = 0;
4678                pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
4679
4680                /* ERP IE */
4681                pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
4682        }
4683
4684        /*  EXTERNDED SUPPORTED RATE */
4685        if (rate_len > 8)
4686                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
4687        /* todo:HT for adhoc */
4688_issue_bcn:
4689
4690#if defined (CONFIG_88EU_AP_MODE)
4691        pmlmepriv->update_bcn = false;
4692
4693        _exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
4694#endif /* if defined (CONFIG_88EU_AP_MODE) */
4695
4696        if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
4697                DBG_88E("beacon frame too large\n");
4698                return;
4699        }
4700
4701        pattrib->last_txcmdsz = pattrib->pktlen;
4702
4703        /* DBG_88E("issue bcn_sz=%d\n", pattrib->last_txcmdsz); */
4704        if (timeout_ms > 0)
4705                dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
4706        else
4707                dump_mgntframe(padapter, pmgntframe);
4708}
4709
4710void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
4711{
4712        struct xmit_frame                       *pmgntframe;
4713        struct pkt_attrib                       *pattrib;
4714        unsigned char                                   *pframe;
4715        struct rtw_ieee80211_hdr        *pwlanhdr;
4716        unsigned short                          *fctrl;
4717        unsigned char                                   *mac, *bssid;
4718        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
4719#if defined (CONFIG_88EU_AP_MODE)
4720        u8 *pwps_ie;
4721        uint wps_ielen;
4722        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4723#endif /* if defined (CONFIG_88EU_AP_MODE) */
4724        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4725        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
4726        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
4727        unsigned int    rate_len;
4728#ifdef CONFIG_88EU_P2P
4729        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
4730#endif /* CONFIG_88EU_P2P */
4731
4732        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4733        if (pmgntframe == NULL) {
4734                DBG_88E("%s, alloc mgnt frame fail\n", __func__);
4735                return;
4736        }
4737
4738        /* update attribute */
4739        pattrib = &pmgntframe->attrib;
4740        update_mgntframe_attrib(padapter, pattrib);
4741
4742        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4743
4744        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4745        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4746
4747        mac = myid(&(padapter->eeprompriv));
4748        bssid = cur_network->MacAddress;
4749
4750        fctrl = &(pwlanhdr->frame_ctl);
4751        *(fctrl) = 0;
4752        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
4753        memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
4754        memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
4755
4756        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4757        pmlmeext->mgnt_seq++;
4758        SetFrameSubType(fctrl, WIFI_PROBERSP);
4759
4760        pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
4761        pattrib->pktlen = pattrib->hdrlen;
4762        pframe += pattrib->hdrlen;
4763
4764        if (cur_network->IELength > MAX_IE_SZ)
4765                return;
4766
4767#if defined(CONFIG_88EU_AP_MODE)
4768        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
4769                pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
4770
4771                /* inerset & update wps_probe_resp_ie */
4772                if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
4773                        uint wps_offset, remainder_ielen;
4774                        u8 *premainder_ie;
4775
4776                        wps_offset = (uint)(pwps_ie - cur_network->IEs);
4777
4778                        premainder_ie = pwps_ie + wps_ielen;
4779
4780                        remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
4781
4782                        memcpy(pframe, cur_network->IEs, wps_offset);
4783                        pframe += wps_offset;
4784                        pattrib->pktlen += wps_offset;
4785
4786                        wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
4787                        if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
4788                                memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
4789                                pframe += wps_ielen+2;
4790                                pattrib->pktlen += wps_ielen+2;
4791                        }
4792
4793                        if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
4794                                memcpy(pframe, premainder_ie, remainder_ielen);
4795                                pframe += remainder_ielen;
4796                                pattrib->pktlen += remainder_ielen;
4797                        }
4798                } else {
4799                        memcpy(pframe, cur_network->IEs, cur_network->IELength);
4800                        pframe += cur_network->IELength;
4801                        pattrib->pktlen += cur_network->IELength;
4802                }
4803        } else
4804#endif
4805        {
4806                /* timestamp will be inserted by hardware */
4807                pframe += 8;
4808                pattrib->pktlen += 8;
4809
4810                /*  beacon interval: 2 bytes */
4811
4812                memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
4813
4814                pframe += 2;
4815                pattrib->pktlen += 2;
4816
4817                /*  capability info: 2 bytes */
4818
4819                memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
4820
4821                pframe += 2;
4822                pattrib->pktlen += 2;
4823
4824                /* below for ad-hoc mode */
4825
4826                /*  SSID */
4827                pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
4828
4829                /*  supported rates... */
4830                rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
4831                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
4832
4833                /*  DS parameter set */
4834                pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
4835
4836                if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
4837                        u8 erpinfo = 0;
4838                        u32 ATIMWindow;
4839                        /*  IBSS Parameter Set... */
4840                        /* ATIMWindow = cur->Configuration.ATIMWindow; */
4841                        ATIMWindow = 0;
4842                        pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
4843
4844                        /* ERP IE */
4845                        pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
4846                }
4847
4848
4849                /*  EXTERNDED SUPPORTED RATE */
4850                if (rate_len > 8)
4851                        pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
4852                /* todo:HT for adhoc */
4853        }
4854
4855#ifdef CONFIG_88EU_P2P
4856        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && is_valid_p2p_probereq) {
4857                u32 len;
4858                len = build_probe_resp_p2p_ie(pwdinfo, pframe);
4859
4860                pframe += len;
4861                pattrib->pktlen += len;
4862        }
4863#endif /* CONFIG_88EU_P2P */
4864
4865        pattrib->last_txcmdsz = pattrib->pktlen;
4866
4867        dump_mgntframe(padapter, pmgntframe);
4868
4869        return;
4870}
4871
4872static int _issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, int wait_ack)
4873{
4874        int ret = _FAIL;
4875        struct xmit_frame               *pmgntframe;
4876        struct pkt_attrib               *pattrib;
4877        unsigned char                   *pframe;
4878        struct rtw_ieee80211_hdr        *pwlanhdr;
4879        unsigned short          *fctrl;
4880        unsigned char                   *mac;
4881        unsigned char                   bssrate[NumRates];
4882        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
4883        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
4884        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
4885        int     bssrate_len = 0;
4886        u8      bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
4887
4888        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+issue_probereq\n"));
4889
4890        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4891        if (pmgntframe == NULL)
4892                goto exit;
4893
4894        /* update attribute */
4895        pattrib = &pmgntframe->attrib;
4896        update_mgntframe_attrib(padapter, pattrib);
4897
4898
4899        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4900
4901        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4902        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
4903
4904        mac = myid(&(padapter->eeprompriv));
4905
4906        fctrl = &(pwlanhdr->frame_ctl);
4907        *(fctrl) = 0;
4908
4909        if (da) {
4910                /*      unicast probe request frame */
4911                memcpy(pwlanhdr->addr1, da, ETH_ALEN);
4912                memcpy(pwlanhdr->addr3, da, ETH_ALEN);
4913        } else {
4914                /*      broadcast probe request frame */
4915                memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
4916                memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
4917        }
4918
4919        memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
4920
4921        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4922        pmlmeext->mgnt_seq++;
4923        SetFrameSubType(pframe, WIFI_PROBEREQ);
4924
4925        pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
4926        pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
4927
4928        if (pssid)
4929                pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
4930        else
4931                pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
4932
4933        get_rate_set(padapter, bssrate, &bssrate_len);
4934
4935        if (bssrate_len > 8) {
4936                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
4937                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
4938        } else {
4939                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
4940        }
4941
4942        /* add wps_ie for wps2.0 */
4943        if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
4944                memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
4945                pframe += pmlmepriv->wps_probe_req_ie_len;
4946                pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
4947        }
4948
4949        pattrib->last_txcmdsz = pattrib->pktlen;
4950
4951        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4952                 ("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
4953
4954        if (wait_ack) {
4955                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
4956        } else {
4957                dump_mgntframe(padapter, pmgntframe);
4958                ret = _SUCCESS;
4959        }
4960
4961exit:
4962        return ret;
4963}
4964
4965inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
4966{
4967        _issue_probereq(padapter, pssid, da, false);
4968}
4969
4970int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da,
4971        int try_cnt, int wait_ms)
4972{
4973        int ret;
4974        int i = 0;
4975        u32 start = rtw_get_current_time();
4976
4977        do {
4978                ret = _issue_probereq(padapter, pssid, da, wait_ms > 0 ? true : false);
4979
4980                i++;
4981
4982                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
4983                        break;
4984
4985                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
4986                        rtw_msleep_os(wait_ms);
4987
4988        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
4989
4990        if (ret != _FAIL) {
4991                ret = _SUCCESS;
4992                goto exit;
4993        }
4994
4995        if (try_cnt && wait_ms) {
4996                if (da)
4997                        DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
4998                                FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
4999                                ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5000                else
5001                        DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5002                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
5003                                ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5004        }
5005exit:
5006        return ret;
5007}
5008
5009/*  if psta == NULL, indiate we are station(client) now... */
5010void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
5011{
5012        struct xmit_frame *pmgntframe;
5013        struct pkt_attrib *pattrib;
5014        unsigned char *pframe;
5015        struct rtw_ieee80211_hdr *pwlanhdr;
5016        unsigned short *fctrl;
5017        unsigned int val32;
5018        u16 val16;
5019#ifdef CONFIG_88EU_AP_MODE
5020        __le16 le_val16;
5021#endif
5022        int use_shared_key = 0;
5023        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
5024        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5025        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5026
5027        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5028        if (pmgntframe == NULL)
5029                return;
5030
5031        /* update attribute */
5032        pattrib = &pmgntframe->attrib;
5033        update_mgntframe_attrib(padapter, pattrib);
5034
5035        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5036
5037        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5038        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5039
5040        fctrl = &(pwlanhdr->frame_ctl);
5041        *(fctrl) = 0;
5042
5043        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5044        pmlmeext->mgnt_seq++;
5045        SetFrameSubType(pframe, WIFI_AUTH);
5046
5047        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
5048        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5049
5050
5051        if (psta) {/*  for AP mode */
5052#ifdef CONFIG_88EU_AP_MODE
5053
5054                memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
5055                memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5056                memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
5057
5058
5059                /*  setting auth algo number */
5060                val16 = (u16)psta->authalg;
5061
5062                if (status != _STATS_SUCCESSFUL_)
5063                        val16 = 0;
5064
5065                if (val16) {
5066                        le_val16 = cpu_to_le16(val16);
5067                        use_shared_key = 1;
5068                } else {
5069                        le_val16 = 0;
5070                }
5071
5072                pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_val16, &(pattrib->pktlen));
5073
5074                /*  setting auth seq number */
5075                val16 = (u16)psta->auth_seq;
5076                le_val16 = cpu_to_le16(val16);
5077                pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_val16, &(pattrib->pktlen));
5078
5079                /*  setting status code... */
5080                val16 = status;
5081                le_val16 = cpu_to_le16(val16);
5082                pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_val16, &(pattrib->pktlen));
5083
5084                /*  added challenging text... */
5085                if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
5086                        pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
5087#endif
5088        } else {
5089                __le32 le_tmp32;
5090                __le16 le_tmp16;
5091                memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5092                memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
5093                memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
5094
5095                /*  setting auth algo number */
5096                val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/*  0:OPEN System, 1:Shared key */
5097                if (val16)
5098                        use_shared_key = 1;
5099
5100                /* setting IV for auth seq #3 */
5101                if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
5102                        val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
5103                        le_tmp32 = cpu_to_le32(val32);
5104                        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen));
5105
5106                        pattrib->iv_len = 4;
5107                }
5108
5109                le_tmp16 = cpu_to_le16(val16);
5110                pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp16, &(pattrib->pktlen));
5111
5112                /*  setting auth seq number */
5113                val16 = pmlmeinfo->auth_seq;
5114                le_tmp16 = cpu_to_le16(val16);
5115                pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp16, &(pattrib->pktlen));
5116
5117
5118                /*  setting status code... */
5119                le_tmp16 = cpu_to_le16(status);
5120                pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp16, &(pattrib->pktlen));
5121
5122                /*  then checking to see if sending challenging text... */
5123                if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
5124                        pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
5125
5126                        SetPrivacy(fctrl);
5127
5128                        pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5129
5130                        pattrib->encrypt = _WEP40_;
5131
5132                        pattrib->icv_len = 4;
5133
5134                        pattrib->pktlen += pattrib->icv_len;
5135                }
5136        }
5137
5138        pattrib->last_txcmdsz = pattrib->pktlen;
5139
5140        rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
5141        DBG_88E("%s\n", __func__);
5142        dump_mgntframe(padapter, pmgntframe);
5143
5144        return;
5145}
5146
5147
5148void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
5149{
5150#ifdef CONFIG_88EU_AP_MODE
5151        struct xmit_frame       *pmgntframe;
5152        struct rtw_ieee80211_hdr        *pwlanhdr;
5153        struct pkt_attrib *pattrib;
5154        unsigned char   *pbuf, *pframe;
5155        unsigned short val;
5156        unsigned short *fctrl;
5157        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
5158        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5159        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5160        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5161        struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
5162        u8 *ie = pnetwork->IEs;
5163        __le16 lestatus, leval;
5164#ifdef CONFIG_88EU_P2P
5165        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
5166#endif /* CONFIG_88EU_P2P */
5167
5168        DBG_88E("%s\n", __func__);
5169
5170        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5171        if (pmgntframe == NULL)
5172                return;
5173
5174        /* update attribute */
5175        pattrib = &pmgntframe->attrib;
5176        update_mgntframe_attrib(padapter, pattrib);
5177
5178
5179        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5180
5181        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5182        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5183
5184        fctrl = &(pwlanhdr->frame_ctl);
5185        *(fctrl) = 0;
5186
5187        memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
5188        memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
5189        memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5190
5191
5192        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5193        pmlmeext->mgnt_seq++;
5194        if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
5195                SetFrameSubType(pwlanhdr, pkt_type);
5196        else
5197                return;
5198
5199        pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5200        pattrib->pktlen += pattrib->hdrlen;
5201        pframe += pattrib->hdrlen;
5202
5203        /* capability */
5204        val = *(unsigned short *)rtw_get_capability_from_ie(ie);
5205
5206        pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_ , (unsigned char *)&val, &(pattrib->pktlen));
5207
5208        lestatus = cpu_to_le16(status);
5209        pframe = rtw_set_fixed_ie(pframe , _STATUS_CODE_ , (unsigned char *)&lestatus, &(pattrib->pktlen));
5210
5211        leval = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
5212        pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_ , (unsigned char *)&leval, &(pattrib->pktlen));
5213
5214        if (pstat->bssratelen <= 8) {
5215                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
5216        } else {
5217                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
5218                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
5219        }
5220
5221        if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
5222                uint ie_len = 0;
5223
5224                /* FILL HT CAP INFO IE */
5225                pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
5226                if (pbuf && ie_len > 0) {
5227                        memcpy(pframe, pbuf, ie_len+2);
5228                        pframe += (ie_len+2);
5229                        pattrib->pktlen += (ie_len+2);
5230                }
5231
5232                /* FILL HT ADD INFO IE */
5233                pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
5234                if (pbuf && ie_len > 0) {
5235                        memcpy(pframe, pbuf, ie_len+2);
5236                        pframe += (ie_len+2);
5237                        pattrib->pktlen += (ie_len+2);
5238                }
5239        }
5240
5241        /* FILL WMM IE */
5242        if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
5243                uint ie_len = 0;
5244                unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
5245
5246                for (pbuf = ie + _BEACON_IE_OFFSET_;; pbuf += (ie_len + 2)) {
5247                        pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
5248                        if (pbuf && _rtw_memcmp(pbuf+2, WMM_PARA_IE, 6)) {
5249                                memcpy(pframe, pbuf, ie_len+2);
5250                                pframe += (ie_len+2);
5251                                pattrib->pktlen += (ie_len+2);
5252                                break;
5253                        }
5254
5255                        if ((pbuf == NULL) || (ie_len == 0))
5256                                break;
5257                }
5258        }
5259
5260        if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
5261                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
5262
5263        /* add WPS IE ie for wps 2.0 */
5264        if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
5265                memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
5266
5267                pframe += pmlmepriv->wps_assoc_resp_ie_len;
5268                pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
5269        }
5270
5271#ifdef CONFIG_88EU_P2P
5272        if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device)) {
5273                u32 len;
5274
5275                len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
5276
5277                pframe += len;
5278                pattrib->pktlen += len;
5279        }
5280#endif /* CONFIG_88EU_P2P */
5281        pattrib->last_txcmdsz = pattrib->pktlen;
5282        dump_mgntframe(padapter, pmgntframe);
5283#endif
5284}
5285
5286void issue_assocreq(struct adapter *padapter)
5287{
5288        int ret = _FAIL;
5289        struct xmit_frame       *pmgntframe;
5290        struct pkt_attrib       *pattrib;
5291        unsigned char           *pframe, *p;
5292        struct rtw_ieee80211_hdr        *pwlanhdr;
5293        unsigned short  *fctrl;
5294        __le16          le_tmp;
5295        unsigned int    i, j, ie_len, index = 0;
5296        unsigned char   rf_type, bssrate[NumRates], sta_bssrate[NumRates];
5297        struct ndis_802_11_var_ie *pIE;
5298        struct registry_priv    *pregpriv = &padapter->registrypriv;
5299        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
5300        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5301        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5302        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5303        int     bssrate_len = 0, sta_bssrate_len = 0;
5304#ifdef CONFIG_88EU_P2P
5305        struct wifidirect_info  *pwdinfo = &(padapter->wdinfo);
5306        u8 p2pie[255] = { 0x00 };
5307        u16 p2pielen = 0;
5308#endif /* CONFIG_88EU_P2P */
5309
5310        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5311        if (pmgntframe == NULL)
5312                goto exit;
5313
5314        /* update attribute */
5315        pattrib = &pmgntframe->attrib;
5316        update_mgntframe_attrib(padapter, pattrib);
5317
5318        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5319        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5320        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5321
5322        fctrl = &(pwlanhdr->frame_ctl);
5323        *(fctrl) = 0;
5324        memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5325        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5326        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5327
5328        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5329        pmlmeext->mgnt_seq++;
5330        SetFrameSubType(pframe, WIFI_ASSOCREQ);
5331
5332        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
5333        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5334
5335        /* caps */
5336
5337        memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
5338
5339        pframe += 2;
5340        pattrib->pktlen += 2;
5341
5342        /* listen interval */
5343        /* todo: listen interval for power saving */
5344        le_tmp = cpu_to_le16(3);
5345        memcpy(pframe , (unsigned char *)&le_tmp, 2);
5346        pframe += 2;
5347        pattrib->pktlen += 2;
5348
5349        /* SSID */
5350        pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
5351
5352        /* supported rate & extended supported rate */
5353
5354        /*  Check if the AP's supported rates are also supported by STA. */
5355        get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
5356
5357        if (pmlmeext->cur_channel == 14)/*  for JAPAN, channel 14 can only uses B Mode(CCK) */
5358                sta_bssrate_len = 4;
5359
5360        for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
5361                if (pmlmeinfo->network.SupportedRates[i] == 0)
5362                        break;
5363                DBG_88E("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
5364        }
5365
5366        for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
5367                if (pmlmeinfo->network.SupportedRates[i] == 0)
5368                        break;
5369
5370                /*  Check if the AP's supported rates are also supported by STA. */
5371                for (j = 0; j < sta_bssrate_len; j++) {
5372                         /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
5373                        if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
5374                                        == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK))
5375                                break;
5376                }
5377
5378                if (j == sta_bssrate_len) {
5379                        /*  the rate is not supported by STA */
5380                        DBG_88E("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]);
5381                } else {
5382                        /*  the rate is supported by STA */
5383                        bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
5384                }
5385        }
5386
5387        bssrate_len = index;
5388        DBG_88E("bssrate_len=%d\n", bssrate_len);
5389
5390        if (bssrate_len == 0) {
5391                rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
5392                rtw_free_xmitframe(pxmitpriv, pmgntframe);
5393                goto exit; /* don't connect to AP if no joint supported rate */
5394        }
5395
5396
5397        if (bssrate_len > 8) {
5398                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
5399                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
5400        } else {
5401                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
5402        }
5403
5404        /* RSN */
5405        p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _RSN_IE_2_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
5406        if (p != NULL)
5407                pframe = rtw_set_ie(pframe, _RSN_IE_2_, ie_len, (p + 2), &(pattrib->pktlen));
5408
5409        /* HT caps */
5410        if (padapter->mlmepriv.htpriv.ht_option) {
5411                p = rtw_get_ie((pmlmeinfo->network.IEs + sizeof(struct ndis_802_11_fixed_ie)), _HT_CAPABILITY_IE_, &ie_len, (pmlmeinfo->network.IELength - sizeof(struct ndis_802_11_fixed_ie)));
5412                if ((p != NULL) && (!(is_ap_in_tkip(padapter)))) {
5413                        memcpy(&(pmlmeinfo->HT_caps), (p + 2), sizeof(struct HT_caps_element));
5414
5415                        /* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
5416                        if (pregpriv->cbw40_enable == 0)
5417                                pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info &= cpu_to_le16(~(BIT(6) | BIT(1)));
5418                        else
5419                                pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(BIT(1));
5420
5421                        /* todo: disable SM power save mode */
5422                        pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x000c);
5423
5424                        rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
5425                        switch (rf_type) {
5426                        case RF_1T1R:
5427                                if (pregpriv->rx_stbc)
5428                                        pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0100);/* RX STBC One spatial stream */
5429                                memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_1R, 16);
5430                                break;
5431                        case RF_2T2R:
5432                        case RF_1T2R:
5433                        default:
5434                                if ((pregpriv->rx_stbc == 0x3) ||/* enable for 2.4/5 GHz */
5435                                    ((pmlmeext->cur_wireless_mode & WIRELESS_11_24N) && (pregpriv->rx_stbc == 0x1)) || /* enable for 2.4GHz */
5436                                    (pregpriv->wifi_spec == 1)) {
5437                                        DBG_88E("declare supporting RX STBC\n");
5438                                        pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |= cpu_to_le16(0x0200);/* RX STBC two spatial stream */
5439                                }
5440                                memcpy(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_rate_2R, 16);
5441                                break;
5442                        }
5443                        pframe = rtw_set_ie(pframe, _HT_CAPABILITY_IE_, ie_len , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
5444                }
5445        }
5446
5447        /* vendor specific IE, such as WPA, WMM, WPS */
5448        for (i = sizeof(struct ndis_802_11_fixed_ie); i < pmlmeinfo->network.IELength;) {
5449                pIE = (struct ndis_802_11_var_ie *)(pmlmeinfo->network.IEs + i);
5450
5451                switch (pIE->ElementID) {
5452                case _VENDOR_SPECIFIC_IE_:
5453                        if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
5454                            (_rtw_memcmp(pIE->data, WMM_OUI, 4)) ||
5455                            (_rtw_memcmp(pIE->data, WPS_OUI, 4))) {
5456                                if (!padapter->registrypriv.wifi_spec) {
5457                                        /* Commented by Kurt 20110629 */
5458                                        /* In some older APs, WPS handshake */
5459                                        /* would be fail if we append vender extensions informations to AP */
5460                                        if (_rtw_memcmp(pIE->data, WPS_OUI, 4))
5461                                                pIE->Length = 14;
5462                                }
5463                                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, pIE->Length, pIE->data, &(pattrib->pktlen));
5464                        }
5465                        break;
5466                default:
5467                        break;
5468                }
5469                i += (pIE->Length + 2);
5470        }
5471
5472        if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
5473                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
5474
5475#ifdef CONFIG_88EU_P2P
5476
5477        if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
5478                /*      Should add the P2P IE in the association request frame. */
5479                /*      P2P OUI */
5480
5481                p2pielen = 0;
5482                p2pie[p2pielen++] = 0x50;
5483                p2pie[p2pielen++] = 0x6F;
5484                p2pie[p2pielen++] = 0x9A;
5485                p2pie[p2pielen++] = 0x09;       /*      WFA P2P v1.0 */
5486
5487                /*      Commented by Albert 20101109 */
5488                /*      According to the P2P Specification, the association request frame should contain 3 P2P attributes */
5489                /*      1. P2P Capability */
5490                /*      2. Extended Listen Timing */
5491                /*      3. Device Info */
5492                /*      Commented by Albert 20110516 */
5493                /*      4. P2P Interface */
5494
5495                /*      P2P Capability */
5496                /*      Type: */
5497                p2pie[p2pielen++] = P2P_ATTR_CAPABILITY;
5498
5499                /*      Length: */
5500                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0002);
5501                p2pielen += 2;
5502
5503                /*      Value: */
5504                /*      Device Capability Bitmap, 1 byte */
5505                p2pie[p2pielen++] = DMP_P2P_DEVCAP_SUPPORT;
5506
5507                /*      Group Capability Bitmap, 1 byte */
5508                if (pwdinfo->persistent_supported)
5509                        p2pie[p2pielen++] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
5510                else
5511                        p2pie[p2pielen++] = DMP_P2P_GRPCAP_SUPPORT;
5512
5513                /*      Extended Listen Timing */
5514                /*      Type: */
5515                p2pie[p2pielen++] = P2P_ATTR_EX_LISTEN_TIMING;
5516
5517                /*      Length: */
5518                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x0004);
5519                p2pielen += 2;
5520
5521                /*      Value: */
5522                /*      Availability Period */
5523                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
5524                p2pielen += 2;
5525
5526                /*      Availability Interval */
5527                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0xFFFF);
5528                p2pielen += 2;
5529
5530                /*      Device Info */
5531                /*      Type: */
5532                p2pie[p2pielen++] = P2P_ATTR_DEVICE_INFO;
5533
5534                /*      Length: */
5535                /*      21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) */
5536                /*      + NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes) */
5537                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(21 + pwdinfo->device_name_len);
5538                p2pielen += 2;
5539
5540                /*      Value: */
5541                /*      P2P Device Address */
5542                memcpy(p2pie + p2pielen, myid(&padapter->eeprompriv), ETH_ALEN);
5543                p2pielen += ETH_ALEN;
5544
5545                /*      Config Method */
5546                /*      This field should be big endian. Noted by P2P specification. */
5547                if ((pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN) ||
5548                    (pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN))
5549                        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_DISPLAY);
5550                else
5551                        *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_CONFIG_METHOD_PBC);
5552
5553                p2pielen += 2;
5554
5555                /*      Primary Device Type */
5556                /*      Category ID */
5557                *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_CID_MULIT_MEDIA);
5558                p2pielen += 2;
5559
5560                /*      OUI */
5561                *(__be32 *)(p2pie + p2pielen) = cpu_to_be32(WPSOUI);
5562                p2pielen += 4;
5563
5564                /*      Sub Category ID */
5565                *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_PDT_SCID_MEDIA_SERVER);
5566                p2pielen += 2;
5567
5568                /*      Number of Secondary Device Types */
5569                p2pie[p2pielen++] = 0x00;       /*      No Secondary Device Type List */
5570
5571                /*      Device Name */
5572                /*      Type: */
5573                *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(WPS_ATTR_DEVICE_NAME);
5574                p2pielen += 2;
5575
5576                /*      Length: */
5577                *(__be16 *)(p2pie + p2pielen) = cpu_to_be16(pwdinfo->device_name_len);
5578                p2pielen += 2;
5579
5580                /*      Value: */
5581                memcpy(p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len);
5582                p2pielen += pwdinfo->device_name_len;
5583
5584                /*      P2P Interface */
5585                /*      Type: */
5586                p2pie[p2pielen++] = P2P_ATTR_INTERFACE;
5587
5588                /*      Length: */
5589                *(__le16 *)(p2pie + p2pielen) = cpu_to_le16(0x000D);
5590                p2pielen += 2;
5591
5592                /*      Value: */
5593                memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);       /*      P2P Device Address */
5594                p2pielen += ETH_ALEN;
5595
5596                p2pie[p2pielen++] = 1;  /*      P2P Interface Address Count */
5597
5598                memcpy(p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN);       /*      P2P Interface Address List */
5599                p2pielen += ETH_ALEN;
5600
5601                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *)p2pie, &pattrib->pktlen);
5602        }
5603
5604#endif /* CONFIG_88EU_P2P */
5605
5606        pattrib->last_txcmdsz = pattrib->pktlen;
5607        dump_mgntframe(padapter, pmgntframe);
5608
5609        ret = _SUCCESS;
5610
5611exit:
5612        if (ret == _SUCCESS)
5613                rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
5614        else
5615                rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
5616
5617        return;
5618}
5619
5620/* when wait_ack is ture, this function shoule be called at process context */
5621static int _issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
5622{
5623        int ret = _FAIL;
5624        struct xmit_frame                       *pmgntframe;
5625        struct pkt_attrib                       *pattrib;
5626        unsigned char                                   *pframe;
5627        struct rtw_ieee80211_hdr        *pwlanhdr;
5628        unsigned short                          *fctrl;
5629        struct xmit_priv        *pxmitpriv;
5630        struct mlme_ext_priv    *pmlmeext;
5631        struct mlme_ext_info    *pmlmeinfo;
5632
5633        if (!padapter)
5634                goto exit;
5635
5636        pxmitpriv = &(padapter->xmitpriv);
5637        pmlmeext = &(padapter->mlmeextpriv);
5638        pmlmeinfo = &(pmlmeext->mlmext_info);
5639
5640        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5641        if (pmgntframe == NULL)
5642                goto exit;
5643
5644        /* update attribute */
5645        pattrib = &pmgntframe->attrib;
5646        update_mgntframe_attrib(padapter, pattrib);
5647        pattrib->retry_ctrl = false;
5648
5649        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5650
5651        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5652        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5653
5654        fctrl = &(pwlanhdr->frame_ctl);
5655        *(fctrl) = 0;
5656
5657        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
5658                SetFrDs(fctrl);
5659        else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
5660                SetToDs(fctrl);
5661
5662        if (power_mode)
5663                SetPwrMgt(fctrl);
5664
5665        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5666        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5667        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5668
5669        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5670        pmlmeext->mgnt_seq++;
5671        SetFrameSubType(pframe, WIFI_DATA_NULL);
5672
5673        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
5674        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5675
5676        pattrib->last_txcmdsz = pattrib->pktlen;
5677
5678        if (wait_ack) {
5679                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5680        } else {
5681                dump_mgntframe(padapter, pmgntframe);
5682                ret = _SUCCESS;
5683        }
5684
5685exit:
5686        return ret;
5687}
5688
5689
5690/* when wait_ms > 0 , this function shoule be called at process context */
5691/* da == NULL for station mode */
5692int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
5693{
5694        int ret;
5695        int i = 0;
5696        u32 start = rtw_get_current_time();
5697        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5698        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5699
5700        /* da == NULL, assum it's null data for sta to ap*/
5701        if (da == NULL)
5702                da = get_my_bssid(&(pmlmeinfo->network));
5703
5704        do {
5705                ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0 ? true : false);
5706
5707                i++;
5708
5709                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5710                        break;
5711
5712                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5713                        rtw_msleep_os(wait_ms);
5714        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5715
5716        if (ret != _FAIL) {
5717                ret = _SUCCESS;
5718                goto exit;
5719        }
5720
5721        if (try_cnt && wait_ms) {
5722                if (da)
5723                        DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
5724                                FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
5725                                ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5726                else
5727                        DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5728                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
5729                                ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5730        }
5731exit:
5732        return ret;
5733}
5734
5735/* when wait_ack is ture, this function shoule be called at process context */
5736static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
5737{
5738        int ret = _FAIL;
5739        struct xmit_frame                       *pmgntframe;
5740        struct pkt_attrib                       *pattrib;
5741        unsigned char                                   *pframe;
5742        struct rtw_ieee80211_hdr        *pwlanhdr;
5743        unsigned short                          *fctrl, *qc;
5744        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
5745        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5746        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5747
5748        DBG_88E("%s\n", __func__);
5749
5750        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5751        if (pmgntframe == NULL)
5752                goto exit;
5753
5754        /* update attribute */
5755        pattrib = &pmgntframe->attrib;
5756        update_mgntframe_attrib(padapter, pattrib);
5757
5758        pattrib->hdrlen += 2;
5759        pattrib->qos_en = true;
5760        pattrib->eosp = 1;
5761        pattrib->ack_policy = 0;
5762        pattrib->mdata = 0;
5763
5764        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5765
5766        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5767        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5768
5769        fctrl = &(pwlanhdr->frame_ctl);
5770        *(fctrl) = 0;
5771
5772        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
5773                SetFrDs(fctrl);
5774        else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
5775                SetToDs(fctrl);
5776
5777        if (pattrib->mdata)
5778                SetMData(fctrl);
5779
5780        qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
5781
5782        SetPriority(qc, tid);
5783
5784        SetEOSP(qc, pattrib->eosp);
5785
5786        SetAckpolicy(qc, pattrib->ack_policy);
5787
5788        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5789        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5790        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5791
5792        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5793        pmlmeext->mgnt_seq++;
5794        SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
5795
5796        pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
5797        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
5798
5799        pattrib->last_txcmdsz = pattrib->pktlen;
5800
5801        if (wait_ack) {
5802                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5803        } else {
5804                dump_mgntframe(padapter, pmgntframe);
5805                ret = _SUCCESS;
5806        }
5807
5808exit:
5809        return ret;
5810}
5811
5812/* when wait_ms > 0 , this function shoule be called at process context */
5813/* da == NULL for station mode */
5814int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
5815{
5816        int ret;
5817        int i = 0;
5818        u32 start = rtw_get_current_time();
5819        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5820        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5821
5822        /* da == NULL, assum it's null data for sta to ap*/
5823        if (da == NULL)
5824                da = get_my_bssid(&(pmlmeinfo->network));
5825
5826        do {
5827                ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0 ? true : false);
5828
5829                i++;
5830
5831                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5832                        break;
5833
5834                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5835                        rtw_msleep_os(wait_ms);
5836        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5837
5838        if (ret != _FAIL) {
5839                ret = _SUCCESS;
5840                goto exit;
5841        }
5842
5843        if (try_cnt && wait_ms) {
5844                if (da)
5845                        DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
5846                                FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
5847                                ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5848                else
5849                        DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5850                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
5851                                ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5852        }
5853exit:
5854        return ret;
5855}
5856
5857static int _issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack)
5858{
5859        struct xmit_frame                       *pmgntframe;
5860        struct pkt_attrib                       *pattrib;
5861        unsigned char                                   *pframe;
5862        struct rtw_ieee80211_hdr        *pwlanhdr;
5863        unsigned short                          *fctrl;
5864        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
5865        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5866        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5867        int ret = _FAIL;
5868        __le16 le_tmp;
5869#ifdef CONFIG_88EU_P2P
5870        struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
5871#endif /* CONFIG_88EU_P2P */
5872
5873#ifdef CONFIG_88EU_P2P
5874        if (!(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) && (pwdinfo->rx_invitereq_info.scan_op_ch_only)) {
5875                _cancel_timer_ex(&pwdinfo->reset_ch_sitesurvey);
5876                _set_timer(&pwdinfo->reset_ch_sitesurvey, 10);
5877        }
5878#endif /* CONFIG_88EU_P2P */
5879
5880        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5881        if (pmgntframe == NULL)
5882                goto exit;
5883
5884        /* update attribute */
5885        pattrib = &pmgntframe->attrib;
5886        update_mgntframe_attrib(padapter, pattrib);
5887        pattrib->retry_ctrl = false;
5888
5889        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5890
5891        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5892        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5893
5894        fctrl = &(pwlanhdr->frame_ctl);
5895        *(fctrl) = 0;
5896
5897        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
5898        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
5899        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
5900
5901        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
5902        pmlmeext->mgnt_seq++;
5903        SetFrameSubType(pframe, WIFI_DEAUTH);
5904
5905        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
5906        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
5907
5908        le_tmp = cpu_to_le16(reason);
5909        pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_ , (unsigned char *)&le_tmp, &(pattrib->pktlen));
5910
5911        pattrib->last_txcmdsz = pattrib->pktlen;
5912
5913
5914        if (wait_ack) {
5915                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
5916        } else {
5917                dump_mgntframe(padapter, pmgntframe);
5918                ret = _SUCCESS;
5919        }
5920
5921exit:
5922        return ret;
5923}
5924
5925int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
5926{
5927        DBG_88E("%s to %pM\n", __func__, da);
5928        return _issue_deauth(padapter, da, reason, false);
5929}
5930
5931int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
5932        int wait_ms)
5933{
5934        int ret;
5935        int i = 0;
5936        u32 start = rtw_get_current_time();
5937
5938        do {
5939                ret = _issue_deauth(padapter, da, reason, wait_ms > 0 ? true : false);
5940
5941                i++;
5942
5943                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
5944                        break;
5945
5946                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
5947                        rtw_msleep_os(wait_ms);
5948        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
5949
5950        if (ret != _FAIL) {
5951                ret = _SUCCESS;
5952                goto exit;
5953        }
5954
5955        if (try_cnt && wait_ms) {
5956                if (da)
5957                        DBG_88E(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n",
5958                                FUNC_ADPT_ARG(padapter), da, rtw_get_oper_ch(padapter),
5959                                ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5960                else
5961                        DBG_88E(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
5962                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
5963                                ret == _SUCCESS ? ", acked" : "", i, try_cnt, rtw_get_passing_time_ms(start));
5964        }
5965exit:
5966        return ret;
5967}
5968
5969void issue_action_spct_ch_switch (struct adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)
5970{
5971        struct xmit_frame                       *pmgntframe;
5972        struct pkt_attrib                       *pattrib;
5973        unsigned char                           *pframe;
5974        struct rtw_ieee80211_hdr        *pwlanhdr;
5975        unsigned short                  *fctrl;
5976        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
5977        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
5978
5979
5980        DBG_88E(FUNC_NDEV_FMT" ra =%pM, ch:%u, offset:%u\n",
5981                FUNC_NDEV_ARG(padapter->pnetdev), ra, new_ch, ch_offset);
5982
5983        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
5984        if (pmgntframe == NULL)
5985                return;
5986
5987        /* update attribute */
5988        pattrib = &pmgntframe->attrib;
5989        update_mgntframe_attrib(padapter, pattrib);
5990
5991        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
5992
5993        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
5994        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
5995
5996        fctrl = &(pwlanhdr->frame_ctl);
5997        *(fctrl) = 0;
5998
5999        memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */
6000        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); /* TA */
6001        memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */
6002
6003        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6004        pmlmeext->mgnt_seq++;
6005        SetFrameSubType(pframe, WIFI_ACTION);
6006
6007        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
6008        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6009
6010        /* category, action */
6011        {
6012                u8 category, action;
6013                category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;
6014                action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;
6015
6016                pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
6017                pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
6018        }
6019
6020        pframe = rtw_set_ie_ch_switch (pframe, &(pattrib->pktlen), 0, new_ch, 0);
6021        pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen),
6022                hal_ch_offset_to_secondary_ch_offset(ch_offset));
6023
6024        pattrib->last_txcmdsz = pattrib->pktlen;
6025
6026        dump_mgntframe(padapter, pmgntframe);
6027}
6028
6029void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
6030{
6031        u8 category = RTW_WLAN_CATEGORY_BACK;
6032        u16 start_seq;
6033        u16 BA_para_set;
6034        u16 reason_code;
6035        u16 BA_timeout_value;
6036        __le16  le_tmp;
6037        u16 BA_starting_seqctrl = 0;
6038        enum ht_cap_ampdu_factor max_rx_ampdu_factor;
6039        struct xmit_frame *pmgntframe;
6040        struct pkt_attrib *pattrib;
6041        u8 *pframe;
6042        struct rtw_ieee80211_hdr *pwlanhdr;
6043        u16 *fctrl;
6044        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
6045        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
6046        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6047        struct sta_info *psta;
6048        struct sta_priv *pstapriv = &padapter->stapriv;
6049        struct registry_priv *pregpriv = &padapter->registrypriv;
6050
6051        DBG_88E("%s, category=%d, action=%d, status=%d\n", __func__, category, action, status);
6052
6053        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
6054        if (pmgntframe == NULL)
6055                return;
6056
6057        /* update attribute */
6058        pattrib = &pmgntframe->attrib;
6059        update_mgntframe_attrib(padapter, pattrib);
6060
6061        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6062
6063        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6064        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
6065
6066        fctrl = &(pwlanhdr->frame_ctl);
6067        *(fctrl) = 0;
6068
6069        /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
6070        memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
6071        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
6072        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
6073
6074        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6075        pmlmeext->mgnt_seq++;
6076        SetFrameSubType(pframe, WIFI_ACTION);
6077
6078        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
6079        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6080
6081        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
6082        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
6083
6084        if (category == 3) {
6085                switch (action) {
6086                case 0: /* ADDBA req */
6087                        do {
6088                                pmlmeinfo->dialogToken++;
6089                        } while (pmlmeinfo->dialogToken == 0);
6090                        pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
6091
6092                        BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
6093                        le_tmp = cpu_to_le16(BA_para_set);
6094                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6095
6096                        BA_timeout_value = 5000;/*  5ms */
6097                        le_tmp = cpu_to_le16(BA_timeout_value);
6098                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6099
6100                        psta = rtw_get_stainfo(pstapriv, raddr);
6101                        if (psta != NULL) {
6102                                start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
6103
6104                                DBG_88E("BA_starting_seqctrl=%d for TID=%d\n", start_seq, status & 0x07);
6105
6106                                psta->BA_starting_seqctrl[status & 0x07] = start_seq;
6107
6108                                BA_starting_seqctrl = start_seq << 4;
6109                        }
6110                        le_tmp = cpu_to_le16(BA_starting_seqctrl);
6111                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6112                        break;
6113                case 1: /* ADDBA rsp */
6114                        pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
6115                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
6116                        rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
6117                        if (MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)
6118                                BA_para_set = (((pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
6119                        else if (MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)
6120                                BA_para_set = (((pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
6121                        else if (MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)
6122                                BA_para_set = (((pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
6123                        else if (MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)
6124                                BA_para_set = (((pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
6125                        else
6126                                BA_para_set = (((pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
6127
6128                        if (pregpriv->ampdu_amsdu == 0)/* disabled */
6129                                BA_para_set = BA_para_set & ~BIT(0);
6130                        else if (pregpriv->ampdu_amsdu == 1)/* enabled */
6131                                BA_para_set = BA_para_set | BIT(0);
6132                        le_tmp = cpu_to_le16(BA_para_set);
6133
6134                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6135                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
6136                        break;
6137                case 2:/* DELBA */
6138                        BA_para_set = (status & 0x1F) << 3;
6139                        le_tmp = cpu_to_le16(BA_para_set);
6140                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6141
6142                        reason_code = 37;/* Requested from peer STA as it does not want to use the mechanism */
6143                        le_tmp = cpu_to_le16(reason_code);
6144                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
6145                        break;
6146                default:
6147                        break;
6148                }
6149        }
6150
6151        pattrib->last_txcmdsz = pattrib->pktlen;
6152
6153        dump_mgntframe(padapter, pmgntframe);
6154}
6155
6156static void issue_action_BSSCoexistPacket(struct adapter *padapter)
6157{
6158        unsigned long   irqL;
6159        struct list_head *plist, *phead;
6160        unsigned char category, action;
6161        struct xmit_frame                       *pmgntframe;
6162        struct pkt_attrib                       *pattrib;
6163        unsigned char                           *pframe;
6164        struct rtw_ieee80211_hdr        *pwlanhdr;
6165        unsigned short                  *fctrl;
6166        struct  wlan_network    *pnetwork = NULL;
6167        struct xmit_priv                        *pxmitpriv = &(padapter->xmitpriv);
6168        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6169        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
6170        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6171        struct __queue *queue   = &(pmlmepriv->scanned_queue);
6172        u8 InfoContent[16] = {0};
6173        u8 ICS[8][15];
6174        if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
6175                return;
6176
6177        if (pmlmeinfo->bwmode_updated)
6178                return;
6179
6180
6181        DBG_88E("%s\n", __func__);
6182
6183
6184        category = RTW_WLAN_CATEGORY_PUBLIC;
6185        action = ACT_PUBLIC_BSSCOEXIST;
6186
6187        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
6188        if (pmgntframe == NULL)
6189                return;
6190
6191        /* update attribute */
6192        pattrib = &pmgntframe->attrib;
6193        update_mgntframe_attrib(padapter, pattrib);
6194
6195        _rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
6196
6197        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
6198        pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
6199
6200        fctrl = &(pwlanhdr->frame_ctl);
6201        *(fctrl) = 0;
6202
6203        memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
6204        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
6205        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
6206
6207        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
6208        pmlmeext->mgnt_seq++;
6209        SetFrameSubType(pframe, WIFI_ACTION);
6210
6211        pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
6212        pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
6213
6214        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
6215        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
6216
6217
6218        /*  */
6219        if (pmlmepriv->num_FortyMHzIntolerant > 0) {
6220                u8 iedata = 0;
6221
6222                iedata |= BIT(2);/* 20 MHz BSS Width Request */
6223
6224                pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));
6225        }
6226
6227
6228        /*  */
6229        _rtw_memset(ICS, 0, sizeof(ICS));
6230        if (pmlmepriv->num_sta_no_ht > 0) {
6231                int i;
6232
6233                _enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6234
6235                phead = get_list_head(queue);
6236                plist = get_next(phead);
6237
6238                while (1) {
6239                        int len;
6240                        u8 *p;
6241                        struct wlan_bssid_ex *pbss_network;
6242
6243                        if (rtw_end_of_queue_search(phead, plist))
6244                                break;
6245
6246                        pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
6247
6248                        plist = get_next(plist);
6249
6250                        pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
6251
6252                        p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
6253                        if ((p == NULL) || (len == 0)) { /* non-HT */
6254                                if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
6255                                        continue;
6256
6257                                ICS[0][pbss_network->Configuration.DSConfig] = 1;
6258
6259                                if (ICS[0][0] == 0)
6260                                        ICS[0][0] = 1;
6261                        }
6262                }
6263                _exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
6264
6265                for (i = 0; i < 8; i++) {
6266                        if (ICS[i][0] == 1) {
6267                                int j, k = 0;
6268
6269                                InfoContent[k] = i;
6270                                /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
6271                                k++;
6272
6273                                for (j = 1; j <= 14; j++) {
6274                                        if (ICS[i][j] == 1) {
6275                                                if (k < 16) {
6276                                                        InfoContent[k] = j; /* channel number */
6277                                                        /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
6278                                                        k++;
6279                                                }
6280                                        }
6281                                }
6282
6283                                pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
6284                        }
6285                }
6286        }
6287
6288
6289        pattrib->last_txcmdsz = pattrib->pktlen;
6290
6291        dump_mgntframe(padapter, pmgntframe);
6292}
6293
6294unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
6295{
6296        struct sta_priv *pstapriv = &padapter->stapriv;
6297        struct sta_info *psta = NULL;
6298        /* struct recv_reorder_ctrl *preorder_ctrl; */
6299        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6300        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6301        u16 tid;
6302
6303        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
6304                if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
6305                        return _SUCCESS;
6306
6307        psta = rtw_get_stainfo(pstapriv, addr);
6308        if (psta == NULL)
6309                return _SUCCESS;
6310
6311        if (initiator == 0) { /*  recipient */
6312                for (tid = 0; tid < MAXTID; tid++) {
6313                        if (psta->recvreorder_ctrl[tid].enable) {
6314                                DBG_88E("rx agg disable tid(%d)\n", tid);
6315                                issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
6316                                psta->recvreorder_ctrl[tid].enable = false;
6317                                psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
6318                        }
6319                }
6320        } else if (initiator == 1) { /*  originator */
6321                for (tid = 0; tid < MAXTID; tid++) {
6322                        if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
6323                                DBG_88E("tx agg disable tid(%d)\n", tid);
6324                                issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
6325                                psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
6326                                psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
6327                        }
6328                }
6329        }
6330
6331        return _SUCCESS;
6332}
6333
6334unsigned int send_beacon(struct adapter *padapter)
6335{
6336        u8 bxmitok = false;
6337        int     issue = 0;
6338        int poll = 0;
6339
6340        u32 start = rtw_get_current_time();
6341
6342        rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
6343        do {
6344                issue_beacon(padapter, 100);
6345                issue++;
6346                do {
6347                        rtw_yield_os();
6348                        rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
6349                        poll++;
6350                } while ((poll%10) != 0 && !bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
6351        } while (!bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
6352
6353        if (padapter->bSurpriseRemoved || padapter->bDriverStopped)
6354                return _FAIL;
6355        if (!bxmitok) {
6356                DBG_88E("%s fail! %u ms\n", __func__, rtw_get_passing_time_ms(start));
6357                return _FAIL;
6358        } else {
6359                u32 passing_time = rtw_get_passing_time_ms(start);
6360
6361                if (passing_time > 100 || issue > 3)
6362                        DBG_88E("%s success, issue:%d, poll:%d, %u ms\n", __func__, issue, poll, rtw_get_passing_time_ms(start));
6363                return _SUCCESS;
6364        }
6365}
6366
6367/****************************************************************************
6368
6369Following are some utitity fuctions for WiFi MLME
6370
6371*****************************************************************************/
6372
6373void site_survey(struct adapter *padapter)
6374{
6375        unsigned char           survey_channel = 0, val8;
6376        enum rt_scan_type ScanType = SCAN_PASSIVE;
6377        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6378        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6379        u32 initialgain = 0;
6380
6381#ifdef CONFIG_88EU_P2P
6382        struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
6383
6384        if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
6385                if (pwdinfo->rx_invitereq_info.scan_op_ch_only) {
6386                        survey_channel = pwdinfo->rx_invitereq_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
6387                } else {
6388                        survey_channel = pwdinfo->p2p_info.operation_ch[pmlmeext->sitesurvey_res.channel_idx];
6389                }
6390                ScanType = SCAN_ACTIVE;
6391        } else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
6392                /*      Commented by Albert 2011/06/03 */
6393                /*      The driver is in the find phase, it should go through the social channel. */
6394                int ch_set_idx;
6395                survey_channel = pwdinfo->social_chan[pmlmeext->sitesurvey_res.channel_idx];
6396                ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, survey_channel);
6397                if (ch_set_idx >= 0)
6398                        ScanType = pmlmeext->channel_set[ch_set_idx].ScanType;
6399                else
6400                        ScanType = SCAN_ACTIVE;
6401        } else
6402#endif /* CONFIG_88EU_P2P */
6403        {
6404                struct rtw_ieee80211_channel *ch;
6405                if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
6406                        ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
6407                        survey_channel = ch->hw_value;
6408                        ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
6409                }
6410        }
6411
6412        if (survey_channel != 0) {
6413                /* PAUSE 4-AC Queue when site_survey */
6414                /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
6415                /* val8 |= 0x0f; */
6416                /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
6417                if (pmlmeext->sitesurvey_res.channel_idx == 0)
6418                        set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6419                else
6420                        SelectChannel(padapter, survey_channel);
6421
6422                if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
6423                        #ifdef CONFIG_88EU_P2P
6424                        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) ||
6425                            rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
6426                                issue_probereq_p2p(padapter, NULL);
6427                                issue_probereq_p2p(padapter, NULL);
6428                                issue_probereq_p2p(padapter, NULL);
6429                        } else
6430                        #endif /* CONFIG_88EU_P2P */
6431                        {
6432                                int i;
6433                                for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
6434                                        if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
6435                                                /* todo: to issue two probe req??? */
6436                                                issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
6437                                                /* rtw_msleep_os(SURVEY_TO>>1); */
6438                                                issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
6439                                        }
6440                                }
6441
6442                                if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
6443                                        /* todo: to issue two probe req??? */
6444                                        issue_probereq(padapter, NULL, NULL);
6445                                        /* rtw_msleep_os(SURVEY_TO>>1); */
6446                                        issue_probereq(padapter, NULL, NULL);
6447                                }
6448                        }
6449                }
6450
6451                set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
6452        } else {
6453                /*      channel number is 0 or this channel is not valid. */
6454
6455#ifdef CONFIG_88EU_P2P
6456                if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)) {
6457                        if ((pwdinfo->rx_invitereq_info.scan_op_ch_only) || (pwdinfo->p2p_info.scan_op_ch_only)) {
6458                                /*      Set the find_phase_state_exchange_cnt to P2P_FINDPHASE_EX_CNT. */
6459                                /*      This will let the following flow to run the scanning end. */
6460                                rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
6461                        }
6462                }
6463
6464                if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) {
6465                        /*      Set the P2P State to the listen state of find phase and set the current channel to the listen channel */
6466                        set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6467                        rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
6468                        pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
6469
6470                        initialgain = 0xff; /* restore RX GAIN */
6471                        rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
6472                        /* turn on dynamic functions */
6473                        Restore_DM_Func_Flag(padapter);
6474                        /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DIG|DYNAMIC_FUNC_HP|DYNAMIC_FUNC_SS, true); */
6475
6476                        _set_timer(&pwdinfo->find_phase_timer, (u32)((u32)(pwdinfo->listen_dwell) * 100));
6477                } else
6478#endif /* CONFIG_88EU_P2P */
6479                {
6480                        /*  20100721:Interrupt scan operation here. */
6481                        /*  For SW antenna diversity before link, it needs to switch to another antenna and scan again. */
6482                        /*  It compares the scan result and select beter one to do connection. */
6483                        if (rtw_hal_antdiv_before_linked(padapter)) {
6484                                pmlmeext->sitesurvey_res.bss_cnt = 0;
6485                                pmlmeext->sitesurvey_res.channel_idx = -1;
6486                                pmlmeext->chan_scan_time = SURVEY_TO / 2;
6487                                set_survey_timer(pmlmeext, pmlmeext->chan_scan_time);
6488                                return;
6489                        }
6490#ifdef CONFIG_88EU_P2P
6491                        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
6492                                rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
6493                        rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
6494#endif /* CONFIG_88EU_P2P */
6495
6496                        pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
6497
6498                        /* switch back to the original channel */
6499
6500#ifdef CONFIG_88EU_P2P
6501                        if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN))
6502                                set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6503                        else
6504                                set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6505#endif /* CONFIG_88EU_P2P */
6506
6507                        /* flush 4-AC Queue after site_survey */
6508                        /* val8 = 0; */
6509                        /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
6510
6511                        /* config MSR */
6512                        Set_MSR(padapter, (pmlmeinfo->state & 0x3));
6513
6514                        initialgain = 0xff; /* restore RX GAIN */
6515                        rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
6516                        /* turn on dynamic functions */
6517                        Restore_DM_Func_Flag(padapter);
6518                        /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
6519
6520                        if (is_client_associated_to_ap(padapter))
6521                                issue_nulldata(padapter, NULL, 0, 3, 500);
6522
6523                        val8 = 0; /* survey done */
6524                        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
6525
6526                        report_surveydone_event(padapter);
6527
6528                        pmlmeext->chan_scan_time = SURVEY_TO;
6529                        pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
6530
6531                        issue_action_BSSCoexistPacket(padapter);
6532                        issue_action_BSSCoexistPacket(padapter);
6533                        issue_action_BSSCoexistPacket(padapter);
6534                }
6535        }
6536        return;
6537}
6538
6539/* collect bss info from Beacon and Probe request/response frames. */
6540u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
6541{
6542        int     i;
6543        u32     len;
6544        u8 *p;
6545        u16 val16, subtype;
6546        u8 *pframe = precv_frame->u.hdr.rx_data;
6547        u32     packet_len = precv_frame->u.hdr.len;
6548        u8 ie_offset;
6549        struct registry_priv    *pregistrypriv = &padapter->registrypriv;
6550        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6551        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6552        __le32 le32_tmp;
6553
6554        len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
6555
6556        if (len > MAX_IE_SZ)
6557                return _FAIL;
6558
6559        _rtw_memset(bssid, 0, sizeof(struct wlan_bssid_ex));
6560
6561        subtype = GetFrameSubType(pframe);
6562
6563        if (subtype == WIFI_BEACON) {
6564                bssid->Reserved[0] = 1;
6565                ie_offset = _BEACON_IE_OFFSET_;
6566        } else {
6567                /*  FIXME : more type */
6568                if (subtype == WIFI_PROBEREQ) {
6569                        ie_offset = _PROBEREQ_IE_OFFSET_;
6570                        bssid->Reserved[0] = 2;
6571                } else if (subtype == WIFI_PROBERSP) {
6572                        ie_offset = _PROBERSP_IE_OFFSET_;
6573                        bssid->Reserved[0] = 3;
6574                } else {
6575                        bssid->Reserved[0] = 0;
6576                        ie_offset = _FIXED_IE_LENGTH_;
6577                }
6578        }
6579
6580        bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
6581
6582        /* below is to copy the information element */
6583        bssid->IELength = len;
6584        memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
6585
6586        /* get the signal strength */
6587        bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.recvpower; /*  in dBM.raw data */
6588        bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
6589        bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
6590        rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA,  &bssid->PhyInfo.Optimum_antenna);
6591
6592        /*  checking SSID */
6593        p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);
6594        if (p == NULL) {
6595                DBG_88E("marc: cannot find SSID for survey event\n");
6596                return _FAIL;
6597        }
6598
6599        if (*(p + 1)) {
6600                if (len > NDIS_802_11_LENGTH_SSID) {
6601                        DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
6602                        return _FAIL;
6603                }
6604                memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
6605                bssid->Ssid.SsidLength = *(p + 1);
6606        } else {
6607                bssid->Ssid.SsidLength = 0;
6608        }
6609
6610        _rtw_memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
6611
6612        /* checking rate info... */
6613        i = 0;
6614        p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
6615        if (p != NULL) {
6616                if (len > NDIS_802_11_LENGTH_RATES_EX) {
6617                        DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
6618                        return _FAIL;
6619                }
6620                memcpy(bssid->SupportedRates, (p + 2), len);
6621                i = len;
6622        }
6623
6624        p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
6625        if (p != NULL) {
6626                if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) {
6627                        DBG_88E("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
6628                        return _FAIL;
6629                }
6630                memcpy(bssid->SupportedRates + i, (p + 2), len);
6631        }
6632
6633        /* todo: */
6634        bssid->NetworkTypeInUse = Ndis802_11OFDM24;
6635
6636        if (bssid->IELength < 12)
6637                return _FAIL;
6638
6639        /*  Checking for DSConfig */
6640        p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
6641
6642        bssid->Configuration.DSConfig = 0;
6643        bssid->Configuration.Length = 0;
6644
6645        if (p) {
6646                bssid->Configuration.DSConfig = *(p + 2);
6647        } else {/*  In 5G, some ap do not have DSSET IE */
6648                /*  checking HT info for channel */
6649                p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
6650                if (p) {
6651                        struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
6652                        bssid->Configuration.DSConfig = HT_info->primary_channel;
6653                } else { /*  use current channel */
6654                        bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
6655                }
6656        }
6657
6658        if (subtype == WIFI_PROBEREQ) {
6659                /*  FIXME */
6660                bssid->InfrastructureMode = Ndis802_11Infrastructure;
6661                memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
6662                bssid->Privacy = 1;
6663                return _SUCCESS;
6664        }
6665
6666        memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
6667        bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp);
6668
6669        val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
6670
6671        if (val16 & BIT(0)) {
6672                bssid->InfrastructureMode = Ndis802_11Infrastructure;
6673                memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
6674        } else {
6675                bssid->InfrastructureMode = Ndis802_11IBSS;
6676                memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
6677        }
6678
6679        if (val16 & BIT(4))
6680                bssid->Privacy = 1;
6681        else
6682                bssid->Privacy = 0;
6683
6684        bssid->Configuration.ATIMWindow = 0;
6685
6686        /* 20/40 BSS Coexistence check */
6687        if ((pregistrypriv->wifi_spec == 1) && (!pmlmeinfo->bwmode_updated)) {
6688                struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
6689                p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
6690                if (p && len > 0) {
6691                        struct HT_caps_element  *pHT_caps;
6692                        pHT_caps = (struct HT_caps_element *)(p + 2);
6693
6694                        if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info)&BIT(14))
6695                                pmlmepriv->num_FortyMHzIntolerant++;
6696                } else {
6697                        pmlmepriv->num_sta_no_ht++;
6698                }
6699        }
6700
6701        /*  mark bss info receving from nearby channel as SignalQuality 101 */
6702        if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
6703                bssid->PhyInfo.SignalQuality = 101;
6704        return _SUCCESS;
6705}
6706
6707void start_create_ibss(struct adapter *padapter)
6708{
6709        unsigned short  caps;
6710        u8 val8;
6711        u8 join_type;
6712        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6713        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6714        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
6715        pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
6716        pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
6717
6718        /* update wireless mode */
6719        update_wireless_mode(padapter);
6720
6721        /* udpate capability */
6722        caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
6723        update_capinfo(padapter, caps);
6724        if (caps&cap_IBSS) {/* adhoc master */
6725                val8 = 0xcf;
6726                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
6727
6728                /* switch channel */
6729                /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
6730                set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, HT_CHANNEL_WIDTH_20);
6731
6732                beacon_timing_control(padapter);
6733
6734                /* set msr to WIFI_FW_ADHOC_STATE */
6735                pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
6736                Set_MSR(padapter, (pmlmeinfo->state & 0x3));
6737
6738                /* issue beacon */
6739                if (send_beacon(padapter) == _FAIL) {
6740                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
6741
6742                        report_join_res(padapter, -1);
6743                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
6744                } else {
6745                        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
6746                        join_type = 0;
6747                        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
6748
6749                        report_join_res(padapter, 1);
6750                        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
6751                }
6752        } else {
6753                DBG_88E("start_create_ibss, invalid cap:%x\n", caps);
6754                return;
6755        }
6756}
6757
6758void start_clnt_join(struct adapter *padapter)
6759{
6760        unsigned short  caps;
6761        u8 val8;
6762        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6763        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6764        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
6765        int beacon_timeout;
6766
6767        pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
6768        pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
6769
6770        /* update wireless mode */
6771        update_wireless_mode(padapter);
6772
6773        /* udpate capability */
6774        caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
6775        update_capinfo(padapter, caps);
6776        if (caps&cap_ESS) {
6777                Set_MSR(padapter, WIFI_FW_STATION_STATE);
6778
6779                val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
6780
6781                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
6782
6783                /* switch channel */
6784                set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6785
6786                /* here wait for receiving the beacon to start auth */
6787                /* and enable a timer */
6788                beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
6789                set_link_timer(pmlmeext, beacon_timeout);
6790                _set_timer(&padapter->mlmepriv.assoc_timer,
6791                           (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout);
6792
6793                pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
6794        } else if (caps&cap_IBSS) { /* adhoc client */
6795                Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
6796
6797                val8 = 0xcf;
6798                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
6799
6800                /* switch channel */
6801                set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
6802
6803                beacon_timing_control(padapter);
6804
6805                pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
6806
6807                report_join_res(padapter, 1);
6808        } else {
6809                return;
6810        }
6811}
6812
6813void start_clnt_auth(struct adapter *padapter)
6814{
6815        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6816        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6817
6818        _cancel_timer_ex(&pmlmeext->link_timer);
6819
6820        pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
6821        pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
6822
6823        pmlmeinfo->auth_seq = 1;
6824        pmlmeinfo->reauth_count = 0;
6825        pmlmeinfo->reassoc_count = 0;
6826        pmlmeinfo->link_count = 0;
6827        pmlmeext->retry = 0;
6828
6829
6830        /*  Because of AP's not receiving deauth before */
6831        /*  AP may: 1)not response auth or 2)deauth us after link is complete */
6832        /*  issue deauth before issuing auth to deal with the situation */
6833        /*      Commented by Albert 2012/07/21 */
6834        /*      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
6835        issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
6836
6837        DBG_88E_LEVEL(_drv_info_, "start auth\n");
6838        issue_auth(padapter, NULL, 0);
6839
6840        set_link_timer(pmlmeext, REAUTH_TO);
6841}
6842
6843
6844void start_clnt_assoc(struct adapter *padapter)
6845{
6846        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6847        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6848
6849        _cancel_timer_ex(&pmlmeext->link_timer);
6850
6851        pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
6852        pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
6853
6854        issue_assocreq(padapter);
6855
6856        set_link_timer(pmlmeext, REASSOC_TO);
6857}
6858
6859unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
6860{
6861        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
6862        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
6863
6864        /* check A3 */
6865        if (!(_rtw_memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
6866                return _SUCCESS;
6867
6868        DBG_88E("%s\n", __func__);
6869
6870        if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
6871                if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
6872                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
6873                        report_del_sta_event(padapter, MacAddr, reason);
6874                } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
6875                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
6876                        report_join_res(padapter, -2);
6877                }
6878        }
6879        return _SUCCESS;
6880}
6881
6882static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
6883{
6884        struct registry_priv *pregistrypriv;
6885        struct mlme_ext_priv *pmlmeext;
6886        struct rt_channel_info *chplan_new;
6887        u8 channel;
6888        u8 i;
6889
6890        pregistrypriv = &padapter->registrypriv;
6891        pmlmeext = &padapter->mlmeextpriv;
6892
6893        /*  Adjust channel plan by AP Country IE */
6894        if (pregistrypriv->enable80211d &&
6895            (!pmlmeext->update_channel_plan_by_ap_done)) {
6896                u8 *ie, *p;
6897                u32 len;
6898                struct rt_channel_plan chplan_ap;
6899                struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM];
6900                u8 country[4];
6901                u8 fcn; /*  first channel number */
6902                u8 noc; /*  number of channel */
6903                u8 j, k;
6904
6905                ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
6906                if (!ie)
6907                        return;
6908                if (len < 6)
6909                        return;
6910                ie += 2;
6911                p = ie;
6912                ie += len;
6913
6914                _rtw_memset(country, 0, 4);
6915                memcpy(country, p, 3);
6916                p += 3;
6917                RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
6918                         ("%s: 802.11d country =%s\n", __func__, country));
6919
6920                i = 0;
6921                while ((ie - p) >= 3) {
6922                        fcn = *(p++);
6923                        noc = *(p++);
6924                        p++;
6925
6926                        for (j = 0; j < noc; j++) {
6927                                if (fcn <= 14)
6928                                        channel = fcn + j; /*  2.4 GHz */
6929                                else
6930                                        channel = fcn + j*4; /*  5 GHz */
6931
6932                                chplan_ap.Channel[i++] = channel;
6933                        }
6934                }
6935                chplan_ap.Len = i;
6936
6937                memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
6938
6939                _rtw_memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
6940                chplan_new = pmlmeext->channel_set;
6941
6942                i = 0;
6943                j = 0;
6944                k = 0;
6945                if (pregistrypriv->wireless_mode & WIRELESS_11G) {
6946                        do {
6947                                if ((i == MAX_CHANNEL_NUM) ||
6948                                    (chplan_sta[i].ChannelNum == 0) ||
6949                                    (chplan_sta[i].ChannelNum > 14))
6950                                        break;
6951
6952                                if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
6953                                        break;
6954
6955                                if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
6956                                        chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6957                                        chplan_new[k].ScanType = SCAN_ACTIVE;
6958                                        i++;
6959                                        j++;
6960                                        k++;
6961                                } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
6962                                        chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6963                                        chplan_new[k].ScanType = SCAN_PASSIVE;
6964                                        i++;
6965                                        k++;
6966                                } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
6967                                        chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6968                                        chplan_new[k].ScanType = SCAN_ACTIVE;
6969                                        j++;
6970                                        k++;
6971                                }
6972                        } while (1);
6973
6974                        /*  change AP not support channel to Passive scan */
6975                        while ((i < MAX_CHANNEL_NUM) &&
6976                               (chplan_sta[i].ChannelNum != 0) &&
6977                               (chplan_sta[i].ChannelNum <= 14)) {
6978                                chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6979                                chplan_new[k].ScanType = SCAN_PASSIVE;
6980                                i++;
6981                                k++;
6982                        }
6983
6984                        /*  add channel AP supported */
6985                        while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
6986                                chplan_new[k].ChannelNum = chplan_ap.Channel[j];
6987                                chplan_new[k].ScanType = SCAN_ACTIVE;
6988                                j++;
6989                                k++;
6990                        }
6991                } else {
6992                        /*  keep original STA 2.4G channel plan */
6993                        while ((i < MAX_CHANNEL_NUM) &&
6994                               (chplan_sta[i].ChannelNum != 0) &&
6995                               (chplan_sta[i].ChannelNum <= 14)) {
6996                                chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
6997                                chplan_new[k].ScanType = chplan_sta[i].ScanType;
6998                                i++;
6999                                k++;
7000                        }
7001
7002                        /*  skip AP 2.4G channel plan */
7003                        while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
7004                                j++;
7005                }
7006
7007                /*  keep original STA 5G channel plan */
7008                while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
7009                        chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
7010                        chplan_new[k].ScanType = chplan_sta[i].ScanType;
7011                        i++;
7012                        k++;
7013                }
7014
7015                pmlmeext->update_channel_plan_by_ap_done = 1;
7016        }
7017
7018        /*  If channel is used by AP, set channel scan type to active */
7019        channel = bssid->Configuration.DSConfig;
7020        chplan_new = pmlmeext->channel_set;
7021        i = 0;
7022        while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
7023                if (chplan_new[i].ChannelNum == channel) {
7024                        if (chplan_new[i].ScanType == SCAN_PASSIVE) {
7025                                chplan_new[i].ScanType = SCAN_ACTIVE;
7026                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
7027                                         ("%s: change channel %d scan type from passive to active\n",
7028                                         __func__, channel));
7029                        }
7030                        break;
7031                }
7032                i++;
7033        }
7034}
7035
7036/****************************************************************************
7037
7038Following are the functions to report events
7039
7040*****************************************************************************/
7041
7042void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame)
7043{
7044        struct cmd_obj *pcmd_obj;
7045        u8 *pevtcmd;
7046        u32 cmdsz;
7047        struct survey_event     *psurvey_evt;
7048        struct C2HEvent_Header *pc2h_evt_hdr;
7049        struct mlme_ext_priv *pmlmeext;
7050        struct cmd_priv *pcmdpriv;
7051        /* u8 *pframe = precv_frame->u.hdr.rx_data; */
7052        /* uint len = precv_frame->u.hdr.len; */
7053
7054        if (!padapter)
7055                return;
7056
7057        pmlmeext = &padapter->mlmeextpriv;
7058        pcmdpriv = &padapter->cmdpriv;
7059
7060
7061        pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7062        if (pcmd_obj == NULL)
7063                return;
7064
7065        cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
7066        pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
7067        if (pevtcmd == NULL) {
7068                kfree(pcmd_obj);
7069                return;
7070        }
7071
7072        _rtw_init_listhead(&pcmd_obj->list);
7073
7074        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
7075        pcmd_obj->cmdsz = cmdsz;
7076        pcmd_obj->parmbuf = pevtcmd;
7077
7078        pcmd_obj->rsp = NULL;
7079        pcmd_obj->rspsz  = 0;
7080
7081        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
7082        pc2h_evt_hdr->len = sizeof(struct survey_event);
7083        pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
7084        pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
7085
7086        psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
7087
7088        if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
7089                kfree(pcmd_obj);
7090                kfree(pevtcmd);
7091                return;
7092        }
7093
7094        process_80211d(padapter, &psurvey_evt->bss);
7095
7096        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
7097
7098        pmlmeext->sitesurvey_res.bss_cnt++;
7099
7100        return;
7101}
7102
7103void report_surveydone_event(struct adapter *padapter)
7104{
7105        struct cmd_obj *pcmd_obj;
7106        u8 *pevtcmd;
7107        u32 cmdsz;
7108        struct surveydone_event *psurveydone_evt;
7109        struct C2HEvent_Header  *pc2h_evt_hdr;
7110        struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
7111        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
7112
7113        pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7114        if (pcmd_obj == NULL)
7115                return;
7116
7117        cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
7118        pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
7119        if (pevtcmd == NULL) {
7120                kfree(pcmd_obj);
7121                return;
7122        }
7123
7124        _rtw_init_listhead(&pcmd_obj->list);
7125
7126        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
7127        pcmd_obj->cmdsz = cmdsz;
7128        pcmd_obj->parmbuf = pevtcmd;
7129
7130        pcmd_obj->rsp = NULL;
7131        pcmd_obj->rspsz  = 0;
7132
7133        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
7134        pc2h_evt_hdr->len = sizeof(struct surveydone_event);
7135        pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
7136        pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
7137
7138        psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
7139        psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
7140
7141        DBG_88E("survey done event(%x)\n", psurveydone_evt->bss_cnt);
7142
7143        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
7144
7145        return;
7146}
7147
7148void report_join_res(struct adapter *padapter, int res)
7149{
7150        struct cmd_obj *pcmd_obj;
7151        u8 *pevtcmd;
7152        u32 cmdsz;
7153        struct joinbss_event            *pjoinbss_evt;
7154        struct C2HEvent_Header  *pc2h_evt_hdr;
7155        struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
7156        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7157        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
7158
7159        pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7160        if (pcmd_obj == NULL)
7161                return;
7162
7163        cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
7164        pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
7165        if (pevtcmd == NULL) {
7166                kfree(pcmd_obj);
7167                return;
7168        }
7169
7170        _rtw_init_listhead(&pcmd_obj->list);
7171
7172        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
7173        pcmd_obj->cmdsz = cmdsz;
7174        pcmd_obj->parmbuf = pevtcmd;
7175
7176        pcmd_obj->rsp = NULL;
7177        pcmd_obj->rspsz  = 0;
7178
7179        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
7180        pc2h_evt_hdr->len = sizeof(struct joinbss_event);
7181        pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
7182        pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
7183
7184        pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
7185        memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
7186        pjoinbss_evt->network.join_res  = res;
7187        pjoinbss_evt->network.aid = res;
7188
7189        DBG_88E("report_join_res(%d)\n", res);
7190
7191
7192        rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
7193
7194
7195        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
7196
7197        return;
7198}
7199
7200void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
7201{
7202        struct cmd_obj *pcmd_obj;
7203        u8 *pevtcmd;
7204        u32 cmdsz;
7205        struct sta_info *psta;
7206        int     mac_id;
7207        struct stadel_event                     *pdel_sta_evt;
7208        struct C2HEvent_Header  *pc2h_evt_hdr;
7209        struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
7210        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
7211
7212        pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7213        if (pcmd_obj == NULL)
7214                return;
7215
7216        cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
7217        pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
7218        if (pevtcmd == NULL) {
7219                kfree(pcmd_obj);
7220                return;
7221        }
7222
7223        _rtw_init_listhead(&pcmd_obj->list);
7224
7225        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
7226        pcmd_obj->cmdsz = cmdsz;
7227        pcmd_obj->parmbuf = pevtcmd;
7228
7229        pcmd_obj->rsp = NULL;
7230        pcmd_obj->rspsz  = 0;
7231
7232        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
7233        pc2h_evt_hdr->len = sizeof(struct stadel_event);
7234        pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
7235        pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
7236
7237        pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
7238        memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
7239        memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
7240
7241
7242        psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
7243        if (psta)
7244                mac_id = (int)psta->mac_id;
7245        else
7246                mac_id = (-1);
7247
7248        pdel_sta_evt->mac_id = mac_id;
7249
7250        DBG_88E("report_del_sta_event: delete STA, mac_id =%d\n", mac_id);
7251
7252        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
7253
7254        return;
7255}
7256
7257void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
7258{
7259        struct cmd_obj *pcmd_obj;
7260        u8 *pevtcmd;
7261        u32 cmdsz;
7262        struct stassoc_event            *padd_sta_evt;
7263        struct C2HEvent_Header  *pc2h_evt_hdr;
7264        struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
7265        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
7266
7267        pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7268        if (pcmd_obj == NULL)
7269                return;
7270
7271        cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
7272        pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
7273        if (pevtcmd == NULL) {
7274                kfree(pcmd_obj);
7275                return;
7276        }
7277
7278        _rtw_init_listhead(&pcmd_obj->list);
7279
7280        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
7281        pcmd_obj->cmdsz = cmdsz;
7282        pcmd_obj->parmbuf = pevtcmd;
7283
7284        pcmd_obj->rsp = NULL;
7285        pcmd_obj->rspsz  = 0;
7286
7287        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
7288        pc2h_evt_hdr->len = sizeof(struct stassoc_event);
7289        pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
7290        pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
7291
7292        padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
7293        memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
7294        padd_sta_evt->cam_id = cam_idx;
7295
7296        DBG_88E("report_add_sta_event: add STA\n");
7297
7298        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
7299
7300        return;
7301}
7302
7303
7304/****************************************************************************
7305
7306Following are the event callback functions
7307
7308*****************************************************************************/
7309
7310/* for sta/adhoc mode */
7311void update_sta_info(struct adapter *padapter, struct sta_info *psta)
7312{
7313        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
7314        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7315        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7316
7317        /* ERP */
7318        VCS_update(padapter, psta);
7319
7320        /* HT */
7321        if (pmlmepriv->htpriv.ht_option) {
7322                psta->htpriv.ht_option = true;
7323
7324                psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
7325
7326                if (support_short_GI(padapter, &(pmlmeinfo->HT_caps)))
7327                        psta->htpriv.sgi = true;
7328
7329                psta->qos_option = true;
7330        } else {
7331                psta->htpriv.ht_option = false;
7332
7333                psta->htpriv.ampdu_enable = false;
7334
7335                psta->htpriv.sgi = false;
7336                psta->qos_option = false;
7337        }
7338        psta->htpriv.bwmode = pmlmeext->cur_bwmode;
7339        psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
7340
7341        psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
7342        psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
7343
7344        /* QoS */
7345        if (pmlmepriv->qospriv.qos_option)
7346                psta->qos_option = true;
7347
7348
7349        psta->state = _FW_LINKED;
7350}
7351
7352void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
7353{
7354        struct sta_info         *psta, *psta_bmc;
7355        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7356        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7357        struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network);
7358        struct sta_priv         *pstapriv = &padapter->stapriv;
7359        u8 join_type;
7360        u16 media_status;
7361
7362        if (join_res < 0) {
7363                join_type = 1;
7364                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
7365                rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
7366
7367                /* restore to initial setting. */
7368                update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
7369
7370                goto exit_mlmeext_joinbss_event_callback;
7371        }
7372
7373        if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
7374                /* for bc/mc */
7375                psta_bmc = rtw_get_bcmc_stainfo(padapter);
7376                if (psta_bmc) {
7377                        pmlmeinfo->FW_sta_info[psta_bmc->mac_id].psta = psta_bmc;
7378                        update_bmc_sta_support_rate(padapter, psta_bmc->mac_id);
7379                        Update_RA_Entry(padapter, psta_bmc->mac_id);
7380                }
7381        }
7382
7383
7384        /* turn on dynamic functions */
7385        Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
7386
7387        /*  update IOT-releated issue */
7388        update_IOT_info(padapter);
7389
7390        rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
7391
7392        /* BCN interval */
7393        rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
7394
7395        /* udpate capability */
7396        update_capinfo(padapter, pmlmeinfo->capability);
7397
7398        /* WMM, Update EDCA param */
7399        WMMOnAssocRsp(padapter);
7400
7401        /* HT */
7402        HTOnAssocRsp(padapter);
7403
7404        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
7405
7406        psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
7407        if (psta) { /* only for infra. mode */
7408                pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
7409
7410                psta->wireless_mode = pmlmeext->cur_wireless_mode;
7411
7412                /* set per sta rate after updating HT cap. */
7413                set_sta_rate(padapter, psta);
7414                rtw_hal_set_hwreg(padapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&psta->mac_id);
7415                media_status = (psta->mac_id<<8)|1; /*   MACID|OPMODE: 1 means connect */
7416                rtw_hal_set_hwreg(padapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
7417        }
7418
7419        join_type = 2;
7420        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
7421
7422        if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
7423                /*  correcting TSF */
7424                correct_TSF(padapter, pmlmeext);
7425        }
7426        rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
7427
7428exit_mlmeext_joinbss_event_callback:
7429
7430        DBG_88E("=>%s\n", __func__);
7431}
7432
7433void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
7434{
7435        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
7436        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7437        u8 join_type;
7438
7439        DBG_88E("%s\n", __func__);
7440
7441        if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
7442                if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {/* adhoc master or sta_count>1 */
7443                        /* nothing to do */
7444                } else { /* adhoc client */
7445                        /*  correcting TSF */
7446                        correct_TSF(padapter, pmlmeext);
7447
7448                        /* start beacon */
7449                        if (send_beacon(padapter) == _FAIL) {
7450                                pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
7451                                pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
7452                                return;
7453                        }
7454                        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
7455                }
7456
7457                join_type = 2;
7458                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
7459        }
7460
7461        pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
7462
7463        /* rate radaptive */
7464        Update_RA_Entry(padapter, psta->mac_id);
7465
7466        /* update adhoc sta_info */
7467        update_sta_info(padapter, psta);
7468}
7469
7470void mlmeext_sta_del_event_callback(struct adapter *padapter)
7471{
7472        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7473        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7474
7475        if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) {
7476                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
7477                rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
7478
7479                /* restore to initial setting. */
7480                update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
7481
7482                /* switch to the 20M Hz mode after disconnect */
7483                pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7484                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7485
7486                /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
7487                set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
7488
7489
7490                flush_all_cam_entry(padapter);
7491
7492                pmlmeinfo->state = WIFI_FW_NULL_STATE;
7493
7494                /* set MSR to no link state -> infra. mode */
7495                Set_MSR(padapter, _HW_STATE_STATION_);
7496
7497                _cancel_timer_ex(&pmlmeext->link_timer);
7498        }
7499}
7500
7501/****************************************************************************
7502
7503Following are the functions for the timer handlers
7504
7505*****************************************************************************/
7506void _linked_rx_signal_strehgth_display(struct adapter *padapter);
7507void _linked_rx_signal_strehgth_display(struct adapter *padapter)
7508{
7509        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7510      struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7511        u8 mac_id;
7512        int UndecoratedSmoothedPWDB;
7513        if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
7514                mac_id = 0;
7515        else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_)
7516                mac_id = 2;
7517
7518        rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &mac_id);
7519
7520        rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
7521        DBG_88E("UndecoratedSmoothedPWDB:%d\n", UndecoratedSmoothedPWDB);
7522}
7523
7524static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
7525{
7526        u8 ret = false;
7527
7528        if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) &&
7529            sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) &&
7530            sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta))
7531                ret = false;
7532        else
7533                ret = true;
7534
7535        sta_update_last_rx_pkts(psta);
7536
7537        return ret;
7538}
7539
7540void linked_status_chk(struct adapter *padapter)
7541{
7542        u32     i;
7543        struct sta_info         *psta;
7544        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
7545        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7546        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7547        struct sta_priv         *pstapriv = &padapter->stapriv;
7548
7549        if (padapter->bRxRSSIDisplay)
7550                _linked_rx_signal_strehgth_display(padapter);
7551
7552        rtw_hal_sreset_linked_status_check(padapter);
7553
7554        if (is_client_associated_to_ap(padapter)) {
7555                /* linked infrastructure client mode */
7556
7557                int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
7558                int rx_chk_limit;
7559
7560                rx_chk_limit = 4;
7561                psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
7562                if (psta != NULL) {
7563                        bool is_p2p_enable = false;
7564                        #ifdef CONFIG_88EU_P2P
7565                        is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
7566                        #endif
7567
7568                        if (!chk_ap_is_alive(padapter, psta))
7569                                rx_chk = _FAIL;
7570
7571                        if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
7572                                tx_chk = _FAIL;
7573
7574                        if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
7575                                u8 backup_oper_channel = 0;
7576
7577                                /* switch to correct channel of current network  before issue keep-alive frames */
7578                                if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
7579                                        backup_oper_channel = rtw_get_oper_ch(padapter);
7580                                        SelectChannel(padapter, pmlmeext->cur_channel);
7581                                }
7582
7583                                if (rx_chk != _SUCCESS)
7584                                        issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 3, 1);
7585
7586                                if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) || rx_chk != _SUCCESS) {
7587                                        tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
7588                                        /* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
7589                                        if (tx_chk == _SUCCESS && !is_p2p_enable)
7590                                                rx_chk = _SUCCESS;
7591                                }
7592
7593                                /* back to the original operation channel */
7594                                if (backup_oper_channel > 0)
7595                                        SelectChannel(padapter, backup_oper_channel);
7596                        } else {
7597                                if (rx_chk != _SUCCESS) {
7598                                        if (pmlmeext->retry == 0) {
7599                                                issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7600                                                issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7601                                                issue_probereq(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress);
7602                                        }
7603                                }
7604
7605                                if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == 0xf) {
7606                                        tx_chk = issue_nulldata(padapter, NULL, 0, 1, 0);
7607                                }
7608                        }
7609
7610                        if (rx_chk == _FAIL) {
7611                                pmlmeext->retry++;
7612                                if (pmlmeext->retry > rx_chk_limit) {
7613                                        DBG_88E_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
7614                                                      FUNC_ADPT_ARG(padapter));
7615                                        receive_disconnect(padapter, pmlmeinfo->network.MacAddress,
7616                                                           WLAN_REASON_EXPIRATION_CHK);
7617                                        return;
7618                                }
7619                        } else {
7620                                pmlmeext->retry = 0;
7621                        }
7622
7623                        if (tx_chk == _FAIL) {
7624                                pmlmeinfo->link_count &= 0xf;
7625                        } else {
7626                                pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
7627                                pmlmeinfo->link_count = 0;
7628                        }
7629                } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
7630        } else if (is_client_associated_to_ibss(padapter)) {
7631                /* linked IBSS mode */
7632                /* for each assoc list entry to check the rx pkt counter */
7633                for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
7634                        if (pmlmeinfo->FW_sta_info[i].status == 1) {
7635                                psta = pmlmeinfo->FW_sta_info[i].psta;
7636
7637                                if (NULL == psta)
7638                                        continue;
7639                                if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
7640                                        if (pmlmeinfo->FW_sta_info[i].retry < 3) {
7641                                                pmlmeinfo->FW_sta_info[i].retry++;
7642                                        } else {
7643                                                pmlmeinfo->FW_sta_info[i].retry = 0;
7644                                                pmlmeinfo->FW_sta_info[i].status = 0;
7645                                                report_del_sta_event(padapter, psta->hwaddr
7646                                                        , 65535/*  indicate disconnect caused by no rx */
7647                                        );
7648                                        }
7649                                } else {
7650                                        pmlmeinfo->FW_sta_info[i].retry = 0;
7651                                        pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
7652                                }
7653                        }
7654                }
7655        }
7656}
7657
7658void survey_timer_hdl(struct adapter *padapter)
7659{
7660        struct cmd_obj  *ph2c;
7661        struct sitesurvey_parm  *psurveyPara;
7662        struct cmd_priv                                 *pcmdpriv = &padapter->cmdpriv;
7663        struct mlme_ext_priv            *pmlmeext = &padapter->mlmeextpriv;
7664#ifdef CONFIG_88EU_P2P
7665        struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
7666#endif
7667
7668        /* issue rtw_sitesurvey_cmd */
7669        if (pmlmeext->sitesurvey_res.state > SCAN_START) {
7670                if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS)
7671                        pmlmeext->sitesurvey_res.channel_idx++;
7672
7673                if (pmlmeext->scan_abort) {
7674                        #ifdef CONFIG_88EU_P2P
7675                        if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE)) {
7676                                rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
7677                                pmlmeext->sitesurvey_res.channel_idx = 3;
7678                                DBG_88E("%s idx:%d, cnt:%u\n", __func__
7679                                        , pmlmeext->sitesurvey_res.channel_idx
7680                                        , pwdinfo->find_phase_state_exchange_cnt
7681                        );
7682                        } else
7683                        #endif
7684                        {
7685                                pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
7686                                DBG_88E("%s idx:%d\n", __func__
7687                                        , pmlmeext->sitesurvey_res.channel_idx
7688                        );
7689                        }
7690
7691                        pmlmeext->scan_abort = false;/* reset */
7692                }
7693
7694                ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
7695                if (ph2c == NULL)
7696                        goto exit_survey_timer_hdl;
7697
7698                psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
7699                if (psurveyPara == NULL) {
7700                        kfree(ph2c);
7701                        goto exit_survey_timer_hdl;
7702                }
7703
7704                init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
7705                rtw_enqueue_cmd(pcmdpriv, ph2c);
7706        }
7707
7708
7709exit_survey_timer_hdl:
7710        return;
7711}
7712
7713void link_timer_hdl(struct adapter *padapter)
7714{
7715        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7716        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7717
7718        if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
7719                DBG_88E("link_timer_hdl:no beacon while connecting\n");
7720                pmlmeinfo->state = WIFI_FW_NULL_STATE;
7721                report_join_res(padapter, -3);
7722        } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
7723                /* re-auth timer */
7724                if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
7725                        pmlmeinfo->state = 0;
7726                        report_join_res(padapter, -1);
7727                        return;
7728                }
7729
7730                DBG_88E("link_timer_hdl: auth timeout and try again\n");
7731                pmlmeinfo->auth_seq = 1;
7732                issue_auth(padapter, NULL, 0);
7733                set_link_timer(pmlmeext, REAUTH_TO);
7734        } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
7735                /* re-assoc timer */
7736                if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
7737                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
7738                        report_join_res(padapter, -2);
7739                        return;
7740                }
7741
7742                DBG_88E("link_timer_hdl: assoc timeout and try again\n");
7743                issue_assocreq(padapter);
7744                set_link_timer(pmlmeext, REASSOC_TO);
7745        }
7746        return;
7747}
7748
7749void addba_timer_hdl(struct sta_info *psta)
7750{
7751        struct ht_priv  *phtpriv;
7752
7753        if (!psta)
7754                return;
7755
7756        phtpriv = &psta->htpriv;
7757
7758        if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
7759                if (phtpriv->candidate_tid_bitmap)
7760                        phtpriv->candidate_tid_bitmap = 0x0;
7761        }
7762}
7763
7764u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
7765{
7766        return H2C_SUCCESS;
7767}
7768
7769u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
7770{
7771        u8 type;
7772        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7773        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7774        struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
7775
7776        if (psetop->mode == Ndis802_11APMode) {
7777                pmlmeinfo->state = WIFI_FW_AP_STATE;
7778                type = _HW_STATE_AP_;
7779        } else if (psetop->mode == Ndis802_11Infrastructure) {
7780                pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
7781                pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to     STATION_STATE */
7782                type = _HW_STATE_STATION_;
7783        } else if (psetop->mode == Ndis802_11IBSS) {
7784                type = _HW_STATE_ADHOC_;
7785        } else {
7786                type = _HW_STATE_NOLINK_;
7787        }
7788
7789        rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
7790        /* Set_NETYPE0_MSR(padapter, type); */
7791
7792        return H2C_SUCCESS;
7793}
7794
7795u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
7796{
7797        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7798        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7799        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
7800        struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
7801        /* u32  initialgain; */
7802
7803
7804        if (pparm->network.InfrastructureMode == Ndis802_11APMode) {
7805#ifdef CONFIG_88EU_AP_MODE
7806
7807                if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
7808                        /* todo: */
7809                        return H2C_SUCCESS;
7810                }
7811#endif
7812        }
7813
7814        /* below is for ad-hoc master */
7815        if (pparm->network.InfrastructureMode == Ndis802_11IBSS) {
7816                rtw_joinbss_reset(padapter);
7817
7818                pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7819                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7820                pmlmeinfo->ERP_enable = 0;
7821                pmlmeinfo->WMM_enable = 0;
7822                pmlmeinfo->HT_enable = 0;
7823                pmlmeinfo->HT_caps_enable = 0;
7824                pmlmeinfo->HT_info_enable = 0;
7825                pmlmeinfo->agg_enable_bitmap = 0;
7826                pmlmeinfo->candidate_tid_bitmap = 0;
7827
7828                /* disable dynamic functions, such as high power, DIG */
7829                Save_DM_Func_Flag(padapter);
7830                Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
7831
7832                /* config the initial gain under linking, need to write the BB registers */
7833                /* initialgain = 0x1E; */
7834                /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
7835
7836                /* cancel link timer */
7837                _cancel_timer_ex(&pmlmeext->link_timer);
7838
7839                /* clear CAM */
7840                flush_all_cam_entry(padapter);
7841
7842                memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
7843                pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
7844
7845                if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
7846                        return H2C_PARAMETERS_ERROR;
7847
7848                memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
7849
7850                start_create_ibss(padapter);
7851        }
7852
7853        return H2C_SUCCESS;
7854}
7855
7856u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
7857{
7858        u8 join_type;
7859        struct ndis_802_11_var_ie *pIE;
7860        struct registry_priv    *pregpriv = &padapter->registrypriv;
7861        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7862        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7863        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
7864        struct joinbss_parm     *pparm = (struct joinbss_parm *)pbuf;
7865        u32 i;
7866
7867        /* check already connecting to AP or not */
7868        if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
7869                if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
7870                        issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 5, 100);
7871
7872                pmlmeinfo->state = WIFI_FW_NULL_STATE;
7873
7874                /* clear CAM */
7875                flush_all_cam_entry(padapter);
7876
7877                _cancel_timer_ex(&pmlmeext->link_timer);
7878
7879                /* set MSR to nolink -> infra. mode */
7880                Set_MSR(padapter, _HW_STATE_STATION_);
7881
7882
7883                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
7884        }
7885
7886        rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, false);
7887
7888        rtw_joinbss_reset(padapter);
7889
7890        pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
7891        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7892        pmlmeinfo->ERP_enable = 0;
7893        pmlmeinfo->WMM_enable = 0;
7894        pmlmeinfo->HT_enable = 0;
7895        pmlmeinfo->HT_caps_enable = 0;
7896        pmlmeinfo->HT_info_enable = 0;
7897        pmlmeinfo->agg_enable_bitmap = 0;
7898        pmlmeinfo->candidate_tid_bitmap = 0;
7899        pmlmeinfo->bwmode_updated = false;
7900
7901        memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
7902        pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
7903
7904        if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
7905                return H2C_PARAMETERS_ERROR;
7906
7907        memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
7908
7909        /* Check AP vendor to move rtw_joinbss_cmd() */
7910
7911        for (i = sizeof(struct ndis_802_11_fixed_ie); i < pnetwork->IELength;) {
7912                pIE = (struct ndis_802_11_var_ie *)(pnetwork->IEs + i);
7913
7914                switch (pIE->ElementID) {
7915                case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
7916                        if (_rtw_memcmp(pIE->data, WMM_OUI, 4))
7917                                pmlmeinfo->WMM_enable = 1;
7918                        break;
7919                case _HT_CAPABILITY_IE_:        /* Get HT Cap IE. */
7920                        pmlmeinfo->HT_caps_enable = 1;
7921                        break;
7922                case _HT_EXTRA_INFO_IE_:        /* Get HT Info IE. */
7923                        pmlmeinfo->HT_info_enable = 1;
7924
7925                        /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
7926                        {
7927                                struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
7928
7929                                if ((pregpriv->cbw40_enable) &&  (pht_info->infos[0] & BIT(2))) {
7930                                        /* switch to the 40M Hz mode according to the AP */
7931                                        pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
7932                                        switch (pht_info->infos[0] & 0x3) {
7933                                        case 1:
7934                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
7935                                                break;
7936                                        case 3:
7937                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
7938                                                break;
7939                                        default:
7940                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
7941                                                break;
7942                                }
7943
7944                                        DBG_88E("set ch/bw before connected\n");
7945                                }
7946                        }
7947                        break;
7948                default:
7949                        break;
7950                }
7951
7952                i += (pIE->Length + 2);
7953        }
7954        /* disable dynamic functions, such as high power, DIG */
7955
7956        /* config the initial gain under linking, need to write the BB registers */
7957
7958        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
7959        join_type = 0;
7960        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
7961
7962        /* cancel link timer */
7963        _cancel_timer_ex(&pmlmeext->link_timer);
7964
7965        start_clnt_join(padapter);
7966
7967        return H2C_SUCCESS;
7968}
7969
7970u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
7971{
7972        struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
7973        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
7974        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
7975        struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
7976        u8 val8;
7977
7978        if (is_client_associated_to_ap(padapter))
7979                issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
7980
7981        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
7982        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
7983
7984        /* restore to initial setting. */
7985        update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
7986
7987        if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
7988                /* Stop BCN */
7989                val8 = 0;
7990                rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
7991        }
7992
7993
7994        /* set MSR to no link state -> infra. mode */
7995        Set_MSR(padapter, _HW_STATE_STATION_);
7996
7997        pmlmeinfo->state = WIFI_FW_NULL_STATE;
7998
7999        /* switch to the 20M Hz mode after disconnect */
8000        pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_20;
8001        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
8002
8003        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
8004
8005        flush_all_cam_entry(padapter);
8006
8007        _cancel_timer_ex(&pmlmeext->link_timer);
8008
8009        rtw_free_uc_swdec_pending_queue(padapter);
8010
8011        return  H2C_SUCCESS;
8012}
8013
8014static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
8015        u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
8016{
8017        int i, j;
8018        int set_idx;
8019        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8020
8021        /* clear out first */
8022        _rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
8023
8024        /* acquire channels from in */
8025        j = 0;
8026        for (i = 0; i < in_num; i++) {
8027                set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
8028                if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) &&
8029                    set_idx >= 0) {
8030                        memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
8031
8032                        if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
8033                                out[j].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
8034
8035                        j++;
8036                }
8037                if (j >= out_num)
8038                        break;
8039        }
8040
8041        /* if out is empty, use channel_set as default */
8042        if (j == 0) {
8043                for (i = 0; i < pmlmeext->max_chan_nums; i++) {
8044                        out[i].hw_value = pmlmeext->channel_set[i].ChannelNum;
8045
8046                        if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
8047                                out[i].flags &= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
8048
8049                        j++;
8050                }
8051        }
8052
8053        return j;
8054}
8055
8056u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
8057{
8058        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8059        struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
8060        u8 bdelayscan = false;
8061        u8 val8;
8062        u32     initialgain;
8063        u32     i;
8064
8065#ifdef CONFIG_88EU_P2P
8066        struct wifidirect_info *pwdinfo = &padapter->wdinfo;
8067#endif
8068
8069        if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
8070                /* for first time sitesurvey_cmd */
8071                rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, NULL);
8072
8073                pmlmeext->sitesurvey_res.state = SCAN_START;
8074                pmlmeext->sitesurvey_res.bss_cnt = 0;
8075                pmlmeext->sitesurvey_res.channel_idx = 0;
8076
8077                for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
8078                        if (pparm->ssid[i].SsidLength) {
8079                                memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
8080                                pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
8081                        } else {
8082                                pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
8083                        }
8084                }
8085
8086                pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
8087                        , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
8088                        , pparm->ch, pparm->ch_num
8089        );
8090
8091                pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
8092
8093                /* issue null data if associating to the AP */
8094                if (is_client_associated_to_ap(padapter)) {
8095                        pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
8096
8097                        issue_nulldata(padapter, NULL, 1, 3, 500);
8098
8099                        bdelayscan = true;
8100                }
8101                if (bdelayscan) {
8102                        /* delay 50ms to protect nulldata(1). */
8103                        set_survey_timer(pmlmeext, 50);
8104                        return H2C_SUCCESS;
8105                }
8106        }
8107
8108        if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
8109                /* disable dynamic functions, such as high power, DIG */
8110                Save_DM_Func_Flag(padapter);
8111                Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
8112
8113                /* config the initial gain under scaning, need to write the BB registers */
8114#ifdef CONFIG_88EU_P2P
8115                if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
8116                        initialgain = 0x1E;
8117                else
8118                        initialgain = 0x28;
8119#else   /*  CONFIG_88EU_P2P */
8120                initialgain = 0x1E;
8121#endif /*  CONFIG_88EU_P2P */
8122
8123                rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
8124
8125                /* set MSR to no link state */
8126                Set_MSR(padapter, _HW_STATE_NOLINK_);
8127
8128                val8 = 1; /* under site survey */
8129                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
8130
8131                pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
8132        }
8133
8134        site_survey(padapter);
8135
8136        return H2C_SUCCESS;
8137}
8138
8139u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
8140{
8141        struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
8142        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8143        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8144
8145        if (pparm->mode < 4)
8146                pmlmeinfo->auth_algo = pparm->mode;
8147        return  H2C_SUCCESS;
8148}
8149
8150u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
8151{
8152        unsigned short                          ctrl;
8153        struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
8154        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8155        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8156        unsigned char                                   null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
8157
8158        /* main tx key for wep. */
8159        if (pparm->set_tx)
8160                pmlmeinfo->key_index = pparm->keyid;
8161
8162        /* write cam */
8163        ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
8164
8165        DBG_88E_LEVEL(_drv_info_, "set group key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) "
8166                        "keyid:%d\n", pparm->algorithm, pparm->keyid);
8167        write_cam(padapter, pparm->keyid, ctrl, null_sta, pparm->key);
8168
8169        return H2C_SUCCESS;
8170}
8171
8172u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
8173{
8174        u16 ctrl = 0;
8175        u8 cam_id;/* cam_entry */
8176        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8177        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8178        struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
8179
8180        /* cam_entry: */
8181        /* 0~3 for default key */
8182
8183        /* for concurrent mode (ap+sta): */
8184        /* default key is disable, using sw encrypt/decrypt */
8185        /* cam_entry = 4 for sta mode (macid = 0) */
8186        /* cam_entry(macid+3) = 5 ~ N for ap mode (aid = 1~N, macid = 2 ~N) */
8187
8188        /* for concurrent mode (sta+sta): */
8189        /* default key is disable, using sw encrypt/decrypt */
8190        /* cam_entry = 4 mapping to macid = 0 */
8191        /* cam_entry = 5 mapping to macid = 2 */
8192
8193        cam_id = 4;
8194
8195        DBG_88E_LEVEL(_drv_info_, "set pairwise key to hw: alg:%d(WEP40-1 WEP104-5 TKIP-2 AES-4) camid:%d\n",
8196                      pparm->algorithm, cam_id);
8197        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
8198                struct sta_info *psta;
8199                struct sta_priv *pstapriv = &padapter->stapriv;
8200
8201                if (pparm->algorithm == _NO_PRIVACY_)   /*  clear cam entry */ {
8202                        clear_cam_entry(padapter, pparm->id);
8203                        return H2C_SUCCESS_RSP;
8204                }
8205
8206                psta = rtw_get_stainfo(pstapriv, pparm->addr);
8207                if (psta) {
8208                        ctrl = (BIT(15) | ((pparm->algorithm) << 2));
8209
8210                        DBG_88E("r871x_set_stakey_hdl(): enc_algorithm=%d\n", pparm->algorithm);
8211
8212                        if ((psta->mac_id < 1) || (psta->mac_id > (NUM_STA-4))) {
8213                                DBG_88E("r871x_set_stakey_hdl():set_stakey failed, mac_id(aid)=%d\n", psta->mac_id);
8214                                return H2C_REJECTED;
8215                        }
8216
8217                        cam_id = (psta->mac_id + 3);/* 0~3 for default key, cmd_id = macid + 3, macid = aid+1; */
8218
8219                        DBG_88E("Write CAM, mac_addr =%x:%x:%x:%x:%x:%x, cam_entry=%d\n", pparm->addr[0],
8220                                pparm->addr[1], pparm->addr[2], pparm->addr[3], pparm->addr[4],
8221                                pparm->addr[5], cam_id);
8222
8223                        write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
8224
8225                        return H2C_SUCCESS_RSP;
8226                } else {
8227                        DBG_88E("r871x_set_stakey_hdl(): sta has been free\n");
8228                        return H2C_REJECTED;
8229                }
8230        }
8231
8232        /* below for sta mode */
8233
8234        if (pparm->algorithm == _NO_PRIVACY_) { /*  clear cam entry */
8235                clear_cam_entry(padapter, pparm->id);
8236                return H2C_SUCCESS;
8237        }
8238        ctrl = BIT(15) | ((pparm->algorithm) << 2);
8239        write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
8240        pmlmeinfo->enc_algo = pparm->algorithm;
8241        return H2C_SUCCESS;
8242}
8243
8244u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
8245{
8246        struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
8247        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8248        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8249
8250        struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
8251
8252        if (!psta)
8253                return  H2C_SUCCESS;
8254
8255        if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
8256            ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
8257                issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
8258                _set_timer(&psta->addba_retry_timer, ADDBA_TO);
8259        } else {
8260                psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
8261        }
8262        return  H2C_SUCCESS;
8263}
8264
8265u8 set_tx_beacon_cmd(struct adapter *padapter)
8266{
8267        struct cmd_obj  *ph2c;
8268        struct Tx_Beacon_param  *ptxBeacon_parm;
8269        struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
8270        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8271        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
8272        u8 res = _SUCCESS;
8273        int len_diff = 0;
8274
8275_func_enter_;
8276
8277        ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
8278        if (ph2c == NULL) {
8279                res = _FAIL;
8280                goto exit;
8281        }
8282
8283        ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param));
8284        if (ptxBeacon_parm == NULL) {
8285                kfree(ph2c);
8286                res = _FAIL;
8287                goto exit;
8288        }
8289
8290        memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
8291
8292        len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_,
8293                                      ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_,
8294                                      pmlmeinfo->hidden_ssid_mode);
8295        ptxBeacon_parm->network.IELength += len_diff;
8296
8297        init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
8298
8299        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
8300
8301
8302exit:
8303
8304_func_exit_;
8305
8306        return res;
8307}
8308
8309u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
8310{
8311        u8 evt_code;
8312        u16 evt_sz;
8313        uint    *peventbuf;
8314        void (*event_callback)(struct adapter *dev, u8 *pbuf);
8315        struct evt_priv *pevt_priv = &(padapter->evtpriv);
8316
8317        peventbuf = (uint *)pbuf;
8318        evt_sz = (u16)(*peventbuf&0xffff);
8319        evt_code = (u8)((*peventbuf>>16)&0xff);
8320
8321        /*  checking if event code is valid */
8322        if (evt_code >= MAX_C2HEVT) {
8323                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
8324                goto _abort_event_;
8325        }
8326
8327        /*  checking if event size match the event parm size */
8328        if ((wlanevents[evt_code].parmsize != 0) &&
8329            (wlanevents[evt_code].parmsize != evt_sz)) {
8330                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_,
8331                         ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
8332                         evt_code, wlanevents[evt_code].parmsize, evt_sz));
8333                goto _abort_event_;
8334        }
8335
8336        ATOMIC_INC(&pevt_priv->event_seq);
8337
8338        peventbuf += 2;
8339
8340        if (peventbuf) {
8341                event_callback = wlanevents[evt_code].event_callback;
8342                event_callback(padapter, (u8 *)peventbuf);
8343
8344                pevt_priv->evt_done_cnt++;
8345        }
8346
8347_abort_event_:
8348        return H2C_SUCCESS;
8349}
8350
8351u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
8352{
8353        if (!pbuf)
8354                return H2C_PARAMETERS_ERROR;
8355
8356        return H2C_SUCCESS;
8357}
8358
8359u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
8360{
8361        if (send_beacon(padapter) == _FAIL) {
8362                DBG_88E("issue_beacon, fail!\n");
8363                return H2C_PARAMETERS_ERROR;
8364        }
8365#ifdef CONFIG_88EU_AP_MODE
8366        else { /* tx bc/mc frames after update TIM */
8367                unsigned long irqL;
8368                struct sta_info *psta_bmc;
8369                struct list_head *xmitframe_plist, *xmitframe_phead;
8370                struct xmit_frame *pxmitframe = NULL;
8371                struct sta_priv  *pstapriv = &padapter->stapriv;
8372
8373                /* for BC/MC Frames */
8374                psta_bmc = rtw_get_bcmc_stainfo(padapter);
8375                if (!psta_bmc)
8376                        return H2C_SUCCESS;
8377
8378                if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
8379                        rtw_msleep_os(10);/*  10ms, ATIM(HIQ) Windows */
8380                        _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
8381
8382                        xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
8383                        xmitframe_plist = get_next(xmitframe_phead);
8384
8385                        while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
8386                                pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
8387
8388                                xmitframe_plist = get_next(xmitframe_plist);
8389
8390                                rtw_list_delete(&pxmitframe->list);
8391
8392                                psta_bmc->sleepq_len--;
8393                                if (psta_bmc->sleepq_len > 0)
8394                                        pxmitframe->attrib.mdata = 1;
8395                                else
8396                                        pxmitframe->attrib.mdata = 0;
8397
8398                                pxmitframe->attrib.triggered = 1;
8399
8400                                pxmitframe->attrib.qsel = 0x11;/* HIQ */
8401
8402                                _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
8403                                if (rtw_hal_xmit(padapter, pxmitframe))
8404                                        rtw_os_xmit_complete(padapter, pxmitframe);
8405                                _enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
8406                        }
8407                        _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
8408                }
8409        }
8410#endif
8411        return H2C_SUCCESS;
8412}
8413
8414u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
8415{
8416        struct set_ch_parm *set_ch_parm;
8417        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8418
8419        if (!pbuf)
8420                return H2C_PARAMETERS_ERROR;
8421
8422        set_ch_parm = (struct set_ch_parm *)pbuf;
8423
8424        DBG_88E(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
8425                FUNC_NDEV_ARG(padapter->pnetdev),
8426                set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
8427
8428        pmlmeext->cur_channel = set_ch_parm->ch;
8429        pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
8430        pmlmeext->cur_bwmode = set_ch_parm->bw;
8431
8432        set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
8433
8434        return  H2C_SUCCESS;
8435}
8436
8437u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
8438{
8439        struct SetChannelPlan_param *setChannelPlan_param;
8440        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
8441
8442        if (!pbuf)
8443                return H2C_PARAMETERS_ERROR;
8444
8445        setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
8446
8447        pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
8448        init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
8449
8450        return  H2C_SUCCESS;
8451}
8452
8453u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf)
8454{
8455        if (!pbuf)
8456                return H2C_PARAMETERS_ERROR;
8457        return  H2C_SUCCESS;
8458}
8459
8460u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
8461{
8462        return  H2C_REJECTED;
8463}
8464
8465/*  TDLS_WRCR           : write RCR DATA BIT */
8466/*  TDLS_SD_PTI         : issue peer traffic indication */
8467/*  TDLS_CS_OFF         : go back to the channel linked with AP, terminating channel switch procedure */
8468/*  TDLS_INIT_CH_SEN    : init channel sensing, receive all data and mgnt frame */
8469/*  TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
8470/*  TDLS_OFF_CH         : first time set channel to off channel */
8471/*  TDLS_BASE_CH                : go back tp the channel linked with AP when set base channel as target channel */
8472/*  TDLS_P_OFF_CH       : periodically go to off channel */
8473/*  TDLS_P_BASE_CH      : periodically go back to base channel */
8474/*  TDLS_RS_RCR         : restore RCR */
8475/*  TDLS_CKALV_PH1      : check alive timer phase1 */
8476/*  TDLS_CKALV_PH2      : check alive timer phase2 */
8477/*  TDLS_FREE_STA       : free tdls sta */
8478u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
8479{
8480        return H2C_REJECTED;
8481}
8482