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