linux/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7#define _RTW_MLME_EXT_C_
   8
   9#include <drv_types.h>
  10#include <rtw_debug.h>
  11#include <rtw_wifi_regd.h>
  12#include <hal_btcoex.h>
  13#include <linux/kernel.h>
  14
  15static struct mlme_handler mlme_sta_tbl[] = {
  16        {WIFI_ASSOCREQ,         "OnAssocReq",   &OnAssocReq},
  17        {WIFI_ASSOCRSP,         "OnAssocRsp",   &OnAssocRsp},
  18        {WIFI_REASSOCREQ,       "OnReAssocReq", &OnAssocReq},
  19        {WIFI_REASSOCRSP,       "OnReAssocRsp", &OnAssocRsp},
  20        {WIFI_PROBEREQ,         "OnProbeReq",   &OnProbeReq},
  21        {WIFI_PROBERSP,         "OnProbeRsp",           &OnProbeRsp},
  22
  23        /*----------------------------------------------------------
  24                                        below 2 are reserved
  25        -----------------------------------------------------------*/
  26        {0,                                     "DoReserved",           &DoReserved},
  27        {0,                                     "DoReserved",           &DoReserved},
  28        {WIFI_BEACON,           "OnBeacon",             &OnBeacon},
  29        {WIFI_ATIM,                     "OnATIM",               &OnAtim},
  30        {WIFI_DISASSOC,         "OnDisassoc",           &OnDisassoc},
  31        {WIFI_AUTH,                     "OnAuth",               &OnAuthClient},
  32        {WIFI_DEAUTH,           "OnDeAuth",             &OnDeAuth},
  33        {WIFI_ACTION,           "OnAction",             &OnAction},
  34        {WIFI_ACTION_NOACK, "OnActionNoAck",    &OnAction},
  35};
  36
  37static struct action_handler OnAction_tbl[] = {
  38        {RTW_WLAN_CATEGORY_SPECTRUM_MGMT,        "ACTION_SPECTRUM_MGMT", on_action_spct},
  39        {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &DoReserved},
  40        {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &DoReserved},
  41        {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
  42        {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
  43        {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
  44        {RTW_WLAN_CATEGORY_FT, "ACTION_FT",     &DoReserved},
  45        {RTW_WLAN_CATEGORY_HT,  "ACTION_HT",    &OnAction_ht},
  46        {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},
  47        {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved},
  48        {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved},
  49        {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &DoReserved},
  50        {RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &DoReserved},
  51        {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved},
  52};
  53
  54static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
  55
  56/**************************************************
  57OUI definitions for the vendor specific IE
  58***************************************************/
  59unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
  60unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
  61unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
  62unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09};
  63unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A};
  64
  65unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
  66unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
  67
  68static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
  69
  70/********************************************************
  71ChannelPlan definitions
  72*********************************************************/
  73static RT_CHANNEL_PLAN_2G       RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = {
  74        {{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 */
  75        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},              /*  0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */
  76        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},                      /*  0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */
  77        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */
  78        {{10, 11, 12, 13}, 4},                                          /*  0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */
  79        {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},  /*  0x05, RT_CHANNEL_DOMAIN_2G_GLOBAL , Passive scan CH 12, 13, 14 */
  80        {{}, 0},                                                                /*  0x06, RT_CHANNEL_DOMAIN_2G_NULL */
  81};
  82
  83static RT_CHANNEL_PLAN_5G       RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = {
  84        {{}, 0},                                                                                                                                                                        /*  0x00, RT_CHANNEL_DOMAIN_5G_NULL */
  85        {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19},                                          /*  0x01, RT_CHANNEL_DOMAIN_5G_ETSI1 */
  86        {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /*  0x02, RT_CHANNEL_DOMAIN_5G_ETSI2 */
  87        {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22},                   /*  0x03, RT_CHANNEL_DOMAIN_5G_ETSI3 */
  88        {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24}, /*  0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */
  89        {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},                                                                                                         /*  0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */
  90        {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},                                                                                        /*  0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */
  91        {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12},                                                                                             /*  0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */
  92        {{149, 153, 157, 161, 165}, 5},                                                                                                                                 /*  0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */
  93        {{36, 40, 44, 48, 52, 56, 60, 64}, 8},                                                                                                                          /*  0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */
  94        {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20},                                     /*  0x0A, RT_CHANNEL_DOMAIN_5G_FCC7_IC1 */
  95        {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 20},                                     /*  0x0B, RT_CHANNEL_DOMAIN_5G_KCC1 */
  96        {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19},                                          /*  0x0C, RT_CHANNEL_DOMAIN_5G_MKK1 */
  97        {{36, 40, 44, 48, 52, 56, 60, 64}, 8},                                                                                                                          /*  0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */
  98        {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},                                                                                  /*  0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */
  99        {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15},                                                         /*  0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */
 100        {{56, 60, 64, 149, 153, 157, 161, 165}, 8},                                                                                                                     /*  0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */
 101        {{149, 153, 157, 161, 165}, 5},                                                                                                                                 /*  0x11, RT_CHANNEL_DOMAIN_5G_NCC3 */
 102        {{36, 40, 44, 48}, 4},                                                                                                                                                  /*  0x12, RT_CHANNEL_DOMAIN_5G_ETSI4 */
 103        {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20},                                     /*  0x13, RT_CHANNEL_DOMAIN_5G_ETSI5 */
 104        {{149, 153, 157, 161}, 4},                                                                                                                                              /*  0x14, RT_CHANNEL_DOMAIN_5G_FCC8 */
 105        {{36, 40, 44, 48, 52, 56, 60, 64}, 8},                                                                                                                          /*  0x15, RT_CHANNEL_DOMAIN_5G_ETSI6 */
 106        {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},                                                                                        /*  0x16, RT_CHANNEL_DOMAIN_5G_ETSI7 */
 107        {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},                                                                                                         /*  0x17, RT_CHANNEL_DOMAIN_5G_ETSI8 */
 108        {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},                                                                                  /*  0x18, RT_CHANNEL_DOMAIN_5G_ETSI9 */
 109        {{149, 153, 157, 161, 165}, 5},                                                                                                                                 /*  0x19, RT_CHANNEL_DOMAIN_5G_ETSI10 */
 110        {{36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165}, 16},                                                                 /*  0x1A, RT_CHANNEL_DOMAIN_5G_ETSI11 */
 111        {{52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17},                                                        /*  0x1B, RT_CHANNEL_DOMAIN_5G_NCC4 */
 112        {{149, 153, 157, 161}, 4},                                                                                                                                              /*  0x1C, RT_CHANNEL_DOMAIN_5G_ETSI12 */
 113        {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17},                                                        /*  0x1D, RT_CHANNEL_DOMAIN_5G_FCC9 */
 114        {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140}, 12},                                                                                 /*  0x1E, RT_CHANNEL_DOMAIN_5G_ETSI13 */
 115        {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161}, 20},                                     /*  0x1F, RT_CHANNEL_DOMAIN_5G_FCC10 */
 116
 117        /*  Driver self defined for old channel plan Compatible , Remember to modify if have new channel plan definition ===== */
 118        {{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},                                /*  0x20, RT_CHANNEL_DOMAIN_5G_FCC */
 119        {{36, 40, 44, 48}, 4},                                                                                                                                                  /*  0x21, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */
 120        {{36, 40, 44, 48, 149, 153, 157, 161}, 8},                                                                                                                      /*  0x22, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */
 121};
 122
 123static RT_CHANNEL_PLAN_MAP      RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = {
 124        /*  0x00 ~ 0x1F , Old Define ===== */
 125        {0x02, 0x20},   /* 0x00, RT_CHANNEL_DOMAIN_FCC */
 126        {0x02, 0x0A},   /* 0x01, RT_CHANNEL_DOMAIN_IC */
 127        {0x01, 0x01},   /* 0x02, RT_CHANNEL_DOMAIN_ETSI */
 128        {0x01, 0x00},   /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */
 129        {0x01, 0x00},   /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */
 130        {0x03, 0x00},   /* 0x05, RT_CHANNEL_DOMAIN_MKK */
 131        {0x03, 0x00},   /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */
 132        {0x01, 0x09},   /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */
 133        {0x03, 0x09},   /* 0x08, RT_CHANNEL_DOMAIN_TELEC */
 134        {0x03, 0x00},   /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */
 135        {0x00, 0x00},   /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */
 136        {0x02, 0x0F},   /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */
 137        {0x01, 0x08},   /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */
 138        {0x02, 0x06},   /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */
 139        {0x02, 0x0B},   /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */
 140        {0x02, 0x09},   /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */
 141        {0x01, 0x01},   /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */
 142        {0x02, 0x05},   /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */
 143        {0x01, 0x21},   /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
 144        {0x00, 0x04},   /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */
 145        {0x02, 0x10},   /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */
 146        {0x00, 0x21},   /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */
 147        {0x00, 0x22},   /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */
 148        {0x03, 0x21},   /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */
 149        {0x06, 0x08},   /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */
 150        {0x02, 0x08},   /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */
 151        {0x00, 0x00},   /* 0x1A, */
 152        {0x00, 0x00},   /* 0x1B, */
 153        {0x00, 0x00},   /* 0x1C, */
 154        {0x00, 0x00},   /* 0x1D, */
 155        {0x00, 0x00},   /* 0x1E, */
 156        {0x06, 0x04},   /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */
 157        /*  0x20 ~ 0x7F , New Define ===== */
 158        {0x00, 0x00},   /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */
 159        {0x01, 0x00},   /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */
 160        {0x02, 0x00},   /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */
 161        {0x03, 0x00},   /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */
 162        {0x04, 0x00},   /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */
 163        {0x02, 0x04},   /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */
 164        {0x00, 0x01},   /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */
 165        {0x03, 0x0C},   /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */
 166        {0x00, 0x0B},   /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */
 167        {0x00, 0x05},   /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */
 168        {0x00, 0x00},   /* 0x2A, */
 169        {0x00, 0x00},   /* 0x2B, */
 170        {0x00, 0x00},   /* 0x2C, */
 171        {0x00, 0x00},   /* 0x2D, */
 172        {0x00, 0x00},   /* 0x2E, */
 173        {0x00, 0x00},   /* 0x2F, */
 174        {0x00, 0x06},   /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */
 175        {0x00, 0x07},   /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */
 176        {0x00, 0x08},   /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */
 177        {0x00, 0x09},   /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */
 178        {0x02, 0x0A},   /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */
 179        {0x00, 0x02},   /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */
 180        {0x00, 0x03},   /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */
 181        {0x03, 0x0D},   /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */
 182        {0x03, 0x0E},   /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */
 183        {0x02, 0x0F},   /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */
 184        {0x00, 0x00},   /* 0x3A, */
 185        {0x00, 0x00},   /* 0x3B, */
 186        {0x00, 0x00},   /* 0x3C, */
 187        {0x00, 0x00},   /* 0x3D, */
 188        {0x00, 0x00},   /* 0x3E, */
 189        {0x00, 0x00},   /* 0x3F, */
 190        {0x02, 0x10},   /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */
 191        {0x05, 0x00},   /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */
 192        {0x01, 0x12},   /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */
 193        {0x02, 0x05},   /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */
 194        {0x02, 0x11},   /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */
 195        {0x00, 0x13},   /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */
 196        {0x02, 0x14},   /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */
 197        {0x00, 0x15},   /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */
 198        {0x00, 0x16},   /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */
 199        {0x00, 0x17},   /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */
 200        {0x00, 0x18},   /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */
 201        {0x00, 0x19},   /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */
 202        {0x00, 0x1A},   /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */
 203        {0x02, 0x1B},   /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */
 204        {0x00, 0x1C},   /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */
 205        {0x02, 0x1D},   /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */
 206        {0x00, 0x1E},   /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */
 207        {0x02, 0x1F},   /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */
 208};
 209
 210static RT_CHANNEL_PLAN_MAP      RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; /* use the conbination for max channel numbers */
 211
 212/*
 213 * Search the @param ch in given @param ch_set
 214 * @ch_set: the given channel set
 215 * @ch: the given channel number
 216 *
 217 * return the index of channel_num in channel_set, -1 if not found
 218 */
 219int rtw_ch_set_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch)
 220{
 221        int i;
 222        for (i = 0; ch_set[i].ChannelNum != 0; i++) {
 223                if (ch == ch_set[i].ChannelNum)
 224                        break;
 225        }
 226
 227        if (i >= ch_set[i].ChannelNum)
 228                return -1;
 229        return i;
 230}
 231
 232/*
 233 * Check the @param ch is fit with setband setting of @param adapter
 234 * @adapter: the given adapter
 235 * @ch: the given channel number
 236 *
 237 * return true when check valid, false not valid
 238 */
 239bool rtw_mlme_band_check(struct adapter *adapter, const u32 ch)
 240{
 241        if (adapter->setband == GHZ24_50 /* 2.4G and 5G */
 242                || (adapter->setband == GHZ_24 && ch < 35) /* 2.4G only */
 243                || (adapter->setband == GHZ_50 && ch > 35) /* 5G only */
 244        ) {
 245                return true;
 246        }
 247        return false;
 248}
 249
 250/****************************************************************************
 251
 252Following are the initialization functions for WiFi MLME
 253
 254*****************************************************************************/
 255
 256int init_hw_mlme_ext(struct adapter *padapter)
 257{
 258        struct  mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 259
 260        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
 261        return _SUCCESS;
 262}
 263
 264void init_mlme_default_rate_set(struct adapter *padapter)
 265{
 266        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 267
 268        unsigned char mixed_datarate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_, 0xff};
 269        unsigned char mixed_basicrate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,};
 270        unsigned char supported_mcs_set[16] = {0xff, 0xff, 0x00, 0x00, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
 271
 272        memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
 273        memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
 274
 275        memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set));
 276}
 277
 278static void init_mlme_ext_priv_value(struct adapter *padapter)
 279{
 280        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 281        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 282
 283        atomic_set(&pmlmeext->event_seq, 0);
 284        pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */
 285        pmlmeext->sa_query_seq = 0;
 286        pmlmeext->mgnt_80211w_IPN = 0;
 287        pmlmeext->mgnt_80211w_IPN_rx = 0;
 288        pmlmeext->cur_channel = padapter->registrypriv.channel;
 289        pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
 290        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 291
 292        pmlmeext->retry = 0;
 293
 294        pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
 295
 296        init_mlme_default_rate_set(padapter);
 297
 298        if (pmlmeext->cur_channel > 14)
 299                pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
 300        else
 301                pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
 302
 303        pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
 304        pmlmeext->sitesurvey_res.channel_idx = 0;
 305        pmlmeext->sitesurvey_res.bss_cnt = 0;
 306        pmlmeext->scan_abort = false;
 307
 308        pmlmeinfo->state = WIFI_FW_NULL_STATE;
 309        pmlmeinfo->reauth_count = 0;
 310        pmlmeinfo->reassoc_count = 0;
 311        pmlmeinfo->link_count = 0;
 312        pmlmeinfo->auth_seq = 0;
 313        pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
 314        pmlmeinfo->key_index = 0;
 315        pmlmeinfo->iv = 0;
 316
 317        pmlmeinfo->enc_algo = _NO_PRIVACY_;
 318        pmlmeinfo->authModeToggle = 0;
 319
 320        memset(pmlmeinfo->chg_txt, 0, 128);
 321
 322        pmlmeinfo->slotTime = SHORT_SLOT_TIME;
 323        pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
 324
 325        pmlmeinfo->dialogToken = 0;
 326
 327        pmlmeext->action_public_rxseq = 0xffff;
 328        pmlmeext->action_public_dialog_token = 0xff;
 329}
 330
 331static int has_channel(RT_CHANNEL_INFO *channel_set,
 332                                           u8 chanset_size,
 333                                           u8 chan)
 334{
 335        int i;
 336
 337        for (i = 0; i < chanset_size; i++) {
 338                if (channel_set[i].ChannelNum == chan) {
 339                        return 1;
 340                }
 341        }
 342
 343        return 0;
 344}
 345
 346static void init_channel_list(struct adapter *padapter, RT_CHANNEL_INFO *channel_set,
 347                                                          u8 chanset_size,
 348                                                          struct p2p_channels *channel_list)
 349{
 350
 351        struct p2p_oper_class_map op_class[] = {
 352                { IEEE80211G,  81,   1,  13,  1, BW20 },
 353                { IEEE80211G,  82,  14,  14,  1, BW20 },
 354                { IEEE80211A, 115,  36,  48,  4, BW20 },
 355                { IEEE80211A, 116,  36,  44,  8, BW40PLUS },
 356                { IEEE80211A, 117,  40,  48,  8, BW40MINUS },
 357                { IEEE80211A, 124, 149, 161,  4, BW20 },
 358                { IEEE80211A, 125, 149, 169,  4, BW20 },
 359                { IEEE80211A, 126, 149, 157,  8, BW40PLUS },
 360                { IEEE80211A, 127, 153, 161,  8, BW40MINUS },
 361                { -1, 0, 0, 0, 0, BW20 }
 362        };
 363
 364        int cla, op;
 365
 366        cla = 0;
 367
 368        for (op = 0; op_class[op].op_class; op++) {
 369                u8 ch;
 370                struct p2p_oper_class_map *o = &op_class[op];
 371                struct p2p_reg_class *reg = NULL;
 372
 373                for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
 374                        if (!has_channel(channel_set, chanset_size, ch))
 375                                continue;
 376
 377                        if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
 378                                continue;
 379
 380                        if ((0 < (padapter->registrypriv.bw_mode & 0xf0)) &&
 381                                ((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
 382                                continue;
 383
 384                        if (!reg) {
 385                                reg = &channel_list->reg_class[cla];
 386                                cla++;
 387                                reg->reg_class = o->op_class;
 388                                reg->channels = 0;
 389                        }
 390                        reg->channel[reg->channels] = ch;
 391                        reg->channels++;
 392                }
 393        }
 394        channel_list->reg_classes = cla;
 395
 396}
 397
 398static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, RT_CHANNEL_INFO *channel_set)
 399{
 400        u8 index, chanset_size = 0;
 401        u8 b5GBand = false, b2_4GBand = false;
 402        u8 Index2G = 0, Index5G = 0;
 403
 404        memset(channel_set, 0, sizeof(RT_CHANNEL_INFO)*MAX_CHANNEL_NUM);
 405
 406        if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) {
 407                DBG_871X("ChannelPlan ID %x error !!!!!\n", ChannelPlan);
 408                return chanset_size;
 409        }
 410
 411        if (IsSupported24G(padapter->registrypriv.wireless_mode)) {
 412                b2_4GBand = true;
 413                if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan)
 414                        Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
 415                else
 416                        Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
 417        }
 418
 419        if (b2_4GBand) {
 420                for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
 421                        channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
 422
 423                        if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */
 424                                (RT_CHANNEL_DOMAIN_GLOBAL_NULL == ChannelPlan)) {
 425                                if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
 426                                        channel_set[chanset_size].ScanType = SCAN_ACTIVE;
 427                                else if ((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
 428                                        channel_set[chanset_size].ScanType  = SCAN_PASSIVE;
 429                        } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan ||
 430                                RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan ||
 431                                RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { /*  channel 12~13, passive scan */
 432                                if (channel_set[chanset_size].ChannelNum <= 11)
 433                                        channel_set[chanset_size].ScanType = SCAN_ACTIVE;
 434                                else
 435                                        channel_set[chanset_size].ScanType = SCAN_PASSIVE;
 436                        } else
 437                                channel_set[chanset_size].ScanType = SCAN_ACTIVE;
 438
 439                        chanset_size++;
 440                }
 441        }
 442
 443        if (b5GBand) {
 444                for (index = 0; index < RTW_ChannelPlan5G[Index5G].Len; index++) {
 445                        if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48
 446                                || RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) {
 447                                channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index];
 448                                if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)/* passive scan for all 5G channels */
 449                                        channel_set[chanset_size].ScanType = SCAN_PASSIVE;
 450                                else
 451                                        channel_set[chanset_size].ScanType = SCAN_ACTIVE;
 452                                DBG_871X("%s(): channel_set[%d].ChannelNum = %d\n", __func__, chanset_size, channel_set[chanset_size].ChannelNum);
 453                                chanset_size++;
 454                        }
 455                }
 456        }
 457
 458        DBG_871X("%s ChannelPlan ID %x Chan num:%d \n", __func__, ChannelPlan, chanset_size);
 459        return chanset_size;
 460}
 461
 462int     init_mlme_ext_priv(struct adapter *padapter)
 463{
 464        int     res = _SUCCESS;
 465        struct registry_priv *pregistrypriv = &padapter->registrypriv;
 466        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 467        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 468        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 469
 470        pmlmeext->padapter = padapter;
 471
 472        /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */
 473
 474        init_mlme_ext_priv_value(padapter);
 475        pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req;
 476
 477        init_mlme_ext_timer(padapter);
 478
 479        init_mlme_ap_info(padapter);
 480
 481        pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set);
 482        init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
 483        pmlmeext->last_scan_time = 0;
 484        pmlmeext->chan_scan_time = SURVEY_TO;
 485        pmlmeext->mlmeext_init = true;
 486        pmlmeext->active_keep_alive_check = true;
 487
 488#ifdef DBG_FIXED_CHAN
 489        pmlmeext->fixed_chan = 0xFF;
 490#endif
 491
 492        return res;
 493
 494}
 495
 496void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext)
 497{
 498        struct adapter *padapter = pmlmeext->padapter;
 499
 500        if (!padapter)
 501                return;
 502
 503        if (padapter->bDriverStopped) {
 504                del_timer_sync(&pmlmeext->survey_timer);
 505                del_timer_sync(&pmlmeext->link_timer);
 506                /* del_timer_sync(&pmlmeext->ADDBA_timer); */
 507        }
 508}
 509
 510static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
 511{
 512        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 513        u8 *pframe = precv_frame->u.hdr.rx_data;
 514
 515        if (ptable->func) {
 516                /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
 517                if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
 518                    memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
 519                        return;
 520
 521                ptable->func(padapter, precv_frame);
 522        }
 523}
 524
 525void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame)
 526{
 527        int index;
 528        struct mlme_handler *ptable;
 529        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 530        u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 531        u8 *pframe = precv_frame->u.hdr.rx_data;
 532        struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
 533        struct dvobj_priv *psdpriv = padapter->dvobj;
 534        struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
 535
 536        RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
 537                 ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n",
 538                  GetFrameType(pframe), GetFrameSubType(pframe)));
 539
 540        if (GetFrameType(pframe) != WIFI_MGT_TYPE) {
 541                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe)));
 542                return;
 543        }
 544
 545        /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
 546        if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
 547                memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) {
 548                return;
 549        }
 550
 551        ptable = mlme_sta_tbl;
 552
 553        index = GetFrameSubType(pframe) >> 4;
 554
 555        if (index >= ARRAY_SIZE(mlme_sta_tbl)) {
 556                RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type =%d\n", index));
 557                return;
 558        }
 559        ptable += index;
 560
 561        if (psta != NULL) {
 562                if (GetRetry(pframe)) {
 563                        if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) {
 564                                /* drop the duplicate management frame */
 565                                pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++;
 566                                DBG_871X("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num);
 567                                return;
 568                        }
 569                }
 570                psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
 571        }
 572
 573        switch (GetFrameSubType(pframe)) {
 574        case WIFI_AUTH:
 575                if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
 576                        ptable->func = &OnAuth;
 577                else
 578                        ptable->func = &OnAuthClient;
 579                /* fall through */
 580        case WIFI_ASSOCREQ:
 581        case WIFI_REASSOCREQ:
 582                _mgt_dispatcher(padapter, ptable, precv_frame);
 583                break;
 584        case WIFI_PROBEREQ:
 585                _mgt_dispatcher(padapter, ptable, precv_frame);
 586                break;
 587        case WIFI_BEACON:
 588                _mgt_dispatcher(padapter, ptable, precv_frame);
 589                break;
 590        case WIFI_ACTION:
 591                /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */
 592                _mgt_dispatcher(padapter, ptable, precv_frame);
 593                break;
 594        default:
 595                _mgt_dispatcher(padapter, ptable, precv_frame);
 596                break;
 597        }
 598}
 599
 600/****************************************************************************
 601
 602Following are the callback functions for each subtype of the management frames
 603
 604*****************************************************************************/
 605
 606unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame)
 607{
 608        unsigned int    ielen;
 609        unsigned char *p;
 610        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 611        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 612        struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
 613        struct wlan_bssid_ex    *cur = &pmlmeinfo->network;
 614        u8 *pframe = precv_frame->u.hdr.rx_data;
 615        uint len = precv_frame->u.hdr.len;
 616        u8 is_valid_p2p_probereq = false;
 617
 618        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 619                return _SUCCESS;
 620
 621        if (check_fwstate(pmlmepriv, _FW_LINKED) == false &&
 622                check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) {
 623                return _SUCCESS;
 624        }
 625
 626
 627        /* DBG_871X("+OnProbeReq\n"); */
 628
 629#ifdef CONFIG_AUTO_AP_MODE
 630        if (check_fwstate(pmlmepriv, _FW_LINKED) &&
 631                        pmlmepriv->cur_network.join_res) {
 632                struct sta_info *psta;
 633                u8 *mac_addr, *peer_addr;
 634                struct sta_priv *pstapriv = &padapter->stapriv;
 635                u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A};
 636                /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */
 637
 638                p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, (int *)&ielen,
 639                        len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
 640
 641                if (!p || ielen != 14)
 642                        goto _non_rc_device;
 643
 644                if (memcmp(p+2, RC_OUI, sizeof(RC_OUI)))
 645                        goto _non_rc_device;
 646
 647                if (memcmp(p+6, get_sa(pframe), ETH_ALEN)) {
 648                        DBG_871X("%s, do rc pairing ("MAC_FMT"), but mac addr mismatch!("MAC_FMT")\n", __func__,
 649                                MAC_ARG(get_sa(pframe)), MAC_ARG(p+6));
 650
 651                        goto _non_rc_device;
 652                }
 653
 654                DBG_871X("%s, got the pairing device("MAC_FMT")\n", __func__,  MAC_ARG(get_sa(pframe)));
 655
 656                /* new a station */
 657                psta = rtw_get_stainfo(pstapriv, get_sa(pframe));
 658                if (psta == NULL) {
 659                        /*  allocate a new one */
 660                        DBG_871X("going to alloc stainfo for rc ="MAC_FMT"\n",  MAC_ARG(get_sa(pframe)));
 661                        psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe));
 662                        if (!psta) {
 663                                /* TODO: */
 664                                DBG_871X(" Exceed the upper limit of supported clients...\n");
 665                                return _SUCCESS;
 666                        }
 667
 668                        spin_lock_bh(&pstapriv->asoc_list_lock);
 669                        if (list_empty(&psta->asoc_list)) {
 670                                psta->expire_to = pstapriv->expire_to;
 671                                list_add_tail(&psta->asoc_list, &pstapriv->asoc_list);
 672                                pstapriv->asoc_list_cnt++;
 673                        }
 674                        spin_unlock_bh(&pstapriv->asoc_list_lock);
 675
 676                        /* generate pairing ID */
 677                        mac_addr = myid(&(padapter->eeprompriv));
 678                        peer_addr = psta->hwaddr;
 679                        psta->pid = (u16)(((mac_addr[4]<<8) + mac_addr[5]) + ((peer_addr[4]<<8) + peer_addr[5]));
 680
 681                        /* update peer stainfo */
 682                        psta->isrc = true;
 683                        /* psta->aid = 0; */
 684                        /* psta->mac_id = 2; */
 685
 686                        /* get a unique AID */
 687                        if (psta->aid > 0) {
 688                                DBG_871X("old AID %d\n", psta->aid);
 689                        } else {
 690                                for (psta->aid = 1; psta->aid <= NUM_STA; psta->aid++)
 691                                        if (pstapriv->sta_aid[psta->aid - 1] == NULL)
 692                                                break;
 693
 694                                if (psta->aid > pstapriv->max_num_sta) {
 695                                        psta->aid = 0;
 696                                        DBG_871X("no room for more AIDs\n");
 697                                        return _SUCCESS;
 698                                }
 699                                pstapriv->sta_aid[psta->aid - 1] = psta;
 700                                DBG_871X("allocate new AID = (%d)\n", psta->aid);
 701                        }
 702
 703                        psta->qos_option = 1;
 704                        psta->bw_mode = CHANNEL_WIDTH_20;
 705                        psta->ieee8021x_blocked = false;
 706                        psta->htpriv.ht_option = true;
 707                        psta->htpriv.ampdu_enable = false;
 708                        psta->htpriv.sgi_20m = false;
 709                        psta->htpriv.sgi_40m = false;
 710                        psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
 711                        psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
 712                        psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
 713
 714                        rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
 715
 716                        memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
 717
 718                        spin_lock_bh(&psta->lock);
 719                        psta->state |= _FW_LINKED;
 720                        spin_unlock_bh(&psta->lock);
 721
 722                        report_add_sta_event(padapter, psta->hwaddr, psta->aid);
 723
 724                }
 725
 726                issue_probersp(padapter, get_sa(pframe), false);
 727
 728                return _SUCCESS;
 729
 730        }
 731
 732_non_rc_device:
 733
 734        return _SUCCESS;
 735
 736#endif /* CONFIG_AUTO_AP_MODE */
 737
 738        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
 739                        len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
 740
 741
 742        /* check (wildcard) SSID */
 743        if (p != NULL) {
 744                if (is_valid_p2p_probereq)
 745                        goto _issue_probersp;
 746
 747                if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength))
 748                        || (ielen == 0 && pmlmeinfo->hidden_ssid_mode)
 749                )
 750                        return _SUCCESS;
 751
 752_issue_probersp:
 753                if ((check_fwstate(pmlmepriv, _FW_LINKED)  &&
 754                        pmlmepriv->cur_network.join_res) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
 755                        /* DBG_871X("+issue_probersp during ap mode\n"); */
 756                        issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);
 757                }
 758
 759        }
 760
 761        return _SUCCESS;
 762
 763}
 764
 765unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame)
 766{
 767        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 768
 769        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
 770                report_survey_event(padapter, precv_frame);
 771                return _SUCCESS;
 772        }
 773
 774        return _SUCCESS;
 775
 776}
 777
 778unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame)
 779{
 780        int cam_idx;
 781        struct sta_info *psta;
 782        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 783        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 784        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 785        struct sta_priv *pstapriv = &padapter->stapriv;
 786        u8 *pframe = precv_frame->u.hdr.rx_data;
 787        uint len = precv_frame->u.hdr.len;
 788        struct wlan_bssid_ex *pbss;
 789        int ret = _SUCCESS;
 790        u8 *p = NULL;
 791        u32 ielen = 0;
 792
 793        p = rtw_get_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ielen, precv_frame->u.hdr.len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_);
 794        if ((p != NULL) && (ielen > 0)) {
 795                if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) {
 796                        /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */
 797                        DBG_871X("[WIFIDBG] Error in ESR IE is detected in Beacon of BSSID:"MAC_FMT". Fix the length of ESR IE to avoid failed Beacon parsing.\n", MAC_ARG(GetAddr3Ptr(pframe)));
 798                        *(p + 1) = ielen - 1;
 799                }
 800        }
 801
 802        if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
 803                report_survey_event(padapter, precv_frame);
 804                return _SUCCESS;
 805        }
 806
 807        if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) {
 808                if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
 809                        /* we should update current network before auth, or some IE is wrong */
 810                        pbss = rtw_malloc(sizeof(struct wlan_bssid_ex));
 811                        if (pbss) {
 812                                if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
 813                                        update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true);
 814                                        rtw_get_bcn_info(&(pmlmepriv->cur_network));
 815                                }
 816                                kfree(pbss);
 817                        }
 818
 819                        /* check the vendor of the assoc AP */
 820                        pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr));
 821
 822                        /* update TSF Value */
 823                        update_TSF(pmlmeext, pframe, len);
 824
 825                        /* reset for adaptive_early_32k */
 826                        pmlmeext->adaptive_tsf_done = false;
 827                        pmlmeext->DrvBcnEarly = 0xff;
 828                        pmlmeext->DrvBcnTimeOut = 0xff;
 829                        pmlmeext->bcn_cnt = 0;
 830                        memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt));
 831                        memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio));
 832
 833                        /* start auth */
 834                        start_clnt_auth(padapter);
 835
 836                        return _SUCCESS;
 837                }
 838
 839                if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
 840                        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
 841                        if (psta != NULL) {
 842                                ret = rtw_check_bcn_info(padapter, pframe, len);
 843                                if (!ret) {
 844                                                DBG_871X_LEVEL(_drv_always_, "ap has changed, disconnect now\n ");
 845                                                receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 0);
 846                                                return _SUCCESS;
 847                                }
 848                                /* update WMM, ERP in the beacon */
 849                                /* todo: the timer is used instead of the number of the beacon received */
 850                                if ((sta_rx_pkts(psta) & 0xf) == 0)
 851                                        /* DBG_871X("update_bcn_info\n"); */
 852                                        update_beacon_info(padapter, pframe, len, psta);
 853
 854                                adaptive_early_32k(pmlmeext, pframe, len);
 855                        }
 856                } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
 857                        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
 858                        if (psta != NULL) {
 859                                /* update WMM, ERP in the beacon */
 860                                /* todo: the timer is used instead of the number of the beacon received */
 861                                if ((sta_rx_pkts(psta) & 0xf) == 0) {
 862                                        /* DBG_871X("update_bcn_info\n"); */
 863                                        update_beacon_info(padapter, pframe, len, psta);
 864                                }
 865                        } else {
 866                                /* allocate a new CAM entry for IBSS station */
 867                                cam_idx = allocate_fw_sta_entry(padapter);
 868                                if (cam_idx == NUM_STA)
 869                                        goto _END_ONBEACON_;
 870
 871                                /* get supported rate */
 872                                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) {
 873                                        pmlmeinfo->FW_sta_info[cam_idx].status = 0;
 874                                        goto _END_ONBEACON_;
 875                                }
 876
 877                                /* update TSF Value */
 878                                update_TSF(pmlmeext, pframe, len);
 879
 880                                /* report sta add event */
 881                                report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
 882                        }
 883                }
 884        }
 885
 886_END_ONBEACON_:
 887
 888        return _SUCCESS;
 889
 890}
 891
 892unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame)
 893{
 894        unsigned int    auth_mode, seq, ie_len;
 895        unsigned char *sa, *p;
 896        u16 algorithm;
 897        int     status;
 898        static struct sta_info stat;
 899        struct  sta_info *pstat = NULL;
 900        struct  sta_priv *pstapriv = &padapter->stapriv;
 901        struct security_priv *psecuritypriv = &padapter->securitypriv;
 902        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 903        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 904        u8 *pframe = precv_frame->u.hdr.rx_data;
 905        uint len = precv_frame->u.hdr.len;
 906        u8 offset = 0;
 907
 908        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
 909                return _FAIL;
 910
 911        DBG_871X("+OnAuth\n");
 912
 913        sa = GetAddr2Ptr(pframe);
 914
 915        auth_mode = psecuritypriv->dot11AuthAlgrthm;
 916
 917        if (GetPrivacy(pframe)) {
 918                u8 *iv;
 919                struct rx_pkt_attrib     *prxattrib = &(precv_frame->u.hdr.attrib);
 920
 921                prxattrib->hdrlen = WLAN_HDR_A3_LEN;
 922                prxattrib->encrypt = _WEP40_;
 923
 924                iv = pframe+prxattrib->hdrlen;
 925                prxattrib->key_index = ((iv[3]>>6)&0x3);
 926
 927                prxattrib->iv_len = 4;
 928                prxattrib->icv_len = 4;
 929
 930                rtw_wep_decrypt(padapter, (u8 *)precv_frame);
 931
 932                offset = 4;
 933        }
 934
 935        algorithm = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
 936        seq     = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
 937
 938        DBG_871X("auth alg =%x, seq =%X\n", algorithm, seq);
 939
 940        if (auth_mode == 2 &&
 941                        psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
 942                        psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
 943                auth_mode = 0;
 944
 945        if ((algorithm > 0 && auth_mode == 0) ||        /*  rx a shared-key auth but shared not enabled */
 946                (algorithm == 0 && auth_mode == 1)) {   /*  rx a open-system auth but shared-key is enabled */
 947                DBG_871X("auth rejected due to bad alg [alg =%d, auth_mib =%d] %02X%02X%02X%02X%02X%02X\n",
 948                        algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
 949
 950                status = _STATS_NO_SUPP_ALG_;
 951
 952                goto auth_fail;
 953        }
 954
 955        if (rtw_access_ctrl(padapter, sa) == false) {
 956                status = _STATS_UNABLE_HANDLE_STA_;
 957                goto auth_fail;
 958        }
 959
 960        pstat = rtw_get_stainfo(pstapriv, sa);
 961        if (pstat == NULL) {
 962
 963                /*  allocate a new one */
 964                DBG_871X("going to alloc stainfo for sa ="MAC_FMT"\n",  MAC_ARG(sa));
 965                pstat = rtw_alloc_stainfo(pstapriv, sa);
 966                if (pstat == NULL) {
 967                        DBG_871X(" Exceed the upper limit of supported clients...\n");
 968                        status = _STATS_UNABLE_HANDLE_STA_;
 969                        goto auth_fail;
 970                }
 971
 972                pstat->state = WIFI_FW_AUTH_NULL;
 973                pstat->auth_seq = 0;
 974
 975                /* pstat->flags = 0; */
 976                /* pstat->capability = 0; */
 977        } else {
 978
 979                spin_lock_bh(&pstapriv->asoc_list_lock);
 980                if (list_empty(&pstat->asoc_list) == false) {
 981                        list_del_init(&pstat->asoc_list);
 982                        pstapriv->asoc_list_cnt--;
 983                        if (pstat->expire_to > 0) {
 984                                /* TODO: STA re_auth within expire_to */
 985                        }
 986                }
 987                spin_unlock_bh(&pstapriv->asoc_list_lock);
 988
 989                if (seq == 1) {
 990                        /* TODO: STA re_auth and auth timeout */
 991                }
 992        }
 993
 994        spin_lock_bh(&pstapriv->auth_list_lock);
 995        if (list_empty(&pstat->auth_list)) {
 996
 997                list_add_tail(&pstat->auth_list, &pstapriv->auth_list);
 998                pstapriv->auth_list_cnt++;
 999        }
1000        spin_unlock_bh(&pstapriv->auth_list_lock);
1001
1002        if (pstat->auth_seq == 0)
1003                pstat->expire_to = pstapriv->auth_to;
1004
1005
1006        if ((pstat->auth_seq + 1) != seq) {
1007                DBG_871X("(1)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n",
1008                        seq, pstat->auth_seq+1);
1009                status = _STATS_OUT_OF_AUTH_SEQ_;
1010                goto auth_fail;
1011        }
1012
1013        if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) {
1014                if (seq == 1) {
1015                        pstat->state &= ~WIFI_FW_AUTH_NULL;
1016                        pstat->state |= WIFI_FW_AUTH_SUCCESS;
1017                        pstat->expire_to = pstapriv->assoc_to;
1018                        pstat->authalg = algorithm;
1019                } else {
1020                        DBG_871X("(2)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n",
1021                                seq, pstat->auth_seq+1);
1022                        status = _STATS_OUT_OF_AUTH_SEQ_;
1023                        goto auth_fail;
1024                }
1025        } else { /*  shared system or auto authentication */
1026                if (seq == 1) {
1027                        /* prepare for the challenging txt... */
1028                        memset((void *)pstat->chg_txt, 78, 128);
1029
1030                        pstat->state &= ~WIFI_FW_AUTH_NULL;
1031                        pstat->state |= WIFI_FW_AUTH_STATE;
1032                        pstat->authalg = algorithm;
1033                        pstat->auth_seq = 2;
1034                } else if (seq == 3) {
1035                        /* checking for challenging txt... */
1036                        DBG_871X("checking for challenging txt...\n");
1037
1038                        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len,
1039                                        len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
1040
1041                        if ((p == NULL) || (ie_len <= 0)) {
1042                                DBG_871X("auth rejected because challenge failure!(1)\n");
1043                                status = _STATS_CHALLENGE_FAIL_;
1044                                goto auth_fail;
1045                        }
1046
1047                        if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) {
1048                                pstat->state &= (~WIFI_FW_AUTH_STATE);
1049                                pstat->state |= WIFI_FW_AUTH_SUCCESS;
1050                                /*  challenging txt is correct... */
1051                                pstat->expire_to =  pstapriv->assoc_to;
1052                        } else {
1053                                DBG_871X("auth rejected because challenge failure!\n");
1054                                status = _STATS_CHALLENGE_FAIL_;
1055                                goto auth_fail;
1056                        }
1057                } else {
1058                        DBG_871X("(3)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n",
1059                                seq, pstat->auth_seq+1);
1060                        status = _STATS_OUT_OF_AUTH_SEQ_;
1061                        goto auth_fail;
1062                }
1063        }
1064
1065
1066        /*  Now, we are going to issue_auth... */
1067        pstat->auth_seq = seq + 1;
1068
1069        issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
1070
1071        if (pstat->state & WIFI_FW_AUTH_SUCCESS)
1072                pstat->auth_seq = 0;
1073
1074
1075        return _SUCCESS;
1076
1077auth_fail:
1078
1079        if (pstat)
1080                rtw_free_stainfo(padapter, pstat);
1081
1082        pstat = &stat;
1083        memset((char *)pstat, '\0', sizeof(stat));
1084        pstat->auth_seq = 2;
1085        memcpy(pstat->hwaddr, sa, 6);
1086
1087        issue_auth(padapter, pstat, (unsigned short)status);
1088
1089        return _FAIL;
1090
1091}
1092
1093unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame)
1094{
1095        unsigned int    seq, len, status, algthm, offset;
1096        unsigned char *p;
1097        unsigned int    go2asoc = 0;
1098        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1099        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1100        u8 *pframe = precv_frame->u.hdr.rx_data;
1101        uint pkt_len = precv_frame->u.hdr.len;
1102
1103        DBG_871X("%s\n", __func__);
1104
1105        /* check A1 matches or not */
1106        if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1107                return _SUCCESS;
1108
1109        if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
1110                return _SUCCESS;
1111
1112        offset = (GetPrivacy(pframe)) ? 4 : 0;
1113
1114        algthm  = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
1115        seq     = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
1116        status  = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4));
1117
1118        if (status != 0) {
1119                DBG_871X("clnt auth fail, status: %d\n", status);
1120                if (status == 13) { /*  pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */
1121                        if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
1122                                pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
1123                        else
1124                                pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
1125                        /* pmlmeinfo->reauth_count = 0; */
1126                }
1127
1128                set_link_timer(pmlmeext, 1);
1129                goto authclnt_fail;
1130        }
1131
1132        if (seq == 2) {
1133                if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
1134                         /*  legendary shared system */
1135                        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
1136                                pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
1137
1138                        if (p == NULL) {
1139                                /* DBG_871X("marc: no challenge text?\n"); */
1140                                goto authclnt_fail;
1141                        }
1142
1143                        memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
1144                        pmlmeinfo->auth_seq = 3;
1145                        issue_auth(padapter, NULL, 0);
1146                        set_link_timer(pmlmeext, REAUTH_TO);
1147
1148                        return _SUCCESS;
1149                } else {
1150                        /*  open system */
1151                        go2asoc = 1;
1152                }
1153        } else if (seq == 4) {
1154                if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
1155                        go2asoc = 1;
1156                } else {
1157                        goto authclnt_fail;
1158                }
1159        } else {
1160                /*  this is also illegal */
1161                /* DBG_871X("marc: clnt auth failed due to illegal seq =%x\n", seq); */
1162                goto authclnt_fail;
1163        }
1164
1165        if (go2asoc) {
1166                DBG_871X_LEVEL(_drv_always_, "auth success, start assoc\n");
1167                start_clnt_assoc(padapter);
1168                return _SUCCESS;
1169        }
1170
1171authclnt_fail:
1172
1173        /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */
1174
1175        return _FAIL;
1176
1177}
1178
1179unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame)
1180{
1181        u16 capab_info, listen_interval;
1182        struct rtw_ieee802_11_elems elems;
1183        struct sta_info *pstat;
1184        unsigned char   reassoc, *p, *pos, *wpa_ie;
1185        unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
1186        int             i, ie_len, wpa_ie_len, left;
1187        unsigned char   supportRate[16];
1188        int                                     supportRateNum;
1189        unsigned short          status = _STATS_SUCCESSFUL_;
1190        unsigned short          frame_type, ie_offset = 0;
1191        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1192        struct security_priv *psecuritypriv = &padapter->securitypriv;
1193        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1194        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1195        struct wlan_bssid_ex    *cur = &(pmlmeinfo->network);
1196        struct sta_priv *pstapriv = &padapter->stapriv;
1197        u8 *pframe = precv_frame->u.hdr.rx_data;
1198        uint pkt_len = precv_frame->u.hdr.len;
1199
1200        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1201                return _FAIL;
1202
1203        frame_type = GetFrameSubType(pframe);
1204        if (frame_type == WIFI_ASSOCREQ) {
1205                reassoc = 0;
1206                ie_offset = _ASOCREQ_IE_OFFSET_;
1207        } else { /*  WIFI_REASSOCREQ */
1208                reassoc = 1;
1209                ie_offset = _REASOCREQ_IE_OFFSET_;
1210        }
1211
1212
1213        if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset) {
1214                DBG_871X("handle_assoc(reassoc =%d) - too short payload (len =%lu)"
1215                       "\n", reassoc, (unsigned long)pkt_len);
1216                return _FAIL;
1217        }
1218
1219        pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1220        if (!pstat) {
1221                status = _RSON_CLS2_;
1222                goto asoc_class2_error;
1223        }
1224
1225        capab_info = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN);
1226        /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */
1227        /* listen_interval = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN+2)); */
1228        listen_interval = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN+2);
1229
1230        left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
1231        pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset);
1232
1233
1234        DBG_871X("%s\n", __func__);
1235
1236        /*  check if this stat has been successfully authenticated/assocated */
1237        if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) {
1238                if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) {
1239                        status = _RSON_CLS2_;
1240                        goto asoc_class2_error;
1241                } else {
1242                        pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
1243                        pstat->state |= WIFI_FW_ASSOC_STATE;
1244                }
1245        } else {
1246                pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
1247                pstat->state |= WIFI_FW_ASSOC_STATE;
1248        }
1249
1250
1251        pstat->capability = capab_info;
1252
1253        /* now parse all ieee802_11 ie to point to elems */
1254        if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
1255            !elems.ssid) {
1256                DBG_871X("STA " MAC_FMT " sent invalid association request\n",
1257                       MAC_ARG(pstat->hwaddr));
1258                status = _STATS_FAILURE_;
1259                goto OnAssocReqFail;
1260        }
1261
1262        /*  now we should check all the fields... */
1263        /*  checking SSID */
1264        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
1265                pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1266
1267        if (!p || ie_len == 0) {
1268                /*  broadcast ssid, however it is not allowed in assocreq */
1269                status = _STATS_FAILURE_;
1270                goto OnAssocReqFail;
1271        } else {
1272                /*  check if ssid match */
1273                if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
1274                        status = _STATS_FAILURE_;
1275
1276                if (ie_len != cur->Ssid.SsidLength)
1277                        status = _STATS_FAILURE_;
1278        }
1279
1280        if (status != _STATS_SUCCESSFUL_)
1281                goto OnAssocReqFail;
1282
1283        /*  check if the supported rate is ok */
1284        p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1285        if (p == NULL) {
1286                DBG_871X("Rx a sta assoc-req which supported rate is empty!\n");
1287                /*  use our own rate set as statoin used */
1288                /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */
1289                /* supportRateNum = AP_BSSRATE_LEN; */
1290
1291                status = _STATS_FAILURE_;
1292                goto OnAssocReqFail;
1293        } else {
1294                memcpy(supportRate, p+2, ie_len);
1295                supportRateNum = ie_len;
1296
1297                p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len,
1298                                pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1299                if (p !=  NULL) {
1300
1301                        if (supportRateNum <= sizeof(supportRate)) {
1302                                memcpy(supportRate+supportRateNum, p+2, ie_len);
1303                                supportRateNum += ie_len;
1304                        }
1305                }
1306        }
1307
1308        /* todo: mask supportRate between AP & STA -> move to update raid */
1309        /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */
1310
1311        /* update station supportRate */
1312        pstat->bssratelen = supportRateNum;
1313        memcpy(pstat->bssrateset, supportRate, supportRateNum);
1314        UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
1315
1316        /* check RSN/WPA/WPS */
1317        pstat->dot8021xalg = 0;
1318        pstat->wpa_psk = 0;
1319        pstat->wpa_group_cipher = 0;
1320        pstat->wpa2_group_cipher = 0;
1321        pstat->wpa_pairwise_cipher = 0;
1322        pstat->wpa2_pairwise_cipher = 0;
1323        memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
1324        if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
1325
1326                int group_cipher = 0, pairwise_cipher = 0;
1327
1328                wpa_ie = elems.rsn_ie;
1329                wpa_ie_len = elems.rsn_ie_len;
1330
1331                if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1332                        pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1333                        pstat->wpa_psk |= BIT(1);
1334
1335                        pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;
1336                        pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
1337
1338                        if (!pstat->wpa2_group_cipher)
1339                                status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1340
1341                        if (!pstat->wpa2_pairwise_cipher)
1342                                status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1343                } else {
1344                        status = WLAN_STATUS_INVALID_IE;
1345                }
1346
1347        } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
1348
1349                int group_cipher = 0, pairwise_cipher = 0;
1350
1351                wpa_ie = elems.wpa_ie;
1352                wpa_ie_len = elems.wpa_ie_len;
1353
1354                if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) {
1355                        pstat->dot8021xalg = 1;/* psk,  todo:802.1x */
1356                        pstat->wpa_psk |= BIT(0);
1357
1358                        pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;
1359                        pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
1360
1361                        if (!pstat->wpa_group_cipher)
1362                                status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1363
1364                        if (!pstat->wpa_pairwise_cipher)
1365                                status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1366
1367                } else {
1368                        status = WLAN_STATUS_INVALID_IE;
1369                }
1370
1371        } else {
1372                wpa_ie = NULL;
1373                wpa_ie_len = 0;
1374        }
1375
1376        if (status != _STATS_SUCCESSFUL_)
1377                goto OnAssocReqFail;
1378
1379        pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
1380        if (!wpa_ie) {
1381                if (elems.wps_ie) {
1382                        DBG_871X("STA included WPS IE in "
1383                                   "(Re)Association Request - assume WPS is "
1384                                   "used\n");
1385                        pstat->flags |= WLAN_STA_WPS;
1386                        /* wpabuf_free(sta->wps_ie); */
1387                        /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */
1388                        /*                              elems.wps_ie_len - 4); */
1389                } else {
1390                        DBG_871X("STA did not include WPA/RSN IE "
1391                                   "in (Re)Association Request - possible WPS "
1392                                   "use\n");
1393                        pstat->flags |= WLAN_STA_MAYBE_WPS;
1394                }
1395
1396
1397                /*  AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */
1398                /*  that the selected registrar of AP is _FLASE */
1399                if ((psecuritypriv->wpa_psk > 0)
1400                        && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) {
1401                        if (pmlmepriv->wps_beacon_ie) {
1402                                u8 selected_registrar = 0;
1403
1404                                rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL);
1405
1406                                if (!selected_registrar) {
1407                                        DBG_871X("selected_registrar is false , or AP is not ready to do WPS\n");
1408
1409                                        status = _STATS_UNABLE_HANDLE_STA_;
1410
1411                                        goto OnAssocReqFail;
1412                                }
1413                        }
1414                }
1415
1416        } else {
1417                int copy_len;
1418
1419                if (psecuritypriv->wpa_psk == 0) {
1420                        DBG_871X("STA " MAC_FMT ": WPA/RSN IE in association "
1421                        "request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr));
1422
1423                        status = WLAN_STATUS_INVALID_IE;
1424
1425                        goto OnAssocReqFail;
1426
1427                }
1428
1429                if (elems.wps_ie) {
1430                        DBG_871X("STA included WPS IE in "
1431                                   "(Re)Association Request - WPS is "
1432                                   "used\n");
1433                        pstat->flags |= WLAN_STA_WPS;
1434                        copy_len = 0;
1435                } else {
1436                        copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
1437                }
1438
1439
1440                if (copy_len > 0)
1441                        memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
1442
1443        }
1444
1445
1446        /*  check if there is WMM IE & support WWM-PS */
1447        pstat->flags &= ~WLAN_STA_WME;
1448        pstat->qos_option = 0;
1449        pstat->qos_info = 0;
1450        pstat->has_legacy_ac = true;
1451        pstat->uapsd_vo = 0;
1452        pstat->uapsd_vi = 0;
1453        pstat->uapsd_be = 0;
1454        pstat->uapsd_bk = 0;
1455        if (pmlmepriv->qospriv.qos_option) {
1456                p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
1457                for (;;) {
1458                        p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
1459                        if (p != NULL) {
1460                                if (!memcmp(p+2, WMM_IE, 6)) {
1461
1462                                        pstat->flags |= WLAN_STA_WME;
1463
1464                                        pstat->qos_option = 1;
1465                                        pstat->qos_info = *(p+8);
1466
1467                                        pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
1468
1469                                        if ((pstat->qos_info&0xf) != 0xf)
1470                                                pstat->has_legacy_ac = true;
1471                                        else
1472                                                pstat->has_legacy_ac = false;
1473
1474                                        if (pstat->qos_info&0xf) {
1475                                                if (pstat->qos_info&BIT(0))
1476                                                        pstat->uapsd_vo = BIT(0)|BIT(1);
1477                                                else
1478                                                        pstat->uapsd_vo = 0;
1479
1480                                                if (pstat->qos_info&BIT(1))
1481                                                        pstat->uapsd_vi = BIT(0)|BIT(1);
1482                                                else
1483                                                        pstat->uapsd_vi = 0;
1484
1485                                                if (pstat->qos_info&BIT(2))
1486                                                        pstat->uapsd_bk = BIT(0)|BIT(1);
1487                                                else
1488                                                        pstat->uapsd_bk = 0;
1489
1490                                                if (pstat->qos_info&BIT(3))
1491                                                        pstat->uapsd_be = BIT(0)|BIT(1);
1492                                                else
1493                                                        pstat->uapsd_be = 0;
1494
1495                                        }
1496
1497                                        break;
1498                                }
1499                        } else {
1500                                break;
1501                        }
1502                        p = p + ie_len + 2;
1503                }
1504        }
1505
1506        /* save HT capabilities in the sta object */
1507        memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
1508        if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) {
1509                pstat->flags |= WLAN_STA_HT;
1510
1511                pstat->flags |= WLAN_STA_WME;
1512
1513                memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));
1514
1515        } else
1516                pstat->flags &= ~WLAN_STA_HT;
1517
1518
1519        if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT)) {
1520                status = _STATS_FAILURE_;
1521                goto OnAssocReqFail;
1522        }
1523
1524
1525        if ((pstat->flags & WLAN_STA_HT) &&
1526                    ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
1527                      (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) {
1528                DBG_871X("HT: " MAC_FMT " tried to "
1529                                   "use TKIP with HT association\n", MAC_ARG(pstat->hwaddr));
1530
1531                /* status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; */
1532                /* goto OnAssocReqFail; */
1533        }
1534        pstat->flags |= WLAN_STA_NONERP;
1535        for (i = 0; i < pstat->bssratelen; i++) {
1536                if ((pstat->bssrateset[i] & 0x7f) > 22) {
1537                        pstat->flags &= ~WLAN_STA_NONERP;
1538                        break;
1539                }
1540        }
1541
1542        if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1543                pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
1544        else
1545                pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
1546
1547
1548
1549        if (status != _STATS_SUCCESSFUL_)
1550                goto OnAssocReqFail;
1551
1552        /* TODO: identify_proprietary_vendor_ie(); */
1553        /*  Realtek proprietary IE */
1554        /*  identify if this is Broadcom sta */
1555        /*  identify if this is ralink sta */
1556        /*  Customer proprietary IE */
1557
1558
1559
1560        /* get a unique AID */
1561        if (pstat->aid > 0) {
1562                DBG_871X("  old AID %d\n", pstat->aid);
1563        } else {
1564                for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++)
1565                        if (pstapriv->sta_aid[pstat->aid - 1] == NULL)
1566                                break;
1567
1568                /* if (pstat->aid > NUM_STA) { */
1569                if (pstat->aid > pstapriv->max_num_sta) {
1570
1571                        pstat->aid = 0;
1572
1573                        DBG_871X("  no room for more AIDs\n");
1574
1575                        status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1576
1577                        goto OnAssocReqFail;
1578
1579
1580                } else {
1581                        pstapriv->sta_aid[pstat->aid - 1] = pstat;
1582                        DBG_871X("allocate new AID = (%d)\n", pstat->aid);
1583                }
1584        }
1585
1586
1587        pstat->state &= (~WIFI_FW_ASSOC_STATE);
1588        pstat->state |= WIFI_FW_ASSOC_SUCCESS;
1589
1590        spin_lock_bh(&pstapriv->auth_list_lock);
1591        if (!list_empty(&pstat->auth_list)) {
1592                list_del_init(&pstat->auth_list);
1593                pstapriv->auth_list_cnt--;
1594        }
1595        spin_unlock_bh(&pstapriv->auth_list_lock);
1596
1597        spin_lock_bh(&pstapriv->asoc_list_lock);
1598        if (list_empty(&pstat->asoc_list)) {
1599                pstat->expire_to = pstapriv->expire_to;
1600                list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list);
1601                pstapriv->asoc_list_cnt++;
1602        }
1603        spin_unlock_bh(&pstapriv->asoc_list_lock);
1604
1605        /*  now the station is qualified to join our BSS... */
1606        if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
1607                /* 1 bss_cap_update & sta_info_update */
1608                bss_cap_update_on_sta_join(padapter, pstat);
1609                sta_info_update(padapter, pstat);
1610
1611                /* 2 issue assoc rsp before notify station join event. */
1612                if (frame_type == WIFI_ASSOCREQ)
1613                        issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1614                else
1615                        issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1616
1617                spin_lock_bh(&pstat->lock);
1618                if (pstat->passoc_req) {
1619                        kfree(pstat->passoc_req);
1620                        pstat->passoc_req = NULL;
1621                        pstat->assoc_req_len = 0;
1622                }
1623
1624                pstat->passoc_req =  rtw_zmalloc(pkt_len);
1625                if (pstat->passoc_req) {
1626                        memcpy(pstat->passoc_req, pframe, pkt_len);
1627                        pstat->assoc_req_len = pkt_len;
1628                }
1629                spin_unlock_bh(&pstat->lock);
1630
1631                /* 3-(1) report sta add event */
1632                report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
1633        }
1634
1635        return _SUCCESS;
1636
1637asoc_class2_error:
1638
1639        issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
1640
1641        return _FAIL;
1642
1643OnAssocReqFail:
1644
1645        pstat->aid = 0;
1646        if (frame_type == WIFI_ASSOCREQ)
1647                issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
1648        else
1649                issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
1650
1651        return _FAIL;
1652}
1653
1654unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame)
1655{
1656        uint i;
1657        int res;
1658        unsigned short  status;
1659        struct ndis_80211_var_ie *pIE;
1660        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1661        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1662        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1663        /* struct wlan_bssid_ex                 *cur_network = &(pmlmeinfo->network); */
1664        u8 *pframe = precv_frame->u.hdr.rx_data;
1665        uint pkt_len = precv_frame->u.hdr.len;
1666
1667        DBG_871X("%s\n", __func__);
1668
1669        /* check A1 matches or not */
1670        if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN))
1671                return _SUCCESS;
1672
1673        if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
1674                return _SUCCESS;
1675
1676        if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
1677                return _SUCCESS;
1678
1679        del_timer_sync(&pmlmeext->link_timer);
1680
1681        /* status */
1682        status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2));
1683        if (status > 0) {
1684                DBG_871X("assoc reject, status code: %d\n", status);
1685                pmlmeinfo->state = WIFI_FW_NULL_STATE;
1686                res = -4;
1687                goto report_assoc_result;
1688        }
1689
1690        /* get capabilities */
1691        pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1692
1693        /* set slot time */
1694        pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20;
1695
1696        /* AID */
1697        res = pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
1698
1699        /* following are moved to join event callback function */
1700        /* to handle HT, WMM, rate adaptive, update MAC reg */
1701        /* for not to handle the synchronous IO in the tasklet */
1702        for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) {
1703                pIE = (struct ndis_80211_var_ie *)(pframe + i);
1704
1705                switch (pIE->ElementID) {
1706                case _VENDOR_SPECIFIC_IE_:
1707                        if (!memcmp(pIE->data, WMM_PARA_OUI, 6))        /* WMM */
1708                                WMM_param_handler(padapter, pIE);
1709                        break;
1710
1711                case _HT_CAPABILITY_IE_:        /* HT caps */
1712                        HT_caps_handler(padapter, pIE);
1713                        break;
1714
1715                case _HT_EXTRA_INFO_IE_:        /* HT info */
1716                        HT_info_handler(padapter, pIE);
1717                        break;
1718
1719                case _ERPINFO_IE_:
1720                        ERP_IE_handler(padapter, pIE);
1721
1722                default:
1723                        break;
1724                }
1725
1726                i += (pIE->Length + 2);
1727        }
1728
1729        pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
1730        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
1731
1732        /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */
1733        UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
1734
1735report_assoc_result:
1736        if (res > 0) {
1737                rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
1738        } else {
1739                rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
1740        }
1741
1742        report_join_res(padapter, res);
1743
1744        return _SUCCESS;
1745}
1746
1747unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame)
1748{
1749        unsigned short  reason;
1750        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1751        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1752        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1753        u8 *pframe = precv_frame->u.hdr.rx_data;
1754
1755        /* check A3 */
1756        if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1757                return _SUCCESS;
1758
1759        reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1760
1761        DBG_871X("%s Reason code(%d)\n", __func__, reason);
1762
1763        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1764                struct sta_info *psta;
1765                struct sta_priv *pstapriv = &padapter->stapriv;
1766
1767                /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
1768                /* rtw_free_stainfo(padapter, psta); */
1769                /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
1770
1771                DBG_871X_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n",
1772                                reason, GetAddr2Ptr(pframe));
1773
1774                psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1775                if (psta) {
1776                        u8 updated = false;
1777
1778                        spin_lock_bh(&pstapriv->asoc_list_lock);
1779                        if (list_empty(&psta->asoc_list) == false) {
1780                                list_del_init(&psta->asoc_list);
1781                                pstapriv->asoc_list_cnt--;
1782                                updated = ap_free_sta(padapter, psta, false, reason);
1783
1784                        }
1785                        spin_unlock_bh(&pstapriv->asoc_list_lock);
1786
1787                        associated_clients_update(padapter, updated);
1788                }
1789
1790
1791                return _SUCCESS;
1792        } else {
1793                int     ignore_received_deauth = 0;
1794
1795                /*      Commented by Albert 20130604 */
1796                /*      Before sending the auth frame to start the STA/GC mode connection with AP/GO, */
1797                /*      we will send the deauth first. */
1798                /*      However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */
1799                /*      Added the following code to avoid this case. */
1800                if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) ||
1801                        (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) {
1802                        if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) {
1803                                ignore_received_deauth = 1;
1804                        } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) {
1805                                /*  TODO: 802.11r */
1806                                ignore_received_deauth = 1;
1807                        }
1808                }
1809
1810                DBG_871X_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n",
1811                                reason, GetAddr3Ptr(pframe), ignore_received_deauth);
1812
1813                if (0 == ignore_received_deauth) {
1814                        receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1815                }
1816        }
1817        pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1818        return _SUCCESS;
1819
1820}
1821
1822unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame)
1823{
1824        unsigned short  reason;
1825        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1826        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1827        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1828        u8 *pframe = precv_frame->u.hdr.rx_data;
1829
1830        /* check A3 */
1831        if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
1832                return _SUCCESS;
1833
1834        reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN));
1835
1836        DBG_871X("%s Reason code(%d)\n", __func__, reason);
1837
1838        if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1839                struct sta_info *psta;
1840                struct sta_priv *pstapriv = &padapter->stapriv;
1841
1842                /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */
1843                /* rtw_free_stainfo(padapter, psta); */
1844                /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */
1845
1846                DBG_871X_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n",
1847                                reason, GetAddr2Ptr(pframe));
1848
1849                psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1850                if (psta) {
1851                        u8 updated = false;
1852
1853                        spin_lock_bh(&pstapriv->asoc_list_lock);
1854                        if (list_empty(&psta->asoc_list) == false) {
1855                                list_del_init(&psta->asoc_list);
1856                                pstapriv->asoc_list_cnt--;
1857                                updated = ap_free_sta(padapter, psta, false, reason);
1858
1859                        }
1860                        spin_unlock_bh(&pstapriv->asoc_list_lock);
1861
1862                        associated_clients_update(padapter, updated);
1863                }
1864
1865                return _SUCCESS;
1866        } else {
1867                DBG_871X_LEVEL(_drv_always_, "sta recv disassoc reason code(%d) sta:%pM\n",
1868                                reason, GetAddr3Ptr(pframe));
1869
1870                receive_disconnect(padapter, GetAddr3Ptr(pframe), reason);
1871        }
1872        pmlmepriv->LinkDetectInfo.bBusyTraffic = false;
1873        return _SUCCESS;
1874
1875}
1876
1877unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame)
1878{
1879        DBG_871X("%s\n", __func__);
1880        return _SUCCESS;
1881}
1882
1883unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame)
1884{
1885        unsigned int ret = _FAIL;
1886        struct sta_info *psta = NULL;
1887        struct sta_priv *pstapriv = &padapter->stapriv;
1888        u8 *pframe = precv_frame->u.hdr.rx_data;
1889        u8 *frame_body = (u8 *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1890        u8 category;
1891        u8 action;
1892
1893        DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
1894
1895        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1896
1897        if (!psta)
1898                goto exit;
1899
1900        category = frame_body[0];
1901        if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
1902                goto exit;
1903
1904        action = frame_body[1];
1905        switch (action) {
1906        case RTW_WLAN_ACTION_SPCT_MSR_REQ:
1907        case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
1908        case RTW_WLAN_ACTION_SPCT_TPC_REQ:
1909        case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
1910        case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
1911                break;
1912        default:
1913                break;
1914        }
1915
1916exit:
1917        return ret;
1918}
1919
1920unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame)
1921{
1922        u8 *addr;
1923        struct sta_info *psta = NULL;
1924        struct recv_reorder_ctrl *preorder_ctrl;
1925        unsigned char   *frame_body;
1926        unsigned char   category, action;
1927        unsigned short  tid, status, reason_code = 0;
1928        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1929        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1930        u8 *pframe = precv_frame->u.hdr.rx_data;
1931        struct sta_priv *pstapriv = &padapter->stapriv;
1932
1933        DBG_871X("%s\n", __func__);
1934
1935        /* check RA matches or not */
1936        if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */
1937                return _SUCCESS;
1938
1939        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
1940                if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
1941                        return _SUCCESS;
1942
1943        addr = GetAddr2Ptr(pframe);
1944        psta = rtw_get_stainfo(pstapriv, addr);
1945
1946        if (!psta)
1947                return _SUCCESS;
1948
1949        frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
1950
1951        category = frame_body[0];
1952        if (category == RTW_WLAN_CATEGORY_BACK) {/*  representing Block Ack */
1953                if (!pmlmeinfo->HT_enable)
1954                        return _SUCCESS;
1955
1956                action = frame_body[1];
1957                DBG_871X("%s, action =%d\n", __func__, action);
1958                switch (action) {
1959                case RTW_WLAN_ACTION_ADDBA_REQ: /* ADDBA request */
1960
1961                        memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
1962                        /* process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */
1963                        process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr);
1964
1965                        if (pmlmeinfo->accept_addba_req) {
1966                                issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 0);
1967                        } else {
1968                                issue_action_BA(padapter, addr, RTW_WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */
1969                        }
1970
1971                        break;
1972
1973                case RTW_WLAN_ACTION_ADDBA_RESP: /* ADDBA response */
1974                        status = RTW_GET_LE16(&frame_body[3]);
1975                        tid = ((frame_body[5] >> 2) & 0x7);
1976
1977                        if (status == 0) {
1978                                /* successful */
1979                                DBG_871X("agg_enable for TID =%d\n", tid);
1980                                psta->htpriv.agg_enable_bitmap |= BIT(tid);
1981                                psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
1982                        } else {
1983                                psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1984                        }
1985
1986                        if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
1987                                DBG_871X("%s alive check - rx ADDBA response\n", __func__);
1988                                psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
1989                                psta->expire_to = pstapriv->expire_to;
1990                                psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
1991                        }
1992
1993                        /* DBG_871X("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap); */
1994                        break;
1995
1996                case RTW_WLAN_ACTION_DELBA: /* DELBA */
1997                        if ((frame_body[3] & BIT(3)) == 0) {
1998                                psta->htpriv.agg_enable_bitmap &=
1999                                        ~BIT((frame_body[3] >> 4) & 0xf);
2000                                psta->htpriv.candidate_tid_bitmap &=
2001                                        ~BIT((frame_body[3] >> 4) & 0xf);
2002
2003                                /* reason_code = frame_body[4] | (frame_body[5] << 8); */
2004                                reason_code = RTW_GET_LE16(&frame_body[4]);
2005                        } else if ((frame_body[3] & BIT(3)) == BIT(3)) {
2006                                tid = (frame_body[3] >> 4) & 0x0F;
2007
2008                                preorder_ctrl =  &psta->recvreorder_ctrl[tid];
2009                                preorder_ctrl->enable = false;
2010                                preorder_ctrl->indicate_seq = 0xffff;
2011                                #ifdef DBG_RX_SEQ
2012                                DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__,
2013                                        preorder_ctrl->indicate_seq);
2014                                #endif
2015                        }
2016
2017                        DBG_871X("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code);
2018                        /* todo: how to notify the host while receiving DELETE BA */
2019                        break;
2020
2021                default:
2022                        break;
2023                }
2024        }
2025        return _SUCCESS;
2026}
2027
2028static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token)
2029{
2030        struct adapter *adapter = recv_frame->u.hdr.adapter;
2031        struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
2032        u8 *frame = recv_frame->u.hdr.rx_data;
2033        u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
2034                (recv_frame->u.hdr.attrib.frag_num & 0xf);
2035
2036        if (GetRetry(frame)) {
2037                if (token >= 0) {
2038                        if ((seq_ctrl == mlmeext->action_public_rxseq)
2039                                && (token == mlmeext->action_public_dialog_token)) {
2040                                DBG_871X(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n",
2041                                        FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
2042                                return _FAIL;
2043                        }
2044                } else {
2045                        if (seq_ctrl == mlmeext->action_public_rxseq) {
2046                                DBG_871X(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n",
2047                                        FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq);
2048                                return _FAIL;
2049                        }
2050                }
2051        }
2052
2053        mlmeext->action_public_rxseq = seq_ctrl;
2054
2055        if (token >= 0)
2056                mlmeext->action_public_dialog_token = token;
2057
2058        return _SUCCESS;
2059}
2060
2061static unsigned int on_action_public_p2p(union recv_frame *precv_frame)
2062{
2063        u8 *pframe = precv_frame->u.hdr.rx_data;
2064        u8 *frame_body;
2065        u8 dialogToken = 0;
2066
2067        frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
2068
2069        dialogToken = frame_body[7];
2070
2071        if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL)
2072                return _FAIL;
2073
2074        return _SUCCESS;
2075}
2076
2077static unsigned int on_action_public_vendor(union recv_frame *precv_frame)
2078{
2079        unsigned int ret = _FAIL;
2080        u8 *pframe = precv_frame->u.hdr.rx_data;
2081        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2082
2083        if (!memcmp(frame_body + 2, P2P_OUI, 4)) {
2084                ret = on_action_public_p2p(precv_frame);
2085        }
2086
2087        return ret;
2088}
2089
2090static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
2091{
2092        unsigned int ret = _FAIL;
2093        u8 *pframe = precv_frame->u.hdr.rx_data;
2094        uint frame_len = precv_frame->u.hdr.len;
2095        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2096        u8 token;
2097        struct adapter *adapter = precv_frame->u.hdr.adapter;
2098        int cnt = 0;
2099        char msg[64];
2100
2101        token = frame_body[2];
2102
2103        if (rtw_action_public_decache(precv_frame, token) == _FAIL)
2104                goto exit;
2105
2106        cnt += sprintf((msg+cnt), "%s(token:%u)", action_public_str(action), token);
2107        rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
2108
2109        ret = _SUCCESS;
2110
2111exit:
2112        return ret;
2113}
2114
2115unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame)
2116{
2117        unsigned int ret = _FAIL;
2118        u8 *pframe = precv_frame->u.hdr.rx_data;
2119        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2120        u8 category, action;
2121
2122        /* check RA matches or not */
2123        if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
2124                goto exit;
2125
2126        category = frame_body[0];
2127        if (category != RTW_WLAN_CATEGORY_PUBLIC)
2128                goto exit;
2129
2130        action = frame_body[1];
2131        switch (action) {
2132        case ACT_PUBLIC_VENDOR:
2133                ret = on_action_public_vendor(precv_frame);
2134                break;
2135        default:
2136                ret = on_action_public_default(precv_frame, action);
2137                break;
2138        }
2139
2140exit:
2141        return ret;
2142}
2143
2144unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame)
2145{
2146        u8 *pframe = precv_frame->u.hdr.rx_data;
2147        u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr);
2148        u8 category, action;
2149
2150        /* check RA matches or not */
2151        if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))
2152                goto exit;
2153
2154        category = frame_body[0];
2155        if (category != RTW_WLAN_CATEGORY_HT)
2156                goto exit;
2157
2158        action = frame_body[1];
2159        switch (action) {
2160        case RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING:
2161                break;
2162        default:
2163                break;
2164        }
2165
2166exit:
2167
2168        return _SUCCESS;
2169}
2170
2171unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv_frame)
2172{
2173        u8 *pframe = precv_frame->u.hdr.rx_data;
2174        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
2175        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2176        unsigned short tid;
2177        /* Baron */
2178
2179        DBG_871X("OnAction_sa_query\n");
2180
2181        switch (pframe[WLAN_HDR_A3_LEN+1]) {
2182        case 0: /* SA Query req */
2183                memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short));
2184                DBG_871X("OnAction_sa_query request, action =%d, tid =%04x\n", pframe[WLAN_HDR_A3_LEN+1], tid);
2185                issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid);
2186                break;
2187
2188        case 1: /* SA Query rsp */
2189                del_timer_sync(&pmlmeext->sa_query_timer);
2190                DBG_871X("OnAction_sa_query response, action =%d, tid =%04x, cancel timer\n", pframe[WLAN_HDR_A3_LEN+1], pframe[WLAN_HDR_A3_LEN+2]);
2191                break;
2192        default:
2193                break;
2194        }
2195        if (0) {
2196                int pp;
2197                printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
2198                for (pp = 0; pp < pattrib->pkt_len; pp++)
2199                        printk(" %02x ", pframe[pp]);
2200                printk("\n");
2201        }
2202
2203        return _SUCCESS;
2204}
2205
2206unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame)
2207{
2208        int i;
2209        unsigned char category;
2210        struct action_handler *ptable;
2211        unsigned char *frame_body;
2212        u8 *pframe = precv_frame->u.hdr.rx_data;
2213
2214        frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr));
2215
2216        category = frame_body[0];
2217
2218        for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) {
2219                ptable = &OnAction_tbl[i];
2220
2221                if (category == ptable->num)
2222                        ptable->func(padapter, precv_frame);
2223
2224        }
2225
2226        return _SUCCESS;
2227
2228}
2229
2230unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame)
2231{
2232
2233        /* DBG_871X("rcvd mgt frame(%x, %x)\n", (GetFrameSubType(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe)); */
2234        return _SUCCESS;
2235}
2236
2237static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
2238{
2239        struct xmit_frame *pmgntframe;
2240        struct xmit_buf *pxmitbuf;
2241
2242        if (once)
2243                pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
2244        else
2245                pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
2246
2247        if (pmgntframe == NULL) {
2248                DBG_871X(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once);
2249                goto exit;
2250        }
2251
2252        pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv);
2253        if (pxmitbuf == NULL) {
2254                DBG_871X(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter));
2255                rtw_free_xmitframe(pxmitpriv, pmgntframe);
2256                pmgntframe = NULL;
2257                goto exit;
2258        }
2259
2260        pmgntframe->frame_tag = MGNT_FRAMETAG;
2261        pmgntframe->pxmitbuf = pxmitbuf;
2262        pmgntframe->buf_addr = pxmitbuf->pbuf;
2263        pxmitbuf->priv_data = pmgntframe;
2264
2265exit:
2266        return pmgntframe;
2267
2268}
2269
2270inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
2271{
2272        return _alloc_mgtxmitframe(pxmitpriv, false);
2273}
2274
2275/****************************************************************************
2276
2277Following are some TX fuctions for WiFi MLME
2278
2279*****************************************************************************/
2280
2281void update_mgnt_tx_rate(struct adapter *padapter, u8 rate)
2282{
2283        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2284
2285        pmlmeext->tx_rate = rate;
2286        /* DBG_871X("%s(): rate = %x\n", __func__, rate); */
2287}
2288
2289void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib)
2290{
2291        u8 wireless_mode;
2292        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2293
2294        /* memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */
2295
2296        pattrib->hdrlen = 24;
2297        pattrib->nr_frags = 1;
2298        pattrib->priority = 7;
2299        pattrib->mac_id = 0;
2300        pattrib->qsel = 0x12;
2301
2302        pattrib->pktlen = 0;
2303
2304        if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
2305                wireless_mode = WIRELESS_11B;
2306        else
2307                wireless_mode = WIRELESS_11G;
2308        pattrib->raid =  rtw_get_mgntframe_raid(padapter, wireless_mode);
2309        pattrib->rate = pmlmeext->tx_rate;
2310
2311        pattrib->encrypt = _NO_PRIVACY_;
2312        pattrib->bswenc = false;
2313
2314        pattrib->qos_en = false;
2315        pattrib->ht_en = false;
2316        pattrib->bwmode = CHANNEL_WIDTH_20;
2317        pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2318        pattrib->sgi = false;
2319
2320        pattrib->seqnum = pmlmeext->mgnt_seq;
2321
2322        pattrib->retry_ctrl = true;
2323
2324        pattrib->mbssid = 0;
2325
2326}
2327
2328void update_mgntframe_attrib_addr(struct adapter *padapter, struct xmit_frame *pmgntframe)
2329{
2330        u8 *pframe;
2331        struct pkt_attrib       *pattrib = &pmgntframe->attrib;
2332
2333        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2334
2335        memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);
2336        memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN);
2337}
2338
2339void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe)
2340{
2341        if (padapter->bSurpriseRemoved ||
2342                padapter->bDriverStopped) {
2343                rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2344                rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2345                return;
2346        }
2347
2348        rtw_hal_mgnt_xmit(padapter, pmgntframe);
2349}
2350
2351s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
2352{
2353        s32 ret = _FAIL;
2354        _irqL irqL;
2355        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2356        struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
2357        struct submit_ctx sctx;
2358
2359        if (padapter->bSurpriseRemoved ||
2360                padapter->bDriverStopped) {
2361                rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2362                rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2363                return ret;
2364        }
2365
2366        rtw_sctx_init(&sctx, timeout_ms);
2367        pxmitbuf->sctx = &sctx;
2368
2369        ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
2370
2371        if (ret == _SUCCESS)
2372                ret = rtw_sctx_wait(&sctx, __func__);
2373
2374        spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL);
2375        pxmitbuf->sctx = NULL;
2376        spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL);
2377
2378        return ret;
2379}
2380
2381s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe)
2382{
2383        static u8 seq_no;
2384        s32 ret = _FAIL;
2385        u32 timeout_ms = 500;/*   500ms */
2386        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2387
2388        if (padapter->bSurpriseRemoved ||
2389                padapter->bDriverStopped) {
2390                rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
2391                rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
2392                return -1;
2393        }
2394
2395        if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex) == 0) {
2396                pxmitpriv->ack_tx = true;
2397                pxmitpriv->seq_no = seq_no++;
2398                pmgntframe->ack_report = 1;
2399                if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS)
2400                        ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms);
2401
2402                pxmitpriv->ack_tx = false;
2403                mutex_unlock(&pxmitpriv->ack_tx_mutex);
2404        }
2405
2406        return ret;
2407}
2408
2409static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
2410{
2411        u8 *ssid_ie;
2412        sint ssid_len_ori;
2413        int len_diff = 0;
2414
2415        ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
2416
2417        /* DBG_871X("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */
2418
2419        if (ssid_ie && ssid_len_ori > 0) {
2420                switch (hidden_ssid_mode) {
2421                case 1:
2422                {
2423                        u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
2424                        u32 remain_len = 0;
2425
2426                        remain_len = ies_len - (next_ie-ies);
2427
2428                        ssid_ie[1] = 0;
2429                        memcpy(ssid_ie+2, next_ie, remain_len);
2430                        len_diff -= ssid_len_ori;
2431
2432                        break;
2433                }
2434                case 2:
2435                        memset(&ssid_ie[2], 0, ssid_len_ori);
2436                        break;
2437                default:
2438                        break;
2439        }
2440        }
2441
2442        return len_diff;
2443}
2444
2445void issue_beacon(struct adapter *padapter, int timeout_ms)
2446{
2447        struct xmit_frame       *pmgntframe;
2448        struct pkt_attrib       *pattrib;
2449        unsigned char *pframe;
2450        struct ieee80211_hdr *pwlanhdr;
2451        __le16 *fctrl;
2452        unsigned int    rate_len;
2453        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2454        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2455        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2456        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2457        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
2458        u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2459
2460        /* DBG_871X("%s\n", __func__); */
2461
2462        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2463        if (!pmgntframe) {
2464                DBG_871X("%s, alloc mgnt frame fail\n", __func__);
2465                return;
2466        }
2467
2468        spin_lock_bh(&pmlmepriv->bcn_update_lock);
2469
2470        /* update attribute */
2471        pattrib = &pmgntframe->attrib;
2472        update_mgntframe_attrib(padapter, pattrib);
2473        pattrib->qsel = 0x10;
2474
2475        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2476
2477        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2478        pwlanhdr = (struct ieee80211_hdr *)pframe;
2479
2480
2481        fctrl = &(pwlanhdr->frame_control);
2482        *(fctrl) = 0;
2483
2484        memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
2485        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
2486        memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
2487
2488        SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
2489        /* pmlmeext->mgnt_seq++; */
2490        SetFrameSubType(pframe, WIFI_BEACON);
2491
2492        pframe += sizeof(struct ieee80211_hdr_3addr);
2493        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2494
2495        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2496                /* DBG_871X("ie len =%d\n", cur_network->IELength); */
2497                {
2498                        int len_diff;
2499                        memcpy(pframe, cur_network->IEs, cur_network->IELength);
2500                        len_diff = update_hidden_ssid(
2501                                pframe+_BEACON_IE_OFFSET_
2502                                , cur_network->IELength-_BEACON_IE_OFFSET_
2503                                , pmlmeinfo->hidden_ssid_mode
2504                        );
2505                        pframe += (cur_network->IELength+len_diff);
2506                        pattrib->pktlen += (cur_network->IELength+len_diff);
2507                }
2508
2509                {
2510                        u8 *wps_ie;
2511                        uint wps_ielen;
2512                        u8 sr = 0;
2513                        wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
2514                                pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
2515                        if (wps_ie && wps_ielen > 0) {
2516                                rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL);
2517                        }
2518                        if (sr != 0)
2519                                set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
2520                        else
2521                                _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
2522                }
2523
2524                goto _issue_bcn;
2525
2526        }
2527
2528        /* below for ad-hoc mode */
2529
2530        /* timestamp will be inserted by hardware */
2531        pframe += 8;
2532        pattrib->pktlen += 8;
2533
2534        /*  beacon interval: 2 bytes */
2535
2536        memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
2537
2538        pframe += 2;
2539        pattrib->pktlen += 2;
2540
2541        /*  capability info: 2 bytes */
2542
2543        memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
2544
2545        pframe += 2;
2546        pattrib->pktlen += 2;
2547
2548        /*  SSID */
2549        pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
2550
2551        /*  supported rates... */
2552        rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
2553        pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
2554
2555        /*  DS parameter set */
2556        pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
2557
2558        /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */
2559        {
2560                u8 erpinfo = 0;
2561                u32 ATIMWindow;
2562                /*  IBSS Parameter Set... */
2563                /* ATIMWindow = cur->Configuration.ATIMWindow; */
2564                ATIMWindow = 0;
2565                pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
2566
2567                /* ERP IE */
2568                pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
2569        }
2570
2571
2572        /*  EXTERNDED SUPPORTED RATE */
2573        if (rate_len > 8) {
2574                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
2575        }
2576
2577
2578        /* todo:HT for adhoc */
2579
2580_issue_bcn:
2581
2582        pmlmepriv->update_bcn = false;
2583
2584        spin_unlock_bh(&pmlmepriv->bcn_update_lock);
2585
2586        if ((pattrib->pktlen + TXDESC_SIZE) > 512) {
2587                DBG_871X("beacon frame too large\n");
2588                return;
2589        }
2590
2591        pattrib->last_txcmdsz = pattrib->pktlen;
2592
2593        /* DBG_871X("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */
2594        if (timeout_ms > 0)
2595                dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
2596        else
2597                dump_mgntframe(padapter, pmgntframe);
2598
2599}
2600
2601void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
2602{
2603        struct xmit_frame                       *pmgntframe;
2604        struct pkt_attrib                       *pattrib;
2605        unsigned char                           *pframe;
2606        struct ieee80211_hdr    *pwlanhdr;
2607        __le16 *fctrl;
2608        unsigned char                           *mac, *bssid;
2609        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
2610
2611        u8 *pwps_ie;
2612        uint wps_ielen;
2613        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2614        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2615        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2616        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
2617        unsigned int    rate_len;
2618
2619        /* DBG_871X("%s\n", __func__); */
2620
2621        if (da == NULL)
2622                return;
2623
2624        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2625        if (pmgntframe == NULL) {
2626                DBG_871X("%s, alloc mgnt frame fail\n", __func__);
2627                return;
2628        }
2629
2630
2631        /* update attribute */
2632        pattrib = &pmgntframe->attrib;
2633        update_mgntframe_attrib(padapter, pattrib);
2634
2635        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2636
2637        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2638        pwlanhdr = (struct ieee80211_hdr *)pframe;
2639
2640        mac = myid(&(padapter->eeprompriv));
2641        bssid = cur_network->MacAddress;
2642
2643        fctrl = &(pwlanhdr->frame_control);
2644        *(fctrl) = 0;
2645        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
2646        memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
2647        memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
2648
2649        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2650        pmlmeext->mgnt_seq++;
2651        SetFrameSubType(fctrl, WIFI_PROBERSP);
2652
2653        pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
2654        pattrib->pktlen = pattrib->hdrlen;
2655        pframe += pattrib->hdrlen;
2656
2657
2658        if (cur_network->IELength > MAX_IE_SZ)
2659                return;
2660
2661        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
2662                pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
2663
2664                /* inerset & update wps_probe_resp_ie */
2665                if ((pmlmepriv->wps_probe_resp_ie != NULL) && pwps_ie && (wps_ielen > 0)) {
2666                        uint wps_offset, remainder_ielen;
2667                        u8 *premainder_ie;
2668
2669                        wps_offset = (uint)(pwps_ie - cur_network->IEs);
2670
2671                        premainder_ie = pwps_ie + wps_ielen;
2672
2673                        remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
2674
2675                        memcpy(pframe, cur_network->IEs, wps_offset);
2676                        pframe += wps_offset;
2677                        pattrib->pktlen += wps_offset;
2678
2679                        wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */
2680                        if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) {
2681                                memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
2682                                pframe += wps_ielen+2;
2683                                pattrib->pktlen += wps_ielen+2;
2684                        }
2685
2686                        if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) {
2687                                memcpy(pframe, premainder_ie, remainder_ielen);
2688                                pframe += remainder_ielen;
2689                                pattrib->pktlen += remainder_ielen;
2690                        }
2691                } else {
2692                        memcpy(pframe, cur_network->IEs, cur_network->IELength);
2693                        pframe += cur_network->IELength;
2694                        pattrib->pktlen += cur_network->IELength;
2695                }
2696
2697                /* retrieve SSID IE from cur_network->Ssid */
2698                {
2699                        u8 *ssid_ie;
2700                        sint ssid_ielen;
2701                        sint ssid_ielen_diff;
2702                        u8 buf[MAX_IE_SZ];
2703                        u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr);
2704
2705                        ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
2706                                (pframe-ies)-_FIXED_IE_LENGTH_);
2707
2708                        ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
2709
2710                        if (ssid_ie &&  cur_network->Ssid.SsidLength) {
2711                                uint remainder_ielen;
2712                                u8 *remainder_ie;
2713                                remainder_ie = ssid_ie+2;
2714                                remainder_ielen = (pframe-remainder_ie);
2715
2716                                if (remainder_ielen > MAX_IE_SZ) {
2717                                        DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));
2718                                        remainder_ielen = MAX_IE_SZ;
2719                                }
2720
2721                                memcpy(buf, remainder_ie, remainder_ielen);
2722                                memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
2723                                *(ssid_ie+1) = cur_network->Ssid.SsidLength;
2724                                memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
2725
2726                                pframe += ssid_ielen_diff;
2727                                pattrib->pktlen += ssid_ielen_diff;
2728                        }
2729                }
2730        } else {
2731                /* timestamp will be inserted by hardware */
2732                pframe += 8;
2733                pattrib->pktlen += 8;
2734
2735                /*  beacon interval: 2 bytes */
2736
2737                memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2);
2738
2739                pframe += 2;
2740                pattrib->pktlen += 2;
2741
2742                /*  capability info: 2 bytes */
2743
2744                memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
2745
2746                pframe += 2;
2747                pattrib->pktlen += 2;
2748
2749                /* below for ad-hoc mode */
2750
2751                /*  SSID */
2752                pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
2753
2754                /*  supported rates... */
2755                rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
2756                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen);
2757
2758                /*  DS parameter set */
2759                pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
2760
2761                if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
2762                        u8 erpinfo = 0;
2763                        u32 ATIMWindow;
2764                        /*  IBSS Parameter Set... */
2765                        /* ATIMWindow = cur->Configuration.ATIMWindow; */
2766                        ATIMWindow = 0;
2767                        pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
2768
2769                        /* ERP IE */
2770                        pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
2771                }
2772
2773
2774                /*  EXTERNDED SUPPORTED RATE */
2775                if (rate_len > 8) {
2776                        pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
2777                }
2778
2779
2780                /* todo:HT for adhoc */
2781
2782        }
2783
2784#ifdef CONFIG_AUTO_AP_MODE
2785{
2786        struct sta_info *psta;
2787        struct sta_priv *pstapriv = &padapter->stapriv;
2788
2789        DBG_871X("(%s)\n", __func__);
2790
2791        /* check rc station */
2792        psta = rtw_get_stainfo(pstapriv, da);
2793        if (psta && psta->isrc && psta->pid > 0) {
2794                u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A};
2795                u8 RC_INFO[14] = {0};
2796                /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */
2797                u16 cu_ch = (u16)cur_network->Configuration.DSConfig;
2798
2799                DBG_871X("%s, reply rc(pid = 0x%x) device "MAC_FMT" in ch =%d\n", __func__,
2800                        psta->pid, MAC_ARG(psta->hwaddr), cu_ch);
2801
2802                /* append vendor specific ie */
2803                memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI));
2804                memcpy(&RC_INFO[4], mac, ETH_ALEN);
2805                memcpy(&RC_INFO[10], (u8 *)&psta->pid, 2);
2806                memcpy(&RC_INFO[12], (u8 *)&cu_ch, 2);
2807
2808                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen);
2809        }
2810}
2811#endif /* CONFIG_AUTO_AP_MODE */
2812
2813
2814        pattrib->last_txcmdsz = pattrib->pktlen;
2815
2816
2817        dump_mgntframe(padapter, pmgntframe);
2818
2819        return;
2820
2821}
2822
2823static int _issue_probereq(struct adapter *padapter,
2824                           struct ndis_802_11_ssid *pssid,
2825                           u8 *da, u8 ch, bool append_wps, bool wait_ack)
2826{
2827        int ret = _FAIL;
2828        struct xmit_frame               *pmgntframe;
2829        struct pkt_attrib               *pattrib;
2830        unsigned char           *pframe;
2831        struct ieee80211_hdr    *pwlanhdr;
2832        __le16 *fctrl;
2833        unsigned char           *mac;
2834        unsigned char           bssrate[NumRates];
2835        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
2836        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
2837        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2838        int     bssrate_len = 0;
2839        u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2840
2841        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+issue_probereq\n"));
2842
2843        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2844        if (!pmgntframe)
2845                goto exit;
2846
2847        /* update attribute */
2848        pattrib = &pmgntframe->attrib;
2849        update_mgntframe_attrib(padapter, pattrib);
2850
2851
2852        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2853
2854        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2855        pwlanhdr = (struct ieee80211_hdr *)pframe;
2856
2857        mac = myid(&(padapter->eeprompriv));
2858
2859        fctrl = &(pwlanhdr->frame_control);
2860        *(fctrl) = 0;
2861
2862        if (da) {
2863                /*      unicast probe request frame */
2864                memcpy(pwlanhdr->addr1, da, ETH_ALEN);
2865                memcpy(pwlanhdr->addr3, da, ETH_ALEN);
2866        } else {
2867                /*      broadcast probe request frame */
2868                memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
2869                memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
2870        }
2871
2872        memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
2873
2874        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
2875        pmlmeext->mgnt_seq++;
2876        SetFrameSubType(pframe, WIFI_PROBEREQ);
2877
2878        pframe += sizeof(struct ieee80211_hdr_3addr);
2879        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
2880
2881        if (pssid)
2882                pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
2883        else
2884                pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
2885
2886        get_rate_set(padapter, bssrate, &bssrate_len);
2887
2888        if (bssrate_len > 8) {
2889                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen));
2890                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
2891        } else {
2892                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen));
2893        }
2894
2895        if (ch)
2896                pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, &ch, &pattrib->pktlen);
2897
2898        if (append_wps) {
2899                /* add wps_ie for wps2.0 */
2900                if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) {
2901                        memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
2902                        pframe += pmlmepriv->wps_probe_req_ie_len;
2903                        pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
2904                }
2905        }
2906
2907        pattrib->last_txcmdsz = pattrib->pktlen;
2908
2909        RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz));
2910
2911        if (wait_ack) {
2912                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
2913        } else {
2914                dump_mgntframe(padapter, pmgntframe);
2915                ret = _SUCCESS;
2916        }
2917
2918exit:
2919        return ret;
2920}
2921
2922inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da)
2923{
2924        _issue_probereq(padapter, pssid, da, 0, 1, false);
2925}
2926
2927int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps,
2928        int try_cnt, int wait_ms)
2929{
2930        int ret;
2931        int i = 0;
2932
2933        do {
2934                ret = _issue_probereq(padapter, pssid, da, ch, append_wps, wait_ms > 0?true:false);
2935
2936                i++;
2937
2938                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2939                        break;
2940
2941                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
2942                        msleep(wait_ms);
2943
2944        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
2945
2946        if (ret != _FAIL) {
2947                ret = _SUCCESS;
2948                #ifndef DBG_XMIT_ACK
2949                goto exit;
2950                #endif
2951        }
2952
2953        if (try_cnt && wait_ms) {
2954                if (da)
2955                        DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
2956                                FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
2957                                ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
2958                else
2959                        DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
2960                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
2961                                ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
2962        }
2963exit:
2964        return ret;
2965}
2966
2967/*  if psta == NULL, indiate we are station(client) now... */
2968void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status)
2969{
2970        struct xmit_frame                       *pmgntframe;
2971        struct pkt_attrib                       *pattrib;
2972        unsigned char                           *pframe;
2973        struct ieee80211_hdr    *pwlanhdr;
2974        __le16 *fctrl;
2975        unsigned int                                    val32;
2976        unsigned short                          val16;
2977        int use_shared_key = 0;
2978        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
2979        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
2980        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2981        __le16 le_tmp;
2982
2983        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
2984        if (pmgntframe == NULL)
2985                return;
2986
2987        /* update attribute */
2988        pattrib = &pmgntframe->attrib;
2989        update_mgntframe_attrib(padapter, pattrib);
2990
2991        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
2992
2993        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
2994        pwlanhdr = (struct ieee80211_hdr *)pframe;
2995
2996        fctrl = &(pwlanhdr->frame_control);
2997        *(fctrl) = 0;
2998
2999        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3000        pmlmeext->mgnt_seq++;
3001        SetFrameSubType(pframe, WIFI_AUTH);
3002
3003        pframe += sizeof(struct ieee80211_hdr_3addr);
3004        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3005
3006
3007        if (psta) { /*  for AP mode */
3008                memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);
3009                memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3010                memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN);
3011
3012                /*  setting auth algo number */
3013                val16 = (u16)psta->authalg;
3014
3015                if (status != _STATS_SUCCESSFUL_)
3016                        val16 = 0;
3017
3018                if (val16)
3019                        use_shared_key = 1;
3020
3021                le_tmp = cpu_to_le16(val16);
3022
3023                pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3024
3025                /*  setting auth seq number */
3026                val16 = (u16)psta->auth_seq;
3027                le_tmp = cpu_to_le16(val16);
3028                pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3029
3030                /*  setting status code... */
3031                val16 = status;
3032                le_tmp = cpu_to_le16(val16);
3033                pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3034
3035                /*  added challenging text... */
3036                if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1))
3037                        pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
3038
3039        } else {
3040                memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
3041                memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN);
3042                memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
3043
3044                /*  setting auth algo number */
3045                val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/*  0:OPEN System, 1:Shared key */
3046                if (val16) {
3047                        use_shared_key = 1;
3048                }
3049                le_tmp = cpu_to_le16(val16);
3050                /* DBG_871X("%s auth_algo = %s auth_seq =%d\n", __func__, (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED", pmlmeinfo->auth_seq); */
3051
3052                /* setting IV for auth seq #3 */
3053                if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
3054                        __le32 le_tmp32;
3055
3056                        /* DBG_871X("==> iv(%d), key_index(%d)\n", pmlmeinfo->iv, pmlmeinfo->key_index); */
3057                        val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
3058                        le_tmp32 = cpu_to_le32(val32);
3059                        pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen));
3060
3061                        pattrib->iv_len = 4;
3062                }
3063
3064                pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3065
3066                /*  setting auth seq number */
3067                le_tmp = cpu_to_le16(pmlmeinfo->auth_seq);
3068                pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3069
3070
3071                /*  setting status code... */
3072                le_tmp = cpu_to_le16(status);
3073                pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3074
3075                /*  then checking to see if sending challenging text... */
3076                if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) {
3077                        pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
3078
3079                        SetPrivacy(fctrl);
3080
3081                        pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3082
3083                        pattrib->encrypt = _WEP40_;
3084
3085                        pattrib->icv_len = 4;
3086
3087                        pattrib->pktlen += pattrib->icv_len;
3088
3089                }
3090
3091        }
3092
3093        pattrib->last_txcmdsz = pattrib->pktlen;
3094
3095        rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
3096        DBG_871X("%s\n", __func__);
3097        dump_mgntframe(padapter, pmgntframe);
3098
3099        return;
3100}
3101
3102
3103void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
3104{
3105        struct xmit_frame       *pmgntframe;
3106        struct ieee80211_hdr    *pwlanhdr;
3107        struct pkt_attrib *pattrib;
3108        unsigned char *pbuf, *pframe;
3109        unsigned short val;
3110        __le16 *fctrl;
3111        struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
3112        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3113        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3114        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3115        struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network);
3116        u8 *ie = pnetwork->IEs;
3117        __le16 lestatus, le_tmp;
3118
3119        DBG_871X("%s\n", __func__);
3120
3121        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3122        if (pmgntframe == NULL)
3123                return;
3124
3125        /* update attribute */
3126        pattrib = &pmgntframe->attrib;
3127        update_mgntframe_attrib(padapter, pattrib);
3128
3129
3130        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3131
3132        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3133        pwlanhdr = (struct ieee80211_hdr *)pframe;
3134
3135        fctrl = &(pwlanhdr->frame_control);
3136        *(fctrl) = 0;
3137
3138        memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
3139        memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN);
3140        memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3141
3142
3143        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3144        pmlmeext->mgnt_seq++;
3145        if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
3146                SetFrameSubType(pwlanhdr, pkt_type);
3147        else
3148                return;
3149
3150        pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
3151        pattrib->pktlen += pattrib->hdrlen;
3152        pframe += pattrib->hdrlen;
3153
3154        /* capability */
3155        val = *(unsigned short *)rtw_get_capability_from_ie(ie);
3156
3157        pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &(pattrib->pktlen));
3158
3159        lestatus = cpu_to_le16(status);
3160        pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &(pattrib->pktlen));
3161
3162        le_tmp = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
3163        pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3164
3165        if (pstat->bssratelen <= 8) {
3166                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
3167        } else {
3168                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
3169                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
3170        }
3171
3172        if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) {
3173                uint ie_len = 0;
3174
3175                /* FILL HT CAP INFO IE */
3176                /* p = hostapd_eid_ht_capabilities_info(hapd, p); */
3177                pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
3178                if (pbuf && ie_len > 0) {
3179                        memcpy(pframe, pbuf, ie_len+2);
3180                        pframe += (ie_len+2);
3181                        pattrib->pktlen += (ie_len+2);
3182                }
3183
3184                /* FILL HT ADD INFO IE */
3185                /* p = hostapd_eid_ht_operation(hapd, p); */
3186                pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
3187                if (pbuf && ie_len > 0) {
3188                        memcpy(pframe, pbuf, ie_len+2);
3189                        pframe += (ie_len+2);
3190                        pattrib->pktlen += (ie_len+2);
3191                }
3192
3193        }
3194
3195        /* FILL WMM IE */
3196        if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) {
3197                uint ie_len = 0;
3198                unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
3199
3200                for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) {
3201                        pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));
3202                        if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) {
3203                                memcpy(pframe, pbuf, ie_len+2);
3204                                pframe += (ie_len+2);
3205                                pattrib->pktlen += (ie_len+2);
3206
3207                                break;
3208                        }
3209
3210                        if ((pbuf == NULL) || (ie_len == 0)) {
3211                                break;
3212                        }
3213                }
3214
3215        }
3216
3217        if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) {
3218                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen));
3219        }
3220
3221        /* add WPS IE ie for wps 2.0 */
3222        if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) {
3223                memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
3224
3225                pframe += pmlmepriv->wps_assoc_resp_ie_len;
3226                pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
3227        }
3228
3229        pattrib->last_txcmdsz = pattrib->pktlen;
3230
3231        dump_mgntframe(padapter, pmgntframe);
3232}
3233
3234void issue_assocreq(struct adapter *padapter)
3235{
3236        int ret = _FAIL;
3237        struct xmit_frame                               *pmgntframe;
3238        struct pkt_attrib                               *pattrib;
3239        unsigned char                           *pframe;
3240        struct ieee80211_hdr                    *pwlanhdr;
3241        __le16 *fctrl;
3242        __le16 val16;
3243        unsigned int                                    i, j, index = 0;
3244        unsigned char bssrate[NumRates], sta_bssrate[NumRates];
3245        struct ndis_80211_var_ie *pIE;
3246        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3247        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
3248        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3249        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3250        int     bssrate_len = 0, sta_bssrate_len = 0;
3251        u8 vs_ie_length = 0;
3252
3253        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3254        if (pmgntframe == NULL)
3255                goto exit;
3256
3257        /* update attribute */
3258        pattrib = &pmgntframe->attrib;
3259        update_mgntframe_attrib(padapter, pattrib);
3260
3261        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3262
3263        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3264        pwlanhdr = (struct ieee80211_hdr *)pframe;
3265
3266        fctrl = &(pwlanhdr->frame_control);
3267        *(fctrl) = 0;
3268        memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3269        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3270        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3271
3272        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3273        pmlmeext->mgnt_seq++;
3274        SetFrameSubType(pframe, WIFI_ASSOCREQ);
3275
3276        pframe += sizeof(struct ieee80211_hdr_3addr);
3277        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3278
3279        /* caps */
3280        memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
3281
3282        pframe += 2;
3283        pattrib->pktlen += 2;
3284
3285        /* listen interval */
3286        /* todo: listen interval for power saving */
3287        val16 = cpu_to_le16(3);
3288        memcpy(pframe, (unsigned char *)&val16, 2);
3289        pframe += 2;
3290        pattrib->pktlen += 2;
3291
3292        /* SSID */
3293        pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
3294
3295        /* supported rate & extended supported rate */
3296
3297        /*  Check if the AP's supported rates are also supported by STA. */
3298        get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
3299        /* DBG_871X("sta_bssrate_len =%d\n", sta_bssrate_len); */
3300
3301        if (pmlmeext->cur_channel == 14) /*  for JAPAN, channel 14 can only uses B Mode(CCK) */
3302                sta_bssrate_len = 4;
3303
3304
3305        /* for (i = 0; i < sta_bssrate_len; i++) { */
3306        /*      DBG_871X("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */
3307        /*  */
3308
3309        for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3310                if (pmlmeinfo->network.SupportedRates[i] == 0)
3311                        break;
3312                DBG_871X("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
3313        }
3314
3315
3316        for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
3317                if (pmlmeinfo->network.SupportedRates[i] == 0)
3318                        break;
3319
3320
3321                /*  Check if the AP's supported rates are also supported by STA. */
3322                for (j = 0; j < sta_bssrate_len; j++) {
3323                         /*  Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
3324                        if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
3325                                        == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) {
3326                                /* DBG_871X("match i = %d, j =%d\n", i, j); */
3327                                break;
3328                        } else {
3329                                /* DBG_871X("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)); */
3330                        }
3331                }
3332
3333                if (j == sta_bssrate_len) {
3334                        /*  the rate is not supported by STA */
3335                        DBG_871X("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]);
3336                } else {
3337                        /*  the rate is supported by STA */
3338                        bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
3339                }
3340        }
3341
3342        bssrate_len = index;
3343        DBG_871X("bssrate_len = %d\n", bssrate_len);
3344
3345        if (bssrate_len == 0) {
3346                rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
3347                rtw_free_xmitframe(pxmitpriv, pmgntframe);
3348                goto exit; /* don't connect to AP if no joint supported rate */
3349        }
3350
3351
3352        if (bssrate_len > 8) {
3353                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, bssrate, &(pattrib->pktlen));
3354                pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
3355        } else
3356                pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, bssrate_len, bssrate, &(pattrib->pktlen));
3357
3358        /* vendor specific IE, such as WPA, WMM, WPS */
3359        for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) {
3360                pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i);
3361
3362                switch (pIE->ElementID) {
3363                case _VENDOR_SPECIFIC_IE_:
3364                        if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
3365                                        (!memcmp(pIE->data, WMM_OUI, 4)) ||
3366                                        (!memcmp(pIE->data, WPS_OUI, 4))) {
3367                                vs_ie_length = pIE->Length;
3368                                if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) {
3369                                        /* Commented by Kurt 20110629 */
3370                                        /* In some older APs, WPS handshake */
3371                                        /* would be fail if we append vender extensions informations to AP */
3372
3373                                        vs_ie_length = 14;
3374                                }
3375
3376                                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, vs_ie_length, pIE->data, &(pattrib->pktlen));
3377                        }
3378                        break;
3379
3380                case EID_WPA2:
3381                        pframe = rtw_set_ie(pframe, EID_WPA2, pIE->Length, pIE->data, &(pattrib->pktlen));
3382                        break;
3383                case EID_HTCapability:
3384                        if (padapter->mlmepriv.htpriv.ht_option) {
3385                                if (!(is_ap_in_tkip(padapter))) {
3386                                        memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
3387                                        pframe = rtw_set_ie(pframe, EID_HTCapability, pIE->Length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
3388                                }
3389                        }
3390                        break;
3391
3392                case EID_EXTCapability:
3393                        if (padapter->mlmepriv.htpriv.ht_option)
3394                                pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
3395                        break;
3396                default:
3397                        break;
3398                }
3399
3400                i += (pIE->Length + 2);
3401        }
3402
3403        if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
3404                pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6, REALTEK_96B_IE, &(pattrib->pktlen));
3405
3406
3407        pattrib->last_txcmdsz = pattrib->pktlen;
3408        dump_mgntframe(padapter, pmgntframe);
3409
3410        ret = _SUCCESS;
3411
3412exit:
3413        if (ret == _SUCCESS)
3414                rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
3415        else
3416                rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
3417
3418        return;
3419}
3420
3421/* when wait_ack is ture, this function shoule be called at process context */
3422static int _issue_nulldata(struct adapter *padapter, unsigned char *da,
3423                           unsigned int power_mode, bool wait_ack)
3424{
3425        int ret = _FAIL;
3426        struct xmit_frame                       *pmgntframe;
3427        struct pkt_attrib                       *pattrib;
3428        unsigned char                           *pframe;
3429        struct ieee80211_hdr    *pwlanhdr;
3430        __le16 *fctrl;
3431        struct xmit_priv *pxmitpriv;
3432        struct mlme_ext_priv *pmlmeext;
3433        struct mlme_ext_info *pmlmeinfo;
3434
3435        /* DBG_871X("%s:%d\n", __func__, power_mode); */
3436
3437        if (!padapter)
3438                goto exit;
3439
3440        pxmitpriv = &(padapter->xmitpriv);
3441        pmlmeext = &(padapter->mlmeextpriv);
3442        pmlmeinfo = &(pmlmeext->mlmext_info);
3443
3444        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3445        if (pmgntframe == NULL)
3446                goto exit;
3447
3448        /* update attribute */
3449        pattrib = &pmgntframe->attrib;
3450        update_mgntframe_attrib(padapter, pattrib);
3451        pattrib->retry_ctrl = false;
3452
3453        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3454
3455        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3456        pwlanhdr = (struct ieee80211_hdr *)pframe;
3457
3458        fctrl = &(pwlanhdr->frame_control);
3459        *(fctrl) = 0;
3460
3461        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3462                SetFrDs(fctrl);
3463        else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3464                SetToDs(fctrl);
3465
3466        if (power_mode)
3467                SetPwrMgt(fctrl);
3468
3469        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3470        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3471        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3472
3473        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3474        pmlmeext->mgnt_seq++;
3475        SetFrameSubType(pframe, WIFI_DATA_NULL);
3476
3477        pframe += sizeof(struct ieee80211_hdr_3addr);
3478        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3479
3480        pattrib->last_txcmdsz = pattrib->pktlen;
3481
3482        if (wait_ack) {
3483                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3484        } else {
3485                dump_mgntframe(padapter, pmgntframe);
3486                ret = _SUCCESS;
3487        }
3488
3489exit:
3490        return ret;
3491}
3492
3493/*
3494 * [IMPORTANT] Don't call this function in interrupt context
3495 *
3496 * When wait_ms > 0, this function shoule be called at process context
3497 * da == NULL for station mode
3498 */
3499int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
3500{
3501        int ret;
3502        int i = 0;
3503        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3504        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3505        struct sta_info *psta;
3506
3507
3508        /* da == NULL, assum it's null data for sta to ap*/
3509        if (!da)
3510                da = get_my_bssid(&(pmlmeinfo->network));
3511
3512        psta = rtw_get_stainfo(&padapter->stapriv, da);
3513        if (psta) {
3514                if (power_mode)
3515                        rtw_hal_macid_sleep(padapter, psta->mac_id);
3516                else
3517                        rtw_hal_macid_wakeup(padapter, psta->mac_id);
3518        } else {
3519                DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",
3520                        FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup");
3521                rtw_warn_on(1);
3522        }
3523
3524        do {
3525                ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0?true:false);
3526
3527                i++;
3528
3529                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3530                        break;
3531
3532                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3533                        msleep(wait_ms);
3534
3535        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3536
3537        if (ret != _FAIL) {
3538                ret = _SUCCESS;
3539                #ifndef DBG_XMIT_ACK
3540                goto exit;
3541                #endif
3542        }
3543
3544        if (try_cnt && wait_ms) {
3545                if (da)
3546                        DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
3547                                FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
3548                                ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3549                else
3550                        DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
3551                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
3552                                ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3553        }
3554exit:
3555        return ret;
3556}
3557
3558/*
3559 * [IMPORTANT] This function run in interrupt context
3560 *
3561 * The null data packet would be sent without power bit,
3562 * and not guarantee success.
3563 */
3564s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da)
3565{
3566        struct mlme_ext_priv *pmlmeext;
3567        struct mlme_ext_info *pmlmeinfo;
3568
3569
3570        pmlmeext = &padapter->mlmeextpriv;
3571        pmlmeinfo = &pmlmeext->mlmext_info;
3572
3573        /* da == NULL, assum it's null data for sta to ap*/
3574        if (!da)
3575                da = get_my_bssid(&(pmlmeinfo->network));
3576
3577        return _issue_nulldata(padapter, da, 0, false);
3578}
3579
3580/* when wait_ack is ture, this function shoule be called at process context */
3581static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da,
3582                               u16 tid, bool wait_ack)
3583{
3584        int ret = _FAIL;
3585        struct xmit_frame                       *pmgntframe;
3586        struct pkt_attrib                       *pattrib;
3587        unsigned char                           *pframe;
3588        struct ieee80211_hdr    *pwlanhdr;
3589        __le16 *fctrl;
3590        u16 *qc;
3591        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3592        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3593        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3594
3595        DBG_871X("%s\n", __func__);
3596
3597        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3598        if (pmgntframe == NULL)
3599                goto exit;
3600
3601        /* update attribute */
3602        pattrib = &pmgntframe->attrib;
3603        update_mgntframe_attrib(padapter, pattrib);
3604
3605        pattrib->hdrlen += 2;
3606        pattrib->qos_en = true;
3607        pattrib->eosp = 1;
3608        pattrib->ack_policy = 0;
3609        pattrib->mdata = 0;
3610
3611        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3612
3613        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3614        pwlanhdr = (struct ieee80211_hdr *)pframe;
3615
3616        fctrl = &(pwlanhdr->frame_control);
3617        *(fctrl) = 0;
3618
3619        if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
3620                SetFrDs(fctrl);
3621        else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
3622                SetToDs(fctrl);
3623
3624        if (pattrib->mdata)
3625                SetMData(fctrl);
3626
3627        qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
3628
3629        SetPriority(qc, tid);
3630
3631        SetEOSP(qc, pattrib->eosp);
3632
3633        SetAckpolicy(qc, pattrib->ack_policy);
3634
3635        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3636        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3637        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3638
3639        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3640        pmlmeext->mgnt_seq++;
3641        SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
3642
3643        pframe += sizeof(struct ieee80211_qos_hdr);
3644        pattrib->pktlen = sizeof(struct ieee80211_qos_hdr);
3645
3646        pattrib->last_txcmdsz = pattrib->pktlen;
3647
3648        if (wait_ack) {
3649                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3650        } else {
3651                dump_mgntframe(padapter, pmgntframe);
3652                ret = _SUCCESS;
3653        }
3654
3655exit:
3656        return ret;
3657}
3658
3659/* when wait_ms >0 , this function shoule be called at process context */
3660/* da == NULL for station mode */
3661int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
3662{
3663        int ret;
3664        int i = 0;
3665        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3666        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3667
3668        /* da == NULL, assum it's null data for sta to ap*/
3669        if (!da)
3670                da = get_my_bssid(&(pmlmeinfo->network));
3671
3672        do {
3673                ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0?true:false);
3674
3675                i++;
3676
3677                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3678                        break;
3679
3680                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3681                        msleep(wait_ms);
3682
3683        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3684
3685        if (ret != _FAIL) {
3686                ret = _SUCCESS;
3687                #ifndef DBG_XMIT_ACK
3688                goto exit;
3689                #endif
3690        }
3691
3692        if (try_cnt && wait_ms) {
3693                if (da)
3694                        DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
3695                                FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
3696                                ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3697                else
3698                        DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
3699                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
3700                                ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3701        }
3702exit:
3703        return ret;
3704}
3705
3706static int _issue_deauth(struct adapter *padapter, unsigned char *da,
3707                         unsigned short reason, bool wait_ack)
3708{
3709        struct xmit_frame                       *pmgntframe;
3710        struct pkt_attrib                       *pattrib;
3711        unsigned char                           *pframe;
3712        struct ieee80211_hdr    *pwlanhdr;
3713        __le16 *fctrl;
3714        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
3715        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3716        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3717        int ret = _FAIL;
3718        __le16 le_tmp;
3719
3720        /* DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da)); */
3721
3722        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3723        if (pmgntframe == NULL) {
3724                goto exit;
3725        }
3726
3727        /* update attribute */
3728        pattrib = &pmgntframe->attrib;
3729        update_mgntframe_attrib(padapter, pattrib);
3730        pattrib->retry_ctrl = false;
3731
3732        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3733
3734        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3735        pwlanhdr = (struct ieee80211_hdr *)pframe;
3736
3737        fctrl = &(pwlanhdr->frame_control);
3738        *(fctrl) = 0;
3739
3740        memcpy(pwlanhdr->addr1, da, ETH_ALEN);
3741        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3742        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3743
3744        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3745        pmlmeext->mgnt_seq++;
3746        SetFrameSubType(pframe, WIFI_DEAUTH);
3747
3748        pframe += sizeof(struct ieee80211_hdr_3addr);
3749        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3750
3751        le_tmp = cpu_to_le16(reason);
3752        pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen));
3753
3754        pattrib->last_txcmdsz = pattrib->pktlen;
3755
3756
3757        if (wait_ack) {
3758                ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
3759        } else {
3760                dump_mgntframe(padapter, pmgntframe);
3761                ret = _SUCCESS;
3762        }
3763
3764exit:
3765        return ret;
3766}
3767
3768int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason)
3769{
3770        DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
3771        return _issue_deauth(padapter, da, reason, false);
3772}
3773
3774int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
3775        int wait_ms)
3776{
3777        int ret;
3778        int i = 0;
3779
3780        do {
3781                ret = _issue_deauth(padapter, da, reason, wait_ms > 0?true:false);
3782
3783                i++;
3784
3785                if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
3786                        break;
3787
3788                if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
3789                        mdelay(wait_ms);
3790
3791        } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
3792
3793        if (ret != _FAIL) {
3794                ret = _SUCCESS;
3795                #ifndef DBG_XMIT_ACK
3796                goto exit;
3797                #endif
3798        }
3799
3800        if (try_cnt && wait_ms) {
3801                if (da)
3802                        DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
3803                                FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
3804                                ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3805                else
3806                        DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
3807                                FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
3808                                ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms);
3809        }
3810exit:
3811        return ret;
3812}
3813
3814void issue_action_SA_Query(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid)
3815{
3816        u8 category = RTW_WLAN_CATEGORY_SA_QUERY;
3817        struct xmit_frame               *pmgntframe;
3818        struct pkt_attrib               *pattrib;
3819        u8                      *pframe;
3820        struct ieee80211_hdr    *pwlanhdr;
3821        __le16 *fctrl;
3822        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3823        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3824        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3825        __le16 le_tmp;
3826
3827        DBG_871X("%s\n", __func__);
3828
3829        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3830        if (pmgntframe == NULL) {
3831                DBG_871X("%s: alloc_mgtxmitframe fail\n", __func__);
3832                return;
3833        }
3834
3835        /* update attribute */
3836        pattrib = &pmgntframe->attrib;
3837        update_mgntframe_attrib(padapter, pattrib);
3838
3839        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3840
3841        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3842        pwlanhdr = (struct ieee80211_hdr *)pframe;
3843
3844        fctrl = &(pwlanhdr->frame_control);
3845        *(fctrl) = 0;
3846
3847        if (raddr)
3848                memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3849        else
3850                memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3851        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3852        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3853
3854        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3855        pmlmeext->mgnt_seq++;
3856        SetFrameSubType(pframe, WIFI_ACTION);
3857
3858        pframe += sizeof(struct ieee80211_hdr_3addr);
3859        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3860
3861        pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
3862        pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
3863
3864        switch (action) {
3865        case 0: /* SA Query req */
3866                pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);
3867                pmlmeext->sa_query_seq++;
3868                /* send sa query request to AP, AP should reply sa query response in 1 second */
3869                set_sa_query_timer(pmlmeext, 1000);
3870                break;
3871
3872        case 1: /* SA Query rsp */
3873                le_tmp = cpu_to_le16(tid);
3874                pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen);
3875                break;
3876        default:
3877                break;
3878        }
3879
3880        pattrib->last_txcmdsz = pattrib->pktlen;
3881
3882        dump_mgntframe(padapter, pmgntframe);
3883}
3884
3885void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status)
3886{
3887        u8 category = RTW_WLAN_CATEGORY_BACK;
3888        u16 start_seq;
3889        u16 BA_para_set;
3890        u16 reason_code;
3891        u16 BA_timeout_value;
3892        u16 BA_starting_seqctrl = 0;
3893        enum HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;
3894        struct xmit_frame               *pmgntframe;
3895        struct pkt_attrib               *pattrib;
3896        u8                      *pframe;
3897        struct ieee80211_hdr    *pwlanhdr;
3898        __le16 *fctrl;
3899        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
3900        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
3901        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
3902        struct sta_info         *psta;
3903        struct sta_priv         *pstapriv = &padapter->stapriv;
3904        struct registry_priv    *pregpriv = &padapter->registrypriv;
3905        __le16 le_tmp;
3906
3907        DBG_871X("%s, category =%d, action =%d, status =%d\n", __func__, category, action, status);
3908
3909        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
3910        if (!pmgntframe)
3911                return;
3912
3913        /* update attribute */
3914        pattrib = &pmgntframe->attrib;
3915        update_mgntframe_attrib(padapter, pattrib);
3916
3917        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
3918
3919        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
3920        pwlanhdr = (struct ieee80211_hdr *)pframe;
3921
3922        fctrl = &(pwlanhdr->frame_control);
3923        *(fctrl) = 0;
3924
3925        /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */
3926        memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
3927        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
3928        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
3929
3930        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
3931        pmlmeext->mgnt_seq++;
3932        SetFrameSubType(pframe, WIFI_ACTION);
3933
3934        pframe += sizeof(struct ieee80211_hdr_3addr);
3935        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
3936
3937        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
3938        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
3939
3940        if (category == 3) {
3941                switch (action) {
3942                case 0: /* ADDBA req */
3943                        do {
3944                                pmlmeinfo->dialogToken++;
3945                        } while (pmlmeinfo->dialogToken == 0);
3946                        pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
3947
3948                        if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter)) {
3949                                /*  A-MSDU NOT Supported */
3950                                BA_para_set = 0;
3951                                /*  immediate Block Ack */
3952                                BA_para_set |= BIT(1) & IEEE80211_ADDBA_PARAM_POLICY_MASK;
3953                                /*  TID */
3954                                BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
3955                                /*  max buffer size is 8 MSDU */
3956                                BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
3957                        } else {
3958                                BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */
3959                        }
3960                        le_tmp = cpu_to_le16(BA_para_set);
3961                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3962
3963                        BA_timeout_value = 5000;/*  5ms */
3964                        le_tmp = cpu_to_le16(BA_timeout_value);
3965                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3966
3967                        /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */
3968                        psta = rtw_get_stainfo(pstapriv, raddr);
3969                        if (psta != NULL) {
3970                                start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1;
3971
3972                                DBG_871X("BA_starting_seqctrl = %d for TID =%d\n", start_seq, status & 0x07);
3973
3974                                psta->BA_starting_seqctrl[status & 0x07] = start_seq;
3975
3976                                BA_starting_seqctrl = start_seq << 4;
3977                        }
3978
3979                        le_tmp = cpu_to_le16(BA_starting_seqctrl);
3980                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
3981                        break;
3982
3983                case 1: /* ADDBA rsp */
3984                        pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
3985                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
3986                        if (padapter->driver_rx_ampdu_factor != 0xFF)
3987                                max_rx_ampdu_factor =
3988                                  (enum HT_CAP_AMPDU_FACTOR)padapter->driver_rx_ampdu_factor;
3989                        else
3990                                rtw_hal_get_def_var(padapter,
3991                                                    HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
3992
3993                        if (MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)
3994                                BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
3995                        else if (MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)
3996                                BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */
3997                        else if (MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)
3998                                BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */
3999                        else if (MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)
4000                                BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */
4001                        else
4002                                BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */
4003
4004                        if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter) &&
4005                            padapter->driver_rx_ampdu_factor == 0xFF) {
4006                                /*  max buffer size is 8 MSDU */
4007                                BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
4008                                BA_para_set |= (8 << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
4009                        }
4010
4011                        if (pregpriv->ampdu_amsdu == 0)/* disabled */
4012                                le_tmp = cpu_to_le16(BA_para_set & ~BIT(0));
4013                        else if (pregpriv->ampdu_amsdu == 1)/* enabled */
4014                                le_tmp = cpu_to_le16(BA_para_set | BIT(0));
4015                        else /* auto */
4016                                le_tmp = cpu_to_le16(BA_para_set);
4017
4018                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
4019                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
4020                        break;
4021                case 2:/* DELBA */
4022                        BA_para_set = (status & 0x1F) << 3;
4023                        le_tmp = cpu_to_le16(BA_para_set);
4024                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
4025
4026                        reason_code = 37;
4027                        le_tmp = cpu_to_le16(reason_code);
4028                        pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen));
4029                        break;
4030                default:
4031                        break;
4032                }
4033        }
4034
4035        pattrib->last_txcmdsz = pattrib->pktlen;
4036
4037        dump_mgntframe(padapter, pmgntframe);
4038}
4039
4040static void issue_action_BSSCoexistPacket(struct adapter *padapter)
4041{
4042        struct list_head                *plist, *phead;
4043        unsigned char category, action;
4044        struct xmit_frame                       *pmgntframe;
4045        struct pkt_attrib                       *pattrib;
4046        unsigned char                   *pframe;
4047        struct ieee80211_hdr    *pwlanhdr;
4048        __le16 *fctrl;
4049        struct  wlan_network    *pnetwork = NULL;
4050        struct xmit_priv                *pxmitpriv = &(padapter->xmitpriv);
4051        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4052        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
4053        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4054        struct __queue          *queue  = &(pmlmepriv->scanned_queue);
4055        u8 InfoContent[16] = {0};
4056        u8 ICS[8][15];
4057
4058        if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0))
4059                return;
4060
4061        if (true == pmlmeinfo->bwmode_updated)
4062                return;
4063
4064
4065        DBG_871X("%s\n", __func__);
4066
4067
4068        category = RTW_WLAN_CATEGORY_PUBLIC;
4069        action = ACT_PUBLIC_BSSCOEXIST;
4070
4071        pmgntframe = alloc_mgtxmitframe(pxmitpriv);
4072        if (pmgntframe == NULL) {
4073                return;
4074        }
4075
4076        /* update attribute */
4077        pattrib = &pmgntframe->attrib;
4078        update_mgntframe_attrib(padapter, pattrib);
4079
4080        memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
4081
4082        pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
4083        pwlanhdr = (struct ieee80211_hdr *)pframe;
4084
4085        fctrl = &(pwlanhdr->frame_control);
4086        *(fctrl) = 0;
4087
4088        memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
4089        memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN);
4090        memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
4091
4092        SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
4093        pmlmeext->mgnt_seq++;
4094        SetFrameSubType(pframe, WIFI_ACTION);
4095
4096        pframe += sizeof(struct ieee80211_hdr_3addr);
4097        pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr);
4098
4099        pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
4100        pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
4101
4102
4103        /*  */
4104        if (pmlmepriv->num_FortyMHzIntolerant > 0) {
4105                u8 iedata = 0;
4106
4107                iedata |= BIT(2);/* 20 MHz BSS Width Request */
4108
4109                pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));
4110
4111        }
4112
4113
4114        /*  */
4115        memset(ICS, 0, sizeof(ICS));
4116        if (pmlmepriv->num_sta_no_ht > 0) {
4117                int i;
4118
4119                spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
4120
4121                phead = get_list_head(queue);
4122                plist = get_next(phead);
4123
4124                while (1) {
4125                        int len;
4126                        u8 *p;
4127                        struct wlan_bssid_ex *pbss_network;
4128
4129                        if (phead == plist)
4130                                break;
4131
4132                        pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
4133
4134                        plist = get_next(plist);
4135
4136                        pbss_network = (struct wlan_bssid_ex *)&pnetwork->network;
4137
4138                        p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
4139                        if ((p == NULL) || (len == 0)) {/* non-HT */
4140
4141                                if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14))
4142                                        continue;
4143
4144                                ICS[0][pbss_network->Configuration.DSConfig] = 1;
4145
4146                                if (ICS[0][0] == 0)
4147                                        ICS[0][0] = 1;
4148                        }
4149
4150                }
4151
4152                spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
4153
4154
4155                for (i = 0; i < 8; i++) {
4156                        if (ICS[i][0] == 1) {
4157                                int j, k = 0;
4158
4159                                InfoContent[k] = i;
4160                                /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */
4161                                k++;
4162
4163                                for (j = 1; j <= 14; j++) {
4164                                        if (ICS[i][j] == 1) {
4165                                                if (k < 16) {
4166                                                        InfoContent[k] = j; /* channel number */
4167                                                        /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */
4168                                                        k++;
4169                                                }
4170                                        }
4171                                }
4172
4173                                pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
4174
4175                        }
4176
4177                }
4178
4179
4180        }
4181
4182
4183        pattrib->last_txcmdsz = pattrib->pktlen;
4184
4185        dump_mgntframe(padapter, pmgntframe);
4186}
4187
4188unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr)
4189{
4190        struct sta_priv *pstapriv = &padapter->stapriv;
4191        struct sta_info *psta = NULL;
4192        /* struct recv_reorder_ctrl *preorder_ctrl; */
4193        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4194        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4195        u16 tid;
4196
4197        if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
4198                if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
4199                        return _SUCCESS;
4200
4201        psta = rtw_get_stainfo(pstapriv, addr);
4202        if (psta == NULL)
4203                return _SUCCESS;
4204
4205        /* DBG_871X("%s:%s\n", __func__, (initiator == 0)?"RX_DIR":"TX_DIR"); */
4206
4207        if (initiator == 0) {/*  recipient */
4208                for (tid = 0; tid < MAXTID; tid++) {
4209                        if (psta->recvreorder_ctrl[tid].enable) {
4210                                DBG_871X("rx agg disable tid(%d)\n", tid);
4211                                issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
4212                                psta->recvreorder_ctrl[tid].enable = false;
4213                                psta->recvreorder_ctrl[tid].indicate_seq = 0xffff;
4214                                #ifdef DBG_RX_SEQ
4215                                DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__,
4216                                        psta->recvreorder_ctrl[tid].indicate_seq);
4217                                #endif
4218                        }
4219                }
4220        } else if (initiator == 1) {/*  originator */
4221                /* DBG_871X("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap); */
4222                for (tid = 0; tid < MAXTID; tid++) {
4223                        if (psta->htpriv.agg_enable_bitmap & BIT(tid)) {
4224                                DBG_871X("tx agg disable tid(%d)\n", tid);
4225                                issue_action_BA(padapter, addr, RTW_WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F));
4226                                psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
4227                                psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
4228
4229                        }
4230                }
4231        }
4232
4233        return _SUCCESS;
4234
4235}
4236
4237unsigned int send_beacon(struct adapter *padapter)
4238{
4239        u8 bxmitok = false;
4240        int     issue = 0;
4241        int poll = 0;
4242        unsigned long start = jiffies;
4243
4244        rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
4245        rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
4246        do {
4247                issue_beacon(padapter, 100);
4248                issue++;
4249                do {
4250                        cond_resched();
4251                        rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
4252                        poll++;
4253                } while ((poll%10) != 0 && false == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
4254
4255        } while (false == bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped);
4256
4257        if (padapter->bSurpriseRemoved || padapter->bDriverStopped) {
4258                return _FAIL;
4259        }
4260
4261
4262        if (false == bxmitok) {
4263                DBG_871X("%s fail! %u ms\n", __func__, jiffies_to_msecs(jiffies - start));
4264                return _FAIL;
4265        } else {
4266                unsigned long passing_time = jiffies_to_msecs(jiffies - start);
4267
4268                if (passing_time > 100 || issue > 3)
4269                        DBG_871X("%s success, issue:%d, poll:%d, %lu ms\n", __func__, issue, poll, passing_time);
4270                /* else */
4271                /*      DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __func__, issue, poll, passing_time); */
4272
4273                return _SUCCESS;
4274        }
4275}
4276
4277/****************************************************************************
4278
4279Following are some utitity fuctions for WiFi MLME
4280
4281*****************************************************************************/
4282
4283void site_survey(struct adapter *padapter)
4284{
4285        unsigned char   survey_channel = 0, val8;
4286        RT_SCAN_TYPE    ScanType = SCAN_PASSIVE;
4287        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4288        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4289        u32 initialgain = 0;
4290        u32 channel_scan_time_ms = 0;
4291
4292        {
4293                struct rtw_ieee80211_channel *ch;
4294                if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) {
4295                        ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx];
4296                        survey_channel = ch->hw_value;
4297                        ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
4298                }
4299        }
4300
4301        DBG_871X(FUNC_ADPT_FMT" ch:%u (cnt:%u) at %dms, %c%c%c\n"
4302                 , FUNC_ADPT_ARG(padapter)
4303                 , survey_channel
4304                 , pmlmeext->sitesurvey_res.channel_idx
4305                 , jiffies_to_msecs(jiffies - padapter->mlmepriv.scan_start_time)
4306                 , ScanType?'A':'P', pmlmeext->sitesurvey_res.scan_mode?'A':'P'
4307                 , pmlmeext->sitesurvey_res.ssid[0].SsidLength?'S':' '
4308                );
4309#ifdef DBG_FIXED_CHAN
4310        DBG_871X(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan);
4311#endif
4312
4313        if (survey_channel != 0) {
4314                /* PAUSE 4-AC Queue when site_survey */
4315                /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
4316                /* val8 |= 0x0f; */
4317                /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
4318                if (pmlmeext->sitesurvey_res.channel_idx == 0) {
4319#ifdef DBG_FIXED_CHAN
4320                        if (pmlmeext->fixed_chan != 0xff)
4321                                set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4322                        else
4323#endif
4324                                set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4325                } else {
4326#ifdef DBG_FIXED_CHAN
4327                        if (pmlmeext->fixed_chan != 0xff)
4328                                SelectChannel(padapter, pmlmeext->fixed_chan);
4329                        else
4330#endif
4331                                SelectChannel(padapter, survey_channel);
4332                }
4333
4334                if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */
4335                        {
4336                                int i;
4337                                for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
4338                                        if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
4339                                                /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
4340                                                if (padapter->registrypriv.wifi_spec)
4341                                                        issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
4342                                                else
4343                                                        issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
4344                                                issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
4345                                        }
4346                                }
4347
4348                                if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
4349                                        /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
4350                                        if (padapter->registrypriv.wifi_spec)
4351                                                issue_probereq(padapter, NULL, NULL);
4352                                        else
4353                                                issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
4354                                        issue_probereq(padapter, NULL, NULL);
4355                                }
4356                        }
4357                }
4358
4359                channel_scan_time_ms = pmlmeext->chan_scan_time;
4360
4361                set_survey_timer(pmlmeext, channel_scan_time_ms);
4362#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
4363                {
4364                        struct noise_info info;
4365                        info.bPauseDIG = false;
4366                        info.IGIValue = 0;
4367                        info.max_time = channel_scan_time_ms/2;/* ms */
4368                        info.chan = survey_channel;
4369                        rtw_hal_set_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &info, false);
4370                }
4371#endif
4372
4373        } else {
4374
4375                /*      channel number is 0 or this channel is not valid. */
4376
4377                {
4378                        pmlmeext->sitesurvey_res.state = SCAN_COMPLETE;
4379
4380                        /* switch back to the original channel */
4381                        /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */
4382
4383                        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
4384
4385                        /* flush 4-AC Queue after site_survey */
4386                        /* val8 = 0; */
4387                        /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */
4388
4389                        /* config MSR */
4390                        Set_MSR(padapter, (pmlmeinfo->state & 0x3));
4391
4392                        initialgain = 0xff; /* restore RX GAIN */
4393                        rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
4394                        /* turn on dynamic functions */
4395                        Restore_DM_Func_Flag(padapter);
4396                        /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */
4397
4398                        if (is_client_associated_to_ap(padapter))
4399                                issue_nulldata(padapter, NULL, 0, 3, 500);
4400
4401                        val8 = 0; /* survey done */
4402                        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
4403
4404                        report_surveydone_event(padapter);
4405
4406                        pmlmeext->chan_scan_time = SURVEY_TO;
4407                        pmlmeext->sitesurvey_res.state = SCAN_DISABLE;
4408
4409                        issue_action_BSSCoexistPacket(padapter);
4410                        issue_action_BSSCoexistPacket(padapter);
4411                        issue_action_BSSCoexistPacket(padapter);
4412                }
4413        }
4414
4415        return;
4416
4417}
4418
4419/* collect bss info from Beacon and Probe request/response frames. */
4420u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid)
4421{
4422        int     i;
4423        u32 len;
4424        u8 *p;
4425        u16 val16, subtype;
4426        u8 *pframe = precv_frame->u.hdr.rx_data;
4427        u32 packet_len = precv_frame->u.hdr.len;
4428        u8 ie_offset;
4429        struct registry_priv *pregistrypriv = &padapter->registrypriv;
4430        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4431        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4432        __le32 le32_tmp;
4433
4434        len = packet_len - sizeof(struct ieee80211_hdr_3addr);
4435
4436        if (len > MAX_IE_SZ) {
4437                /* DBG_871X("IE too long for survey event\n"); */
4438                return _FAIL;
4439        }
4440
4441        memset(bssid, 0, sizeof(struct wlan_bssid_ex));
4442
4443        subtype = GetFrameSubType(pframe);
4444
4445        if (subtype == WIFI_BEACON) {
4446                bssid->Reserved[0] = 1;
4447                ie_offset = _BEACON_IE_OFFSET_;
4448        } else {
4449                /*  FIXME : more type */
4450                if (subtype == WIFI_PROBERSP) {
4451                        ie_offset = _PROBERSP_IE_OFFSET_;
4452                        bssid->Reserved[0] = 3;
4453                } else if (subtype == WIFI_PROBEREQ) {
4454                        ie_offset = _PROBEREQ_IE_OFFSET_;
4455                        bssid->Reserved[0] = 2;
4456                } else {
4457                        bssid->Reserved[0] = 0;
4458                        ie_offset = _FIXED_IE_LENGTH_;
4459                }
4460        }
4461
4462        bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len;
4463
4464        /* below is to copy the information element */
4465        bssid->IELength = len;
4466        memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength);
4467
4468        /* get the signal strength */
4469        bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /*  in dBM.raw data */
4470        bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */
4471        bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */
4472
4473        /*  checking SSID */
4474        p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset);
4475        if (p == NULL) {
4476                DBG_871X("marc: cannot find SSID for survey event\n");
4477                return _FAIL;
4478        }
4479
4480        if (*(p + 1)) {
4481                if (len > NDIS_802_11_LENGTH_SSID) {
4482                        DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
4483                        return _FAIL;
4484                }
4485                memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
4486                bssid->Ssid.SsidLength = *(p + 1);
4487        } else
4488                bssid->Ssid.SsidLength = 0;
4489
4490        memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
4491
4492        /* checking rate info... */
4493        i = 0;
4494        p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
4495        if (p != NULL) {
4496                if (len > NDIS_802_11_LENGTH_RATES_EX) {
4497                        DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
4498                        return _FAIL;
4499                }
4500                memcpy(bssid->SupportedRates, (p + 2), len);
4501                i = len;
4502        }
4503
4504        p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
4505        if (p != NULL) {
4506                if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) {
4507                        DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len);
4508                        return _FAIL;
4509                }
4510                memcpy(bssid->SupportedRates + i, (p + 2), len);
4511        }
4512
4513        bssid->NetworkTypeInUse = Ndis802_11OFDM24;
4514
4515        if (bssid->IELength < 12)
4516                return _FAIL;
4517
4518        /*  Checking for DSConfig */
4519        p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
4520
4521        bssid->Configuration.DSConfig = 0;
4522        bssid->Configuration.Length = 0;
4523
4524        if (p) {
4525                bssid->Configuration.DSConfig = *(p + 2);
4526        } else {
4527                /*  In 5G, some ap do not have DSSET IE */
4528                /*  checking HT info for channel */
4529                p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
4530                if (p) {
4531                        struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
4532                        bssid->Configuration.DSConfig = HT_info->primary_channel;
4533                } else { /*  use current channel */
4534                        bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
4535                }
4536        }
4537
4538        memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
4539        bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp);
4540
4541        val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid);
4542
4543        if (val16 & BIT(0)) {
4544                bssid->InfrastructureMode = Ndis802_11Infrastructure;
4545                memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
4546        } else {
4547                bssid->InfrastructureMode = Ndis802_11IBSS;
4548                memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
4549        }
4550
4551        if (val16 & BIT(4))
4552                bssid->Privacy = 1;
4553        else
4554                bssid->Privacy = 0;
4555
4556        bssid->Configuration.ATIMWindow = 0;
4557
4558        /* 20/40 BSS Coexistence check */
4559        if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) {
4560                struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
4561
4562                p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
4563                if (p && len > 0) {
4564                        struct HT_caps_element  *pHT_caps;
4565                        pHT_caps = (struct HT_caps_element      *)(p + 2);
4566
4567                        if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14))
4568                                pmlmepriv->num_FortyMHzIntolerant++;
4569                } else
4570                        pmlmepriv->num_sta_no_ht++;
4571        }
4572
4573        #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1
4574        if (strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
4575                DBG_871X("Receiving %s("MAC_FMT", DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n"
4576                        , bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig
4577                        , rtw_get_oper_ch(padapter)
4578                        , bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi
4579                );
4580        }
4581        #endif
4582
4583        /*  mark bss info receving from nearby channel as SignalQuality 101 */
4584        if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
4585                bssid->PhyInfo.SignalQuality = 101;
4586
4587        return _SUCCESS;
4588}
4589
4590void start_create_ibss(struct adapter *padapter)
4591{
4592        unsigned short  caps;
4593        u8 val8;
4594        u8 join_type;
4595        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4596        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4597        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4598        pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
4599        pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
4600
4601        /* update wireless mode */
4602        update_wireless_mode(padapter);
4603
4604        /* udpate capability */
4605        caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
4606        update_capinfo(padapter, caps);
4607        if (caps&cap_IBSS) {/* adhoc master */
4608                val8 = 0xcf;
4609                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4610
4611                rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
4612
4613                /* switch channel */
4614                /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */
4615                set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
4616
4617                beacon_timing_control(padapter);
4618
4619                /* set msr to WIFI_FW_ADHOC_STATE */
4620                pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4621                Set_MSR(padapter, (pmlmeinfo->state & 0x3));
4622
4623                /* issue beacon */
4624                if (send_beacon(padapter) == _FAIL) {
4625                        RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n"));
4626
4627                        report_join_res(padapter, -1);
4628                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
4629                } else {
4630                        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
4631                        join_type = 0;
4632                        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
4633
4634                        report_join_res(padapter, 1);
4635                        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
4636                        rtw_indicate_connect(padapter);
4637                }
4638        } else {
4639                DBG_871X("start_create_ibss, invalid cap:%x\n", caps);
4640                return;
4641        }
4642        /* update bc/mc sta_info */
4643        update_bmc_sta(padapter);
4644
4645}
4646
4647void start_clnt_join(struct adapter *padapter)
4648{
4649        unsigned short  caps;
4650        u8 val8;
4651        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4652        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4653        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
4654        int beacon_timeout;
4655
4656        /* update wireless mode */
4657        update_wireless_mode(padapter);
4658
4659        /* udpate capability */
4660        caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork);
4661        update_capinfo(padapter, caps);
4662        if (caps&cap_ESS) {
4663                Set_MSR(padapter, WIFI_FW_STATION_STATE);
4664
4665                val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf;
4666
4667                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4668
4669                /*  Because of AP's not receiving deauth before */
4670                /*  AP may: 1)not response auth or 2)deauth us after link is complete */
4671                /*  issue deauth before issuing auth to deal with the situation */
4672
4673                /*      Commented by Albert 2012/07/21 */
4674                /*      For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */
4675                {
4676                                /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */
4677                                issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
4678                }
4679
4680                /* here wait for receiving the beacon to start auth */
4681                /* and enable a timer */
4682                beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
4683                set_link_timer(pmlmeext, beacon_timeout);
4684                _set_timer(&padapter->mlmepriv.assoc_timer,
4685                        (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout);
4686
4687                pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
4688        } else if (caps&cap_IBSS) { /* adhoc client */
4689                Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
4690
4691                val8 = 0xcf;
4692                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
4693
4694                beacon_timing_control(padapter);
4695
4696                pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
4697
4698                report_join_res(padapter, 1);
4699        } else {
4700                /* DBG_871X("marc: invalid cap:%x\n", caps); */
4701                return;
4702        }
4703
4704}
4705
4706void start_clnt_auth(struct adapter *padapter)
4707{
4708        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4709        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4710
4711        del_timer_sync(&pmlmeext->link_timer);
4712
4713        pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
4714        pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
4715
4716        pmlmeinfo->auth_seq = 1;
4717        pmlmeinfo->reauth_count = 0;
4718        pmlmeinfo->reassoc_count = 0;
4719        pmlmeinfo->link_count = 0;
4720        pmlmeext->retry = 0;
4721
4722
4723        DBG_871X_LEVEL(_drv_always_, "start auth\n");
4724        issue_auth(padapter, NULL, 0);
4725
4726        set_link_timer(pmlmeext, REAUTH_TO);
4727
4728}
4729
4730
4731void start_clnt_assoc(struct adapter *padapter)
4732{
4733        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4734        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4735
4736        del_timer_sync(&pmlmeext->link_timer);
4737
4738        pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
4739        pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
4740
4741        issue_assocreq(padapter);
4742
4743        set_link_timer(pmlmeext, REASSOC_TO);
4744}
4745
4746unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
4747{
4748        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
4749        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
4750
4751        /* check A3 */
4752        if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
4753                return _SUCCESS;
4754
4755        DBG_871X("%s\n", __func__);
4756
4757        if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
4758                if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
4759                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
4760                        report_del_sta_event(padapter, MacAddr, reason);
4761
4762                } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) {
4763                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
4764                        report_join_res(padapter, -2);
4765                }
4766        }
4767
4768        return _SUCCESS;
4769}
4770
4771static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid)
4772{
4773        struct registry_priv *pregistrypriv;
4774        struct mlme_ext_priv *pmlmeext;
4775        RT_CHANNEL_INFO *chplan_new;
4776        u8 channel;
4777        u8 i;
4778
4779
4780        pregistrypriv = &padapter->registrypriv;
4781        pmlmeext = &padapter->mlmeextpriv;
4782
4783        /*  Adjust channel plan by AP Country IE */
4784        if (pregistrypriv->enable80211d &&
4785                (!pmlmeext->update_channel_plan_by_ap_done)) {
4786                u8 *ie, *p;
4787                u32 len;
4788                RT_CHANNEL_PLAN chplan_ap;
4789                RT_CHANNEL_INFO chplan_sta[MAX_CHANNEL_NUM];
4790                u8 country[4];
4791                u8 fcn; /*  first channel number */
4792                u8 noc; /*  number of channel */
4793                u8 j, k;
4794
4795                ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
4796                if (!ie)
4797                        return;
4798                if (len < 6)
4799                        return;
4800
4801                ie += 2;
4802                p = ie;
4803                ie += len;
4804
4805                memset(country, 0, 4);
4806                memcpy(country, p, 3);
4807                p += 3;
4808                RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
4809                                ("%s: 802.11d country =%s\n", __func__, country));
4810
4811                i = 0;
4812                while ((ie - p) >= 3) {
4813                        fcn = *(p++);
4814                        noc = *(p++);
4815                        p++;
4816
4817                        for (j = 0; j < noc; j++) {
4818                                if (fcn <= 14)
4819                                        channel = fcn + j; /*  2.4 GHz */
4820                                else
4821                                        channel = fcn + j*4; /*  5 GHz */
4822
4823                                chplan_ap.Channel[i++] = channel;
4824                        }
4825                }
4826                chplan_ap.Len = i;
4827
4828#ifdef DEBUG_RTL871X
4829                i = 0;
4830                DBG_871X("%s: AP[%s] channel plan {", __func__, bssid->Ssid.Ssid);
4831                while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0)) {
4832                        DBG_8192C("%02d,", chplan_ap.Channel[i]);
4833                        i++;
4834                }
4835                DBG_871X("}\n");
4836#endif
4837
4838                memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
4839#ifdef DEBUG_RTL871X
4840                i = 0;
4841                DBG_871X("%s: STA channel plan {", __func__);
4842                while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
4843                        DBG_871X("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType == SCAN_PASSIVE?'p':'a');
4844                        i++;
4845                }
4846                DBG_871X("}\n");
4847#endif
4848
4849                memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
4850                chplan_new = pmlmeext->channel_set;
4851
4852                i = j = k = 0;
4853                if (pregistrypriv->wireless_mode & WIRELESS_11G) {
4854                        do {
4855                                if ((i == MAX_CHANNEL_NUM) ||
4856                                        (chplan_sta[i].ChannelNum == 0) ||
4857                                        (chplan_sta[i].ChannelNum > 14))
4858                                        break;
4859
4860                                if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
4861                                        break;
4862
4863                                if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
4864                                        chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4865                                        chplan_new[k].ScanType = SCAN_ACTIVE;
4866                                        i++;
4867                                        j++;
4868                                        k++;
4869                                } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
4870                                        chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4871/*                                      chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4872                                        chplan_new[k].ScanType = SCAN_PASSIVE;
4873                                        i++;
4874                                        k++;
4875                                } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
4876                                        chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4877                                        chplan_new[k].ScanType = SCAN_ACTIVE;
4878                                        j++;
4879                                        k++;
4880                                }
4881                        } while (1);
4882
4883                        /*  change AP not support channel to Passive scan */
4884                        while ((i < MAX_CHANNEL_NUM) &&
4885                                (chplan_sta[i].ChannelNum != 0) &&
4886                                (chplan_sta[i].ChannelNum <= 14)) {
4887
4888                                chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4889/*                              chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4890                                chplan_new[k].ScanType = SCAN_PASSIVE;
4891                                i++;
4892                                k++;
4893                        }
4894
4895                        /*  add channel AP supported */
4896                        while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
4897                                chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4898                                chplan_new[k].ScanType = SCAN_ACTIVE;
4899                                j++;
4900                                k++;
4901                        }
4902                } else {
4903                        /*  keep original STA 2.4G channel plan */
4904                        while ((i < MAX_CHANNEL_NUM) &&
4905                                (chplan_sta[i].ChannelNum != 0) &&
4906                                (chplan_sta[i].ChannelNum <= 14)) {
4907                                chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4908                                chplan_new[k].ScanType = chplan_sta[i].ScanType;
4909                                i++;
4910                                k++;
4911                        }
4912
4913                        /*  skip AP 2.4G channel plan */
4914                        while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) {
4915                                j++;
4916                        }
4917                }
4918
4919                if (pregistrypriv->wireless_mode & WIRELESS_11A) {
4920                        do {
4921                                if ((i == MAX_CHANNEL_NUM) ||
4922                                        (chplan_sta[i].ChannelNum == 0))
4923                                        break;
4924
4925                                if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
4926                                        break;
4927
4928                                if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) {
4929                                        chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4930                                        chplan_new[k].ScanType = SCAN_ACTIVE;
4931                                        i++;
4932                                        j++;
4933                                        k++;
4934                                } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) {
4935                                        chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4936/*                                      chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4937                                        chplan_new[k].ScanType = SCAN_PASSIVE;
4938                                        i++;
4939                                        k++;
4940                                } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) {
4941                                        chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4942                                        chplan_new[k].ScanType = SCAN_ACTIVE;
4943                                        j++;
4944                                        k++;
4945                                }
4946                        } while (1);
4947
4948                        /*  change AP not support channel to Passive scan */
4949                        while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
4950                                chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4951/*                              chplan_new[k].ScanType = chplan_sta[i].ScanType; */
4952                                chplan_new[k].ScanType = SCAN_PASSIVE;
4953                                i++;
4954                                k++;
4955                        }
4956
4957                        /*  add channel AP supported */
4958                        while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) {
4959                                chplan_new[k].ChannelNum = chplan_ap.Channel[j];
4960                                chplan_new[k].ScanType = SCAN_ACTIVE;
4961                                j++;
4962                                k++;
4963                        }
4964                } else {
4965                        /*  keep original STA 5G channel plan */
4966                        while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) {
4967                                chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
4968                                chplan_new[k].ScanType = chplan_sta[i].ScanType;
4969                                i++;
4970                                k++;
4971                        }
4972                }
4973
4974                pmlmeext->update_channel_plan_by_ap_done = 1;
4975
4976#ifdef DEBUG_RTL871X
4977                k = 0;
4978                DBG_871X("%s: new STA channel plan {", __func__);
4979                while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) {
4980                        DBG_871X("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType == SCAN_PASSIVE?'p':'c');
4981                        k++;
4982                }
4983                DBG_871X("}\n");
4984#endif
4985        }
4986
4987        /*  If channel is used by AP, set channel scan type to active */
4988        channel = bssid->Configuration.DSConfig;
4989        chplan_new = pmlmeext->channel_set;
4990        i = 0;
4991        while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) {
4992                if (chplan_new[i].ChannelNum == channel) {
4993                        if (chplan_new[i].ScanType == SCAN_PASSIVE) {
4994                                /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */
4995                                if (channel >= 52 && channel <= 144)
4996                                        break;
4997
4998                                chplan_new[i].ScanType = SCAN_ACTIVE;
4999                                RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
5000                                                 ("%s: change channel %d scan type from passive to active\n",
5001                                                  __func__, channel));
5002                        }
5003                        break;
5004                }
5005                i++;
5006        }
5007}
5008
5009/****************************************************************************
5010
5011Following are the functions to report events
5012
5013*****************************************************************************/
5014
5015void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame)
5016{
5017        struct cmd_obj *pcmd_obj;
5018        u8 *pevtcmd;
5019        u32 cmdsz;
5020        struct survey_event     *psurvey_evt;
5021        struct C2HEvent_Header *pc2h_evt_hdr;
5022        struct mlme_ext_priv *pmlmeext;
5023        struct cmd_priv *pcmdpriv;
5024        /* u8 *pframe = precv_frame->u.hdr.rx_data; */
5025        /* uint len = precv_frame->u.hdr.len; */
5026
5027        if (!padapter)
5028                return;
5029
5030        pmlmeext = &padapter->mlmeextpriv;
5031        pcmdpriv = &padapter->cmdpriv;
5032
5033        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
5034        if (!pcmd_obj)
5035                return;
5036
5037        cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
5038        pevtcmd = rtw_zmalloc(cmdsz);
5039        if (!pevtcmd) {
5040                kfree(pcmd_obj);
5041                return;
5042        }
5043
5044        INIT_LIST_HEAD(&pcmd_obj->list);
5045
5046        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5047        pcmd_obj->cmdsz = cmdsz;
5048        pcmd_obj->parmbuf = pevtcmd;
5049
5050        pcmd_obj->rsp = NULL;
5051        pcmd_obj->rspsz  = 0;
5052
5053        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5054        pc2h_evt_hdr->len = sizeof(struct survey_event);
5055        pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
5056        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5057
5058        psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5059
5060        if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) {
5061                kfree(pcmd_obj);
5062                kfree(pevtcmd);
5063                return;
5064        }
5065
5066        process_80211d(padapter, &psurvey_evt->bss);
5067
5068        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5069
5070        pmlmeext->sitesurvey_res.bss_cnt++;
5071
5072        return;
5073
5074}
5075
5076void report_surveydone_event(struct adapter *padapter)
5077{
5078        struct cmd_obj *pcmd_obj;
5079        u8 *pevtcmd;
5080        u32 cmdsz;
5081        struct surveydone_event *psurveydone_evt;
5082        struct C2HEvent_Header  *pc2h_evt_hdr;
5083        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5084        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5085
5086        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
5087        if (!pcmd_obj)
5088                return;
5089
5090        cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
5091        pevtcmd = rtw_zmalloc(cmdsz);
5092        if (!pevtcmd) {
5093                kfree(pcmd_obj);
5094                return;
5095        }
5096
5097        INIT_LIST_HEAD(&pcmd_obj->list);
5098
5099        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5100        pcmd_obj->cmdsz = cmdsz;
5101        pcmd_obj->parmbuf = pevtcmd;
5102
5103        pcmd_obj->rsp = NULL;
5104        pcmd_obj->rspsz  = 0;
5105
5106        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5107        pc2h_evt_hdr->len = sizeof(struct surveydone_event);
5108        pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
5109        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5110
5111        psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5112        psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
5113
5114        DBG_871X("survey done event(%x) band:%d for "ADPT_FMT"\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter));
5115
5116        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5117
5118        return;
5119
5120}
5121
5122void report_join_res(struct adapter *padapter, int res)
5123{
5124        struct cmd_obj *pcmd_obj;
5125        u8 *pevtcmd;
5126        u32 cmdsz;
5127        struct joinbss_event            *pjoinbss_evt;
5128        struct C2HEvent_Header  *pc2h_evt_hdr;
5129        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5130        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5131        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5132
5133        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
5134        if (!pcmd_obj)
5135                return;
5136
5137        cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
5138        pevtcmd = rtw_zmalloc(cmdsz);
5139        if (!pevtcmd) {
5140                kfree(pcmd_obj);
5141                return;
5142        }
5143
5144        INIT_LIST_HEAD(&pcmd_obj->list);
5145
5146        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5147        pcmd_obj->cmdsz = cmdsz;
5148        pcmd_obj->parmbuf = pevtcmd;
5149
5150        pcmd_obj->rsp = NULL;
5151        pcmd_obj->rspsz  = 0;
5152
5153        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5154        pc2h_evt_hdr->len = sizeof(struct joinbss_event);
5155        pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
5156        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5157
5158        pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5159        memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
5160        pjoinbss_evt->network.join_res  = pjoinbss_evt->network.aid = res;
5161
5162        DBG_871X("report_join_res(%d)\n", res);
5163
5164
5165        rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
5166
5167
5168        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5169
5170        return;
5171
5172}
5173
5174void report_wmm_edca_update(struct adapter *padapter)
5175{
5176        struct cmd_obj *pcmd_obj;
5177        u8 *pevtcmd;
5178        u32 cmdsz;
5179        struct wmm_event                *pwmm_event;
5180        struct C2HEvent_Header  *pc2h_evt_hdr;
5181        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5182        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5183
5184        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
5185        if (!pcmd_obj)
5186                return;
5187
5188        cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));
5189        pevtcmd = rtw_zmalloc(cmdsz);
5190        if (!pevtcmd) {
5191                kfree(pcmd_obj);
5192                return;
5193        }
5194
5195        INIT_LIST_HEAD(&pcmd_obj->list);
5196
5197        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5198        pcmd_obj->cmdsz = cmdsz;
5199        pcmd_obj->parmbuf = pevtcmd;
5200
5201        pcmd_obj->rsp = NULL;
5202        pcmd_obj->rspsz  = 0;
5203
5204        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5205        pc2h_evt_hdr->len = sizeof(struct wmm_event);
5206        pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM);
5207        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5208
5209        pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5210        pwmm_event->wmm = 0;
5211
5212        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5213
5214        return;
5215
5216}
5217
5218void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason)
5219{
5220        struct cmd_obj *pcmd_obj;
5221        u8 *pevtcmd;
5222        u32 cmdsz;
5223        struct sta_info *psta;
5224        int     mac_id;
5225        struct stadel_event                     *pdel_sta_evt;
5226        struct C2HEvent_Header  *pc2h_evt_hdr;
5227        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5228        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5229
5230        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
5231        if (pcmd_obj == NULL) {
5232                return;
5233        }
5234
5235        cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
5236        pevtcmd = rtw_zmalloc(cmdsz);
5237        if (pevtcmd == NULL) {
5238                kfree(pcmd_obj);
5239                return;
5240        }
5241
5242        INIT_LIST_HEAD(&pcmd_obj->list);
5243
5244        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5245        pcmd_obj->cmdsz = cmdsz;
5246        pcmd_obj->parmbuf = pevtcmd;
5247
5248        pcmd_obj->rsp = NULL;
5249        pcmd_obj->rspsz  = 0;
5250
5251        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5252        pc2h_evt_hdr->len = sizeof(struct stadel_event);
5253        pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
5254        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5255
5256        pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5257        memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
5258        memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
5259
5260
5261        psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
5262        if (psta)
5263                mac_id = (int)psta->mac_id;
5264        else
5265                mac_id = (-1);
5266
5267        pdel_sta_evt->mac_id = mac_id;
5268
5269        DBG_871X("report_del_sta_event: delete STA, mac_id =%d\n", mac_id);
5270
5271        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5272
5273        return;
5274}
5275
5276void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx)
5277{
5278        struct cmd_obj *pcmd_obj;
5279        u8 *pevtcmd;
5280        u32 cmdsz;
5281        struct stassoc_event            *padd_sta_evt;
5282        struct C2HEvent_Header  *pc2h_evt_hdr;
5283        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5284        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
5285
5286        pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj));
5287        if (pcmd_obj == NULL)
5288                return;
5289
5290        cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
5291        pevtcmd = rtw_zmalloc(cmdsz);
5292        if (pevtcmd == NULL) {
5293                kfree(pcmd_obj);
5294                return;
5295        }
5296
5297        INIT_LIST_HEAD(&pcmd_obj->list);
5298
5299        pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
5300        pcmd_obj->cmdsz = cmdsz;
5301        pcmd_obj->parmbuf = pevtcmd;
5302
5303        pcmd_obj->rsp = NULL;
5304        pcmd_obj->rspsz  = 0;
5305
5306        pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
5307        pc2h_evt_hdr->len = sizeof(struct stassoc_event);
5308        pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
5309        pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq);
5310
5311        padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
5312        memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
5313        padd_sta_evt->cam_id = cam_idx;
5314
5315        DBG_871X("report_add_sta_event: add STA\n");
5316
5317        rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
5318
5319        return;
5320}
5321
5322/****************************************************************************
5323
5324Following are the event callback functions
5325
5326*****************************************************************************/
5327
5328/* for sta/adhoc mode */
5329void update_sta_info(struct adapter *padapter, struct sta_info *psta)
5330{
5331        struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
5332        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5333        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5334
5335        /* ERP */
5336        VCS_update(padapter, psta);
5337
5338        /* HT */
5339        if (pmlmepriv->htpriv.ht_option) {
5340                psta->htpriv.ht_option = true;
5341
5342                psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
5343
5344                psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2;
5345
5346                if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))
5347                        psta->htpriv.sgi_20m = true;
5348
5349                if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))
5350                        psta->htpriv.sgi_40m = true;
5351
5352                psta->qos_option = true;
5353
5354                psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;
5355                psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;
5356                psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
5357
5358                memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct rtw_ieee80211_ht_cap));
5359        } else {
5360                psta->htpriv.ht_option = false;
5361
5362                psta->htpriv.ampdu_enable = false;
5363
5364                psta->htpriv.sgi_20m = false;
5365                psta->htpriv.sgi_40m = false;
5366                psta->qos_option = false;
5367
5368        }
5369
5370        psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
5371
5372        psta->htpriv.agg_enable_bitmap = 0x0;/* reset */
5373        psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */
5374
5375        psta->bw_mode = pmlmeext->cur_bwmode;
5376
5377        /* QoS */
5378        if (pmlmepriv->qospriv.qos_option)
5379                psta->qos_option = true;
5380
5381        update_ldpc_stbc_cap(psta);
5382
5383        spin_lock_bh(&psta->lock);
5384        psta->state = _FW_LINKED;
5385        spin_unlock_bh(&psta->lock);
5386
5387}
5388
5389static void rtw_mlmeext_disconnect(struct adapter *padapter)
5390{
5391        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
5392        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5393        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5394        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
5395
5396        /* set_opmode_cmd(padapter, infra_client_with_mlme); */
5397
5398        /*
5399         * For safety, prevent from keeping macid sleep.
5400         * If we can sure all power mode enter/leave are paired,
5401         * this check can be removed.
5402         * Lucas@20131113
5403         */
5404        /* wakeup macid after disconnect. */
5405        {
5406                struct sta_info *psta;
5407                psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
5408                if (psta)
5409                        rtw_hal_macid_wakeup(padapter, psta->mac_id);
5410        }
5411
5412        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
5413        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
5414
5415        /* set MSR to no link state -> infra. mode */
5416        Set_MSR(padapter, _HW_STATE_STATION_);
5417
5418        pmlmeinfo->state = WIFI_FW_NULL_STATE;
5419
5420        /* switch to the 20M Hz mode after disconnect */
5421        pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
5422        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
5423
5424        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5425
5426        flush_all_cam_entry(padapter);
5427
5428        del_timer_sync(&pmlmeext->link_timer);
5429
5430        /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */
5431        pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
5432        pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
5433
5434}
5435
5436void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
5437{
5438        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5439        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5440        struct wlan_bssid_ex            *cur_network = &(pmlmeinfo->network);
5441        struct sta_priv         *pstapriv = &padapter->stapriv;
5442        u8 join_type;
5443        struct sta_info *psta;
5444        if (join_res < 0) {
5445                join_type = 1;
5446                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5447                rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
5448
5449                goto exit_mlmeext_joinbss_event_callback;
5450        }
5451
5452        if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
5453                /* update bc/mc sta_info */
5454                update_bmc_sta(padapter);
5455
5456
5457        /* turn on dynamic functions */
5458        Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true);
5459
5460        /*  update IOT-releated issue */
5461        update_IOT_info(padapter);
5462
5463        rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
5464
5465        /* BCN interval */
5466        rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
5467
5468        /* udpate capability */
5469        update_capinfo(padapter, pmlmeinfo->capability);
5470
5471        /* WMM, Update EDCA param */
5472        WMMOnAssocRsp(padapter);
5473
5474        /* HT */
5475        HTOnAssocRsp(padapter);
5476
5477        /* Set cur_channel&cur_bwmode&cur_ch_offset */
5478        set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
5479
5480        psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
5481        if (psta) { /* only for infra. mode */
5482
5483                pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5484
5485                /* DBG_871X("set_sta_rate\n"); */
5486
5487                psta->wireless_mode = pmlmeext->cur_wireless_mode;
5488
5489                /* set per sta rate after updating HT cap. */
5490                set_sta_rate(padapter, psta);
5491
5492                rtw_sta_media_status_rpt(padapter, psta, 1);
5493
5494                /* wakeup macid after join bss successfully to ensure
5495                        the subsequent data frames can be sent out normally */
5496                rtw_hal_macid_wakeup(padapter, psta->mac_id);
5497        }
5498
5499        join_type = 2;
5500        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5501
5502        if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
5503                /*  correcting TSF */
5504                correct_TSF(padapter, pmlmeext);
5505
5506                /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5507        }
5508
5509        if (get_iface_type(padapter) == IFACE_PORT0)
5510                rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
5511
5512exit_mlmeext_joinbss_event_callback:
5513
5514        DBG_871X("=>%s\n", __func__);
5515
5516}
5517
5518/* currently only adhoc mode will go here */
5519void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta)
5520{
5521        struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
5522        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5523        u8 join_type;
5524
5525        DBG_871X("%s\n", __func__);
5526
5527        if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) {
5528                if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */
5529
5530                        /* nothing to do */
5531                } else { /* adhoc client */
5532                        /* update TSF Value */
5533                        /* update_TSF(pmlmeext, pframe, len); */
5534
5535                        /*  correcting TSF */
5536                        correct_TSF(padapter, pmlmeext);
5537
5538                        /* start beacon */
5539                        if (send_beacon(padapter) == _FAIL) {
5540                                pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
5541
5542                                pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
5543
5544                                return;
5545                        }
5546
5547                        pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
5548
5549                }
5550
5551                join_type = 2;
5552                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
5553        }
5554
5555        pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
5556
5557        psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates);
5558        memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen);
5559
5560        /* update adhoc sta_info */
5561        update_sta_info(padapter, psta);
5562
5563        rtw_hal_update_sta_rate_mask(padapter, psta);
5564
5565        /*  ToDo: HT for Ad-hoc */
5566        psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);
5567        psta->raid = networktype_to_raid_ex(padapter, psta);
5568
5569        /* rate radaptive */
5570        Update_RA_Entry(padapter, psta);
5571}
5572
5573void mlmeext_sta_del_event_callback(struct adapter *padapter)
5574{
5575        if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
5576                rtw_mlmeext_disconnect(padapter);
5577}
5578
5579/****************************************************************************
5580
5581Following are the functions for the timer handlers
5582
5583*****************************************************************************/
5584void _linked_info_dump(struct adapter *padapter)
5585{
5586        int i;
5587        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5588        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
5589        int UndecoratedSmoothedPWDB;
5590        struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
5591
5592        if (padapter->bLinkInfoDump) {
5593
5594                DBG_871X("\n ============["ADPT_FMT"] linked status check ===================\n", ADPT_ARG(padapter));
5595
5596                if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) {
5597                        rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
5598
5599                        DBG_871X("AP[" MAC_FMT "] - UndecoratedSmoothedPWDB:%d\n",
5600                                MAC_ARG(padapter->mlmepriv.cur_network.network.MacAddress), UndecoratedSmoothedPWDB);
5601                } else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_) {
5602                        struct list_head        *phead, *plist;
5603
5604                        struct sta_info *psta = NULL;
5605                        struct sta_priv *pstapriv = &padapter->stapriv;
5606
5607                        spin_lock_bh(&pstapriv->asoc_list_lock);
5608                        phead = &pstapriv->asoc_list;
5609                        plist = get_next(phead);
5610                        while (phead != plist) {
5611                                psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
5612                                plist = get_next(plist);
5613
5614                                DBG_871X("STA[" MAC_FMT "]:UndecoratedSmoothedPWDB:%d\n",
5615                                        MAC_ARG(psta->hwaddr), psta->rssi_stat.UndecoratedSmoothedPWDB);
5616                        }
5617                        spin_unlock_bh(&pstapriv->asoc_list_lock);
5618
5619                }
5620                for (i = 0; i < NUM_STA; i++) {
5621                        if (pdvobj->macid[i]) {
5622                                if (i != 1) /* skip bc/mc sta */
5623                                        /*   tx info ============ */
5624                                        rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i);
5625                        }
5626                }
5627                rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL);
5628
5629
5630        }
5631
5632
5633}
5634
5635static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta)
5636{
5637        u8 ret = false;
5638
5639        #ifdef DBG_EXPIRATION_CHK
5640        DBG_871X(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"
5641                                /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/
5642                                ", retry:%u\n"
5643                , FUNC_ADPT_ARG(padapter)
5644                , STA_RX_PKTS_DIFF_ARG(psta)
5645                , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts
5646                , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts
5647                /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts
5648                , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts
5649                , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts
5650                , pmlmeinfo->bcn_interval*/
5651                , pmlmeext->retry
5652        );
5653
5654        DBG_871X(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter)
5655                , padapter->xmitpriv.tx_pkts
5656                , pmlmeinfo->link_count
5657        );
5658        #endif
5659
5660        if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
5661                && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
5662                && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
5663        ) {
5664                ret = false;
5665        } else {
5666                ret = true;
5667        }
5668
5669        sta_update_last_rx_pkts(psta);
5670
5671        return ret;
5672}
5673
5674void linked_status_chk(struct adapter *padapter)
5675{
5676        u32 i;
5677        struct sta_info         *psta;
5678        struct xmit_priv        *pxmitpriv = &(padapter->xmitpriv);
5679        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5680        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5681        struct sta_priv         *pstapriv = &padapter->stapriv;
5682
5683
5684        if (is_client_associated_to_ap(padapter)) {
5685                /* linked infrastructure client mode */
5686
5687                int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
5688                int rx_chk_limit;
5689                int link_count_limit;
5690
5691                #if defined(DBG_ROAMING_TEST)
5692                rx_chk_limit = 1;
5693                #else
5694                rx_chk_limit = 8;
5695                #endif
5696                link_count_limit = 7; /*  16 sec */
5697
5698                /*  Marked by Kurt 20130715 */
5699                /*  For WiDi 3.5 and latered on, they don't ask WiDi sink to do roaming, so we could not check rx limit that strictly. */
5700                /*  todo: To check why we under miracast session, rx_chk would be false */
5701                psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
5702                if (psta != NULL) {
5703                        if (chk_ap_is_alive(padapter, psta) == false)
5704                                rx_chk = _FAIL;
5705
5706                        if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
5707                                tx_chk = _FAIL;
5708
5709                        {
5710                                if (rx_chk != _SUCCESS) {
5711                                        if (pmlmeext->retry == 0) {
5712                                                #ifdef DBG_EXPIRATION_CHK
5713                                                DBG_871X("issue_probereq to trigger probersp, retry =%d\n", pmlmeext->retry);
5714                                                #endif
5715                                                issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
5716                                                issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
5717                                                issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
5718                                        }
5719                                }
5720
5721                                if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) {
5722                                        #ifdef DBG_EXPIRATION_CHK
5723                                        DBG_871X("%s issue_nulldata 0\n", __func__);
5724                                        #endif
5725                                        tx_chk = issue_nulldata_in_interrupt(padapter, NULL);
5726                                }
5727                        }
5728
5729                        if (rx_chk == _FAIL) {
5730                                pmlmeext->retry++;
5731                                if (pmlmeext->retry > rx_chk_limit) {
5732                                        DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
5733                                                FUNC_ADPT_ARG(padapter));
5734                                        receive_disconnect(padapter, pmlmeinfo->network.MacAddress
5735                                                , WLAN_REASON_EXPIRATION_CHK);
5736                                        return;
5737                                }
5738                        } else {
5739                                pmlmeext->retry = 0;
5740                        }
5741
5742                        if (tx_chk == _FAIL) {
5743                                pmlmeinfo->link_count %= (link_count_limit+1);
5744                        } else {
5745                                pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
5746                                pmlmeinfo->link_count = 0;
5747                        }
5748
5749                } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */
5750        } else if (is_client_associated_to_ibss(padapter)) {
5751                /* linked IBSS mode */
5752                /* for each assoc list entry to check the rx pkt counter */
5753                for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) {
5754                        if (pmlmeinfo->FW_sta_info[i].status == 1) {
5755                                psta = pmlmeinfo->FW_sta_info[i].psta;
5756
5757                                if (NULL == psta)
5758                                        continue;
5759
5760                                if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) {
5761
5762                                        if (pmlmeinfo->FW_sta_info[i].retry < 3) {
5763                                                pmlmeinfo->FW_sta_info[i].retry++;
5764                                        } else {
5765                                                pmlmeinfo->FW_sta_info[i].retry = 0;
5766                                                pmlmeinfo->FW_sta_info[i].status = 0;
5767                                                report_del_sta_event(padapter, psta->hwaddr
5768                                                        , 65535/*  indicate disconnect caused by no rx */
5769                                                );
5770                                        }
5771                                } else {
5772                                        pmlmeinfo->FW_sta_info[i].retry = 0;
5773                                        pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
5774                                }
5775                        }
5776                }
5777
5778                /* set_link_timer(pmlmeext, DISCONNECT_TO); */
5779
5780        }
5781
5782}
5783
5784void survey_timer_hdl(struct timer_list *t)
5785{
5786        struct adapter *padapter =
5787                from_timer(padapter, t, mlmeextpriv.survey_timer);
5788        struct cmd_obj  *ph2c;
5789        struct sitesurvey_parm  *psurveyPara;
5790        struct cmd_priv                                 *pcmdpriv = &padapter->cmdpriv;
5791        struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
5792
5793        /* DBG_871X("marc: survey timer\n"); */
5794
5795        /* issue rtw_sitesurvey_cmd */
5796        if (pmlmeext->sitesurvey_res.state > SCAN_START) {
5797                if (pmlmeext->sitesurvey_res.state ==  SCAN_PROCESS) {
5798                        pmlmeext->sitesurvey_res.channel_idx++;
5799                }
5800
5801                if (pmlmeext->scan_abort) {
5802                        {
5803                                pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num;
5804                                DBG_871X("%s idx:%d\n", __func__
5805                                        , pmlmeext->sitesurvey_res.channel_idx
5806                                );
5807                        }
5808
5809                        pmlmeext->scan_abort = false;/* reset */
5810                }
5811
5812                ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
5813                if (ph2c == NULL) {
5814                        goto exit_survey_timer_hdl;
5815                }
5816
5817                psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm));
5818                if (psurveyPara == NULL) {
5819                        kfree(ph2c);
5820                        goto exit_survey_timer_hdl;
5821                }
5822
5823                init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
5824                rtw_enqueue_cmd(pcmdpriv, ph2c);
5825        }
5826
5827
5828exit_survey_timer_hdl:
5829
5830        return;
5831}
5832
5833void link_timer_hdl(struct timer_list *t)
5834{
5835        struct adapter *padapter =
5836                from_timer(padapter, t, mlmeextpriv.link_timer);
5837        /* static unsigned int          rx_pkt = 0; */
5838        /* static u64                           tx_cnt = 0; */
5839        /* struct xmit_priv     *pxmitpriv = &(padapter->xmitpriv); */
5840        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
5841        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
5842        /* struct sta_priv      *pstapriv = &padapter->stapriv; */
5843
5844
5845        if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) {
5846                DBG_871X("link_timer_hdl:no beacon while connecting\n");
5847                pmlmeinfo->state = WIFI_FW_NULL_STATE;
5848                report_join_res(padapter, -3);
5849        } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) {
5850                /* re-auth timer */
5851                if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) {
5852                        /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */
5853                        /*  */
5854                                pmlmeinfo->state = 0;
5855                                report_join_res(padapter, -1);
5856                                return;
5857                        /*  */
5858                        /* else */
5859                        /*  */
5860                        /*      pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */
5861                        /*      pmlmeinfo->reauth_count = 0; */
5862                        /*  */
5863                }
5864
5865                DBG_871X("link_timer_hdl: auth timeout and try again\n");
5866                pmlmeinfo->auth_seq = 1;
5867                issue_auth(padapter, NULL, 0);
5868                set_link_timer(pmlmeext, REAUTH_TO);
5869        } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) {
5870                /* re-assoc timer */
5871                if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) {
5872                        pmlmeinfo->state = WIFI_FW_NULL_STATE;
5873                        report_join_res(padapter, -2);
5874                        return;
5875                }
5876
5877                DBG_871X("link_timer_hdl: assoc timeout and try again\n");
5878                issue_assocreq(padapter);
5879                set_link_timer(pmlmeext, REASSOC_TO);
5880        }
5881
5882        return;
5883}
5884
5885void addba_timer_hdl(struct timer_list *t)
5886{
5887        struct sta_info *psta = from_timer(psta, t, addba_retry_timer);
5888        struct ht_priv *phtpriv;
5889
5890        if (!psta)
5891                return;
5892
5893        phtpriv = &psta->htpriv;
5894
5895        if (phtpriv->ht_option && phtpriv->ampdu_enable) {
5896                if (phtpriv->candidate_tid_bitmap)
5897                        phtpriv->candidate_tid_bitmap = 0x0;
5898
5899        }
5900}
5901
5902void sa_query_timer_hdl(struct timer_list *t)
5903{
5904        struct adapter *padapter =
5905                from_timer(padapter, t, mlmeextpriv.sa_query_timer);
5906        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
5907        /* disconnect */
5908        spin_lock_bh(&pmlmepriv->lock);
5909
5910        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
5911                rtw_disassoc_cmd(padapter, 0, true);
5912                rtw_indicate_disconnect(padapter);
5913                rtw_free_assoc_resources(padapter, 1);
5914        }
5915
5916        spin_unlock_bh(&pmlmepriv->lock);
5917        DBG_871X("SA query timeout disconnect\n");
5918}
5919
5920u8 NULL_hdl(struct adapter *padapter, u8 *pbuf)
5921{
5922        return H2C_SUCCESS;
5923}
5924
5925#ifdef CONFIG_AUTO_AP_MODE
5926static int rtw_auto_ap_start_beacon(struct adapter *adapter)
5927{
5928        int ret = 0;
5929        u8 *pbuf = NULL;
5930        uint len;
5931        u8 supportRate[16];
5932        int     sz = 0, rateLen;
5933        u8 *ie;
5934        u8 wireless_mode, oper_channel;
5935        u8 ssid[3] = {0}; /* hidden ssid */
5936        u32 ssid_len = sizeof(ssid);
5937        struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
5938
5939
5940        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true)
5941                return -EINVAL;
5942
5943
5944        len = 128;
5945        pbuf = rtw_zmalloc(len);
5946        if (!pbuf)
5947                return -ENOMEM;
5948
5949
5950        /* generate beacon */
5951        ie = pbuf;
5952
5953        /* timestamp will be inserted by hardware */
5954        sz += 8;
5955        ie += sz;
5956
5957        /* beacon interval : 2bytes */
5958        *(u16 *)ie = cpu_to_le16((u16)100);/* BCN_INTERVAL = 100; */
5959        sz += 2;
5960        ie += 2;
5961
5962        /* capability info */
5963        *(u16 *)ie = 0;
5964        *(u16 *)ie |= cpu_to_le16(cap_ESS);
5965        *(u16 *)ie |= cpu_to_le16(cap_ShortPremble);
5966        /* u16*)ie |= cpu_to_le16(cap_Privacy); */
5967        sz += 2;
5968        ie += 2;
5969
5970        /* SSID */
5971        ie = rtw_set_ie(ie, _SSID_IE_, ssid_len, ssid, &sz);
5972
5973        /* supported rates */
5974        wireless_mode = WIRELESS_11BG_24N;
5975        rtw_set_supported_rate(supportRate, wireless_mode);
5976        rateLen = rtw_get_rateset_len(supportRate);
5977        if (rateLen > 8) {
5978                ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, supportRate, &sz);
5979        } else {
5980                ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, supportRate, &sz);
5981        }
5982
5983
5984        /* DS parameter set */
5985        if (check_buddy_fwstate(adapter, _FW_LINKED) &&
5986                check_buddy_fwstate(adapter, WIFI_STATION_STATE)) {
5987                struct adapter *pbuddystruct adapter = adapter->pbuddystruct adapter;
5988                struct mlme_ext_priv *pbuddy_mlmeext  = &pbuddystruct adapter->mlmeextpriv;
5989
5990                oper_channel = pbuddy_mlmeext->cur_channel;
5991        } else {
5992                oper_channel = adapter_to_dvobj(adapter)->oper_channel;
5993        }
5994        ie = rtw_set_ie(ie, _DSSET_IE_, 1, &oper_channel, &sz);
5995
5996        /* ext supported rates */
5997        if (rateLen > 8) {
5998                ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz);
5999        }
6000
6001        DBG_871X("%s, start auto ap beacon sz =%d\n", __func__, sz);
6002
6003        /* lunch ap mode & start to issue beacon */
6004        if (rtw_check_beacon_data(adapter, pbuf,  sz) == _SUCCESS) {
6005
6006        } else {
6007                ret = -EINVAL;
6008        }
6009
6010
6011        kfree(pbuf);
6012
6013        return ret;
6014
6015}
6016#endif/* CONFIG_AUTO_AP_MODE */
6017
6018u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf)
6019{
6020        u8 type;
6021        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6022        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6023        struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
6024
6025        if (psetop->mode == Ndis802_11APMode) {
6026                pmlmeinfo->state = WIFI_FW_AP_STATE;
6027                type = _HW_STATE_AP_;
6028                /* start_ap_mode(padapter); */
6029        } else if (psetop->mode == Ndis802_11Infrastructure) {
6030                pmlmeinfo->state &= ~(BIT(0)|BIT(1));/*  clear state */
6031                pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to     STATION_STATE */
6032                type = _HW_STATE_STATION_;
6033        } else if (psetop->mode == Ndis802_11IBSS) {
6034                type = _HW_STATE_ADHOC_;
6035        } else {
6036                type = _HW_STATE_NOLINK_;
6037        }
6038
6039        rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
6040        /* Set_MSR(padapter, type); */
6041
6042
6043#ifdef CONFIG_AUTO_AP_MODE
6044        if (psetop->mode == Ndis802_11APMode)
6045                rtw_auto_ap_start_beacon(padapter);
6046#endif
6047
6048        if (psetop->mode == Ndis802_11APMode) {
6049                /*  Do this after port switch to */
6050                /*  prevent from downloading rsvd page to wrong port */
6051                rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */
6052        }
6053
6054        return H2C_SUCCESS;
6055
6056}
6057
6058u8 createbss_hdl(struct adapter *padapter, u8 *pbuf)
6059{
6060        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6061        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6062        struct wlan_bssid_ex    *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
6063        struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf;
6064        /* u32 initialgain; */
6065
6066        if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
6067                struct wlan_bssid_ex *network = &padapter->mlmepriv.cur_network.network;
6068                start_bss_network(padapter, (u8 *)network);
6069                return H2C_SUCCESS;
6070        }
6071
6072        /* below is for ad-hoc master */
6073        if (pparm->network.InfrastructureMode == Ndis802_11IBSS) {
6074                rtw_joinbss_reset(padapter);
6075
6076                pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
6077                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6078                pmlmeinfo->ERP_enable = 0;
6079                pmlmeinfo->WMM_enable = 0;
6080                pmlmeinfo->HT_enable = 0;
6081                pmlmeinfo->HT_caps_enable = 0;
6082                pmlmeinfo->HT_info_enable = 0;
6083                pmlmeinfo->agg_enable_bitmap = 0;
6084                pmlmeinfo->candidate_tid_bitmap = 0;
6085
6086                /* disable dynamic functions, such as high power, DIG */
6087                Save_DM_Func_Flag(padapter);
6088                Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
6089
6090                /* config the initial gain under linking, need to write the BB registers */
6091                /* initialgain = 0x1E; */
6092                /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
6093
6094                /* cancel link timer */
6095                del_timer_sync(&pmlmeext->link_timer);
6096
6097                /* clear CAM */
6098                flush_all_cam_entry(padapter);
6099
6100                memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
6101                pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
6102
6103                if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
6104                        return H2C_PARAMETERS_ERROR;
6105
6106                memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
6107
6108                start_create_ibss(padapter);
6109
6110        }
6111
6112        return H2C_SUCCESS;
6113
6114}
6115
6116u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf)
6117{
6118        u8 join_type;
6119        struct ndis_80211_var_ie *pIE;
6120        struct registry_priv *pregpriv = &padapter->registrypriv;
6121        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6122        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6123        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
6124        u32 i;
6125        u8 cbw40_enable = 0;
6126        /* u32 initialgain; */
6127        /* u32 acparm; */
6128        u8 ch, bw, offset;
6129
6130        /* check already connecting to AP or not */
6131        if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) {
6132                if (pmlmeinfo->state & WIFI_FW_STATION_STATE) {
6133                        issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
6134                }
6135                pmlmeinfo->state = WIFI_FW_NULL_STATE;
6136
6137                /* clear CAM */
6138                flush_all_cam_entry(padapter);
6139
6140                del_timer_sync(&pmlmeext->link_timer);
6141
6142                /* set MSR to nolink -> infra. mode */
6143                /* Set_MSR(padapter, _HW_STATE_NOLINK_); */
6144                Set_MSR(padapter, _HW_STATE_STATION_);
6145
6146
6147                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL);
6148        }
6149
6150        rtw_joinbss_reset(padapter);
6151
6152        pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
6153        pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6154        pmlmeinfo->ERP_enable = 0;
6155        pmlmeinfo->WMM_enable = 0;
6156        pmlmeinfo->HT_enable = 0;
6157        pmlmeinfo->HT_caps_enable = 0;
6158        pmlmeinfo->HT_info_enable = 0;
6159        pmlmeinfo->agg_enable_bitmap = 0;
6160        pmlmeinfo->candidate_tid_bitmap = 0;
6161        pmlmeinfo->bwmode_updated = false;
6162        /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */
6163        pmlmeinfo->VHT_enable = 0;
6164
6165        memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength));
6166        pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength;
6167
6168        if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */
6169                return H2C_PARAMETERS_ERROR;
6170
6171        memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength);
6172
6173        pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
6174        pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
6175
6176        /* Check AP vendor to move rtw_joinbss_cmd() */
6177        /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */
6178
6179        /* sizeof(struct ndis_802_11_fix_ie) */
6180        for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) {
6181                pIE = (struct ndis_80211_var_ie *)(pnetwork->IEs + i);
6182
6183                switch (pIE->ElementID) {
6184                case _VENDOR_SPECIFIC_IE_:/* Get WMM IE. */
6185                        if (!memcmp(pIE->data, WMM_OUI, 4))
6186                                WMM_param_handler(padapter, pIE);
6187                        break;
6188
6189                case _HT_CAPABILITY_IE_:        /* Get HT Cap IE. */
6190                        pmlmeinfo->HT_caps_enable = 1;
6191                        break;
6192
6193                case _HT_EXTRA_INFO_IE_:        /* Get HT Info IE. */
6194                        pmlmeinfo->HT_info_enable = 1;
6195
6196                        /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */
6197                        {
6198                                struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data);
6199
6200                                if (pnetwork->Configuration.DSConfig > 14) {
6201                                        if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20)
6202                                                cbw40_enable = 1;
6203                                } else {
6204                                        if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20)
6205                                                cbw40_enable = 1;
6206                                }
6207
6208                                if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) {
6209                                        /* switch to the 40M Hz mode according to the AP */
6210                                        pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
6211                                        switch (pht_info->infos[0] & 0x3) {
6212                                        case 1:
6213                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
6214                                                break;
6215
6216                                        case 3:
6217                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
6218                                                break;
6219
6220                                        default:
6221                                                pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6222                                                pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
6223                                                break;
6224                                        }
6225
6226                                        DBG_871X("set HT ch/bw before connected\n");
6227                                }
6228                        }
6229                        break;
6230                default:
6231                        break;
6232                }
6233
6234                i += (pIE->Length + 2);
6235        }
6236
6237        /* check channel, bandwidth, offset and switch */
6238        if (rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) {
6239                report_join_res(padapter, (-4));
6240                return H2C_SUCCESS;
6241        }
6242
6243        /* disable dynamic functions, such as high power, DIG */
6244        /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */
6245
6246        /* config the initial gain under linking, need to write the BB registers */
6247        /* initialgain = 0x1E; */
6248        /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */
6249
6250        rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
6251        join_type = 0;
6252        rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
6253        rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL);
6254
6255        set_channel_bwmode(padapter, ch, offset, bw);
6256
6257        /* cancel link timer */
6258        del_timer_sync(&pmlmeext->link_timer);
6259
6260        start_clnt_join(padapter);
6261
6262        return H2C_SUCCESS;
6263
6264}
6265
6266u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
6267{
6268        struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
6269        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6270        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6271        struct wlan_bssid_ex            *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network));
6272        u8 val8;
6273
6274        if (is_client_associated_to_ap(padapter)) {
6275                        issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
6276        }
6277
6278        if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
6279                /* Stop BCN */
6280                val8 = 0;
6281                rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
6282        }
6283
6284        rtw_mlmeext_disconnect(padapter);
6285
6286        rtw_free_uc_swdec_pending_queue(padapter);
6287
6288        return  H2C_SUCCESS;
6289}
6290
6291static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out,
6292        u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
6293{
6294        int i, j;
6295        int set_idx;
6296        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6297
6298        /* clear first */
6299        memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
6300
6301        /* acquire channels from in */
6302        j = 0;
6303        for (i = 0; i < in_num; i++) {
6304
6305                DBG_871X(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
6306
6307                set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value);
6308                if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED)
6309                        && set_idx >= 0
6310                        && rtw_mlme_band_check(padapter, in[i].hw_value)
6311                ) {
6312                        if (j >= out_num) {
6313                                DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
6314                                        FUNC_ADPT_ARG(padapter), out_num);
6315                                break;
6316                        }
6317
6318                        memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
6319
6320                        if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
6321                                out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
6322
6323                        j++;
6324                }
6325                if (j >= out_num)
6326                        break;
6327        }
6328
6329        /* if out is empty, use channel_set as default */
6330        if (j == 0) {
6331                for (i = 0; i < pmlmeext->max_chan_nums; i++) {
6332
6333                        DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), pmlmeext->channel_set[i].ChannelNum);
6334
6335                        if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum)) {
6336
6337                                if (j >= out_num) {
6338                                        DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
6339                                                FUNC_ADPT_ARG(padapter), out_num);
6340                                        break;
6341                                }
6342
6343                                out[j].hw_value = pmlmeext->channel_set[i].ChannelNum;
6344
6345                                if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
6346                                        out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
6347
6348                                j++;
6349                        }
6350                }
6351        }
6352
6353        return j;
6354}
6355
6356u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf)
6357{
6358        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6359        struct sitesurvey_parm  *pparm = (struct sitesurvey_parm *)pbuf;
6360        u8 bdelayscan = false;
6361        u8 val8;
6362        u32 initialgain;
6363        u32 i;
6364
6365        if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) {
6366                pmlmeext->sitesurvey_res.state = SCAN_START;
6367                pmlmeext->sitesurvey_res.bss_cnt = 0;
6368                pmlmeext->sitesurvey_res.channel_idx = 0;
6369
6370                for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
6371                        if (pparm->ssid[i].SsidLength) {
6372                                memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
6373                                pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength;
6374                        } else {
6375                                pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0;
6376                        }
6377                }
6378
6379                pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter
6380                        , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT
6381                        , pparm->ch, pparm->ch_num
6382                );
6383
6384                pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode;
6385
6386                /* issue null data if associating to the AP */
6387                if (is_client_associated_to_ap(padapter)) {
6388                        pmlmeext->sitesurvey_res.state = SCAN_TXNULL;
6389
6390                        issue_nulldata(padapter, NULL, 1, 3, 500);
6391
6392                        bdelayscan = true;
6393                }
6394                if (bdelayscan) {
6395                        /* delay 50ms to protect nulldata(1). */
6396                        set_survey_timer(pmlmeext, 50);
6397                        return H2C_SUCCESS;
6398                }
6399        }
6400
6401        if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) {
6402                /* disable dynamic functions, such as high power, DIG */
6403                Save_DM_Func_Flag(padapter);
6404                Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false);
6405
6406                /* config the initial gain under scaning, need to write the BB registers */
6407                initialgain = 0x1e;
6408
6409                rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain));
6410
6411                /* set MSR to no link state */
6412                Set_MSR(padapter, _HW_STATE_NOLINK_);
6413
6414                val8 = 1; /* under site survey */
6415                rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
6416
6417                pmlmeext->sitesurvey_res.state = SCAN_PROCESS;
6418        }
6419
6420        site_survey(padapter);
6421
6422        return H2C_SUCCESS;
6423
6424}
6425
6426u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf)
6427{
6428        struct setauth_parm             *pparm = (struct setauth_parm *)pbuf;
6429        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6430        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6431
6432        if (pparm->mode < 4)
6433                pmlmeinfo->auth_algo = pparm->mode;
6434
6435        return  H2C_SUCCESS;
6436}
6437
6438u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
6439{
6440        u16 ctrl = 0;
6441        s16 cam_id = 0;
6442        struct setkey_parm              *pparm = (struct setkey_parm *)pbuf;
6443        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6444        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6445        unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
6446        u8 *addr;
6447
6448        /* main tx key for wep. */
6449        if (pparm->set_tx)
6450                pmlmeinfo->key_index = pparm->keyid;
6451
6452        cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid);
6453
6454        if (cam_id < 0) {
6455        } else {
6456                if (cam_id > 3) /* not default key, searched by A2 */
6457                        addr = get_bssid(&padapter->mlmepriv);
6458                else
6459                        addr = null_addr;
6460
6461                ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid;
6462                write_cam(padapter, cam_id, ctrl, addr, pparm->key);
6463                DBG_871X_LEVEL(_drv_always_, "set group key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n"
6464                        , cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm));
6465        }
6466
6467        if (cam_id >= 0 && cam_id <= 3)
6468                rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true);
6469
6470        /* allow multicast packets to driver */
6471        padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
6472
6473        return H2C_SUCCESS;
6474}
6475
6476u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf)
6477{
6478        u16 ctrl = 0;
6479        s16 cam_id = 0;
6480        u8 ret = H2C_SUCCESS;
6481        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6482        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6483        struct set_stakey_parm  *pparm = (struct set_stakey_parm *)pbuf;
6484        struct sta_priv *pstapriv = &padapter->stapriv;
6485        struct sta_info *psta;
6486
6487        if (pparm->algorithm == _NO_PRIVACY_)
6488                goto write_to_cam;
6489
6490        psta = rtw_get_stainfo(pstapriv, pparm->addr);
6491        if (!psta) {
6492                DBG_871X_LEVEL(_drv_always_, "%s sta:"MAC_FMT" not found\n", __func__, MAC_ARG(pparm->addr));
6493                ret = H2C_REJECTED;
6494                goto exit;
6495        }
6496
6497        pmlmeinfo->enc_algo = pparm->algorithm;
6498        cam_id = rtw_camid_alloc(padapter, psta, 0);
6499        if (cam_id < 0)
6500                goto exit;
6501
6502write_to_cam:
6503        if (pparm->algorithm == _NO_PRIVACY_) {
6504                while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) {
6505                        DBG_871X_LEVEL(_drv_always_, "clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), cam_id);
6506                        clear_cam_entry(padapter, cam_id);
6507                        rtw_camid_free(padapter, cam_id);
6508                }
6509        } else {
6510                DBG_871X_LEVEL(_drv_always_, "set pairwise key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n",
6511                        cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm));
6512                ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
6513                write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
6514        }
6515        ret = H2C_SUCCESS_RSP;
6516
6517exit:
6518        return ret;
6519}
6520
6521u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf)
6522{
6523        struct addBaReq_parm    *pparm = (struct addBaReq_parm *)pbuf;
6524        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6525        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6526
6527        struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
6528
6529        if (!psta)
6530                return  H2C_SUCCESS;
6531
6532        if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
6533                ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
6534                /* pmlmeinfo->ADDBA_retry_count = 0; */
6535                /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */
6536                /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */
6537                issue_action_BA(padapter, pparm->addr, RTW_WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid);
6538                /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */
6539                _set_timer(&psta->addba_retry_timer, ADDBA_TO);
6540        } else {
6541                psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);
6542        }
6543        return  H2C_SUCCESS;
6544}
6545
6546
6547u8 chk_bmc_sleepq_cmd(struct adapter *padapter)
6548{
6549        struct cmd_obj *ph2c;
6550        struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
6551        u8 res = _SUCCESS;
6552
6553        ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
6554        if (ph2c == NULL) {
6555                res = _FAIL;
6556                goto exit;
6557        }
6558
6559        init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));
6560
6561        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
6562
6563exit:
6564        return res;
6565}
6566
6567u8 set_tx_beacon_cmd(struct adapter *padapter)
6568{
6569        struct cmd_obj  *ph2c;
6570        struct Tx_Beacon_param  *ptxBeacon_parm;
6571        struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
6572        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6573        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
6574        u8 res = _SUCCESS;
6575        int len_diff = 0;
6576
6577        ph2c = rtw_zmalloc(sizeof(struct cmd_obj));
6578        if (ph2c == NULL) {
6579                res = _FAIL;
6580                goto exit;
6581        }
6582
6583        ptxBeacon_parm = rtw_zmalloc(sizeof(struct Tx_Beacon_param));
6584        if (ptxBeacon_parm == NULL) {
6585                kfree(ph2c);
6586                res = _FAIL;
6587                goto exit;
6588        }
6589
6590        memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex));
6591
6592        len_diff = update_hidden_ssid(
6593                ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_
6594                , ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_
6595                , pmlmeinfo->hidden_ssid_mode
6596        );
6597        ptxBeacon_parm->network.IELength += len_diff;
6598
6599        init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
6600
6601        res = rtw_enqueue_cmd(pcmdpriv, ph2c);
6602
6603exit:
6604        return res;
6605}
6606
6607
6608u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf)
6609{
6610        u8 evt_code, evt_seq;
6611        u16 evt_sz;
6612        uint    *peventbuf;
6613        void (*event_callback)(struct adapter *dev, u8 *pbuf);
6614        struct evt_priv *pevt_priv = &(padapter->evtpriv);
6615
6616        if (pbuf == NULL)
6617                goto _abort_event_;
6618
6619        peventbuf = (uint *)pbuf;
6620        evt_sz = (u16)(*peventbuf&0xffff);
6621        evt_seq = (u8)((*peventbuf>>24)&0x7f);
6622        evt_code = (u8)((*peventbuf>>16)&0xff);
6623
6624
6625        #ifdef CHECK_EVENT_SEQ
6626        /*  checking event sequence... */
6627        if (evt_seq != (atomic_read(&pevt_priv->event_seq) & 0x7f)) {
6628                RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_,
6629                         ("Event Seq Error! %d vs %d\n", (evt_seq & 0x7f),
6630                          (atomic_read(&pevt_priv->event_seq) & 0x7f)));
6631
6632                pevt_priv->event_seq = (evt_seq+1)&0x7f;
6633
6634                goto _abort_event_;
6635        }
6636        #endif
6637
6638        /*  checking if event code is valid */
6639        if (evt_code >= MAX_C2HEVT) {
6640                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code));
6641                goto _abort_event_;
6642        }
6643
6644        /*  checking if event size match the event parm size */
6645        if ((wlanevents[evt_code].parmsize != 0) &&
6646                        (wlanevents[evt_code].parmsize != evt_sz)) {
6647
6648                RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n",
6649                        evt_code, wlanevents[evt_code].parmsize, evt_sz));
6650                goto _abort_event_;
6651
6652        }
6653
6654        atomic_inc(&pevt_priv->event_seq);
6655
6656        peventbuf += 2;
6657
6658        if (peventbuf) {
6659                event_callback = wlanevents[evt_code].event_callback;
6660                event_callback(padapter, (u8 *)peventbuf);
6661
6662                pevt_priv->evt_done_cnt++;
6663        }
6664
6665
6666_abort_event_:
6667
6668
6669        return H2C_SUCCESS;
6670
6671}
6672
6673u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf)
6674{
6675        if (!pbuf)
6676                return H2C_PARAMETERS_ERROR;
6677
6678        return H2C_SUCCESS;
6679}
6680
6681u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf)
6682{
6683        struct sta_info *psta_bmc;
6684        struct list_head        *xmitframe_plist, *xmitframe_phead;
6685        struct xmit_frame *pxmitframe = NULL;
6686        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
6687        struct sta_priv  *pstapriv = &padapter->stapriv;
6688
6689        /* for BC/MC Frames */
6690        psta_bmc = rtw_get_bcmc_stainfo(padapter);
6691        if (!psta_bmc)
6692                return H2C_SUCCESS;
6693
6694        if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) {
6695                msleep(10);/*  10ms, ATIM(HIQ) Windows */
6696
6697                /* spin_lock_bh(&psta_bmc->sleep_q.lock); */
6698                spin_lock_bh(&pxmitpriv->lock);
6699
6700                xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
6701                xmitframe_plist = get_next(xmitframe_phead);
6702
6703                while (xmitframe_phead != xmitframe_plist) {
6704                        pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
6705
6706                        xmitframe_plist = get_next(xmitframe_plist);
6707
6708                        list_del_init(&pxmitframe->list);
6709
6710                        psta_bmc->sleepq_len--;
6711                        if (psta_bmc->sleepq_len > 0)
6712                                pxmitframe->attrib.mdata = 1;
6713                        else
6714                                pxmitframe->attrib.mdata = 0;
6715
6716                        pxmitframe->attrib.triggered = 1;
6717
6718                        if (xmitframe_hiq_filter(pxmitframe))
6719                                pxmitframe->attrib.qsel = 0x11;/* HIQ */
6720
6721                        rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
6722                }
6723
6724                /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
6725                spin_unlock_bh(&pxmitpriv->lock);
6726
6727                /* check hi queue and bmc_sleepq */
6728                rtw_chk_hi_queue_cmd(padapter);
6729        }
6730
6731        return H2C_SUCCESS;
6732}
6733
6734u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf)
6735{
6736        if (send_beacon(padapter) == _FAIL) {
6737                DBG_871X("issue_beacon, fail!\n");
6738                return H2C_PARAMETERS_ERROR;
6739        }
6740
6741        /* tx bc/mc frames after update TIM */
6742        chk_bmc_sleepq_hdl(padapter, NULL);
6743
6744        return H2C_SUCCESS;
6745}
6746
6747int rtw_chk_start_clnt_join(struct adapter *padapter, u8 *ch, u8 *bw, u8 *offset)
6748{
6749        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6750        unsigned char cur_ch = pmlmeext->cur_channel;
6751        unsigned char cur_bw = pmlmeext->cur_bwmode;
6752        unsigned char cur_ch_offset = pmlmeext->cur_ch_offset;
6753        bool connect_allow = true;
6754
6755        if (!ch || !bw || !offset) {
6756                rtw_warn_on(1);
6757                connect_allow = false;
6758        }
6759
6760        if (connect_allow) {
6761                DBG_871X("start_join_set_ch_bw: ch =%d, bwmode =%d, ch_offset =%d\n", cur_ch, cur_bw, cur_ch_offset);
6762                *ch = cur_ch;
6763                *bw = cur_bw;
6764                *offset = cur_ch_offset;
6765        }
6766
6767        return connect_allow ? _SUCCESS : _FAIL;
6768}
6769
6770/* Find union about ch, bw, ch_offset of all linked/linking interfaces */
6771int rtw_get_ch_setting_union(struct adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
6772{
6773        struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
6774        struct adapter *iface;
6775
6776        if (ch)
6777                *ch = 0;
6778        if (bw)
6779                *bw = CHANNEL_WIDTH_20;
6780        if (offset)
6781                *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
6782
6783        iface = dvobj->padapters;
6784
6785        if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING))
6786                return 0;
6787
6788        return 1;
6789}
6790
6791u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf)
6792{
6793        struct set_ch_parm *set_ch_parm;
6794        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6795
6796        if (!pbuf)
6797                return H2C_PARAMETERS_ERROR;
6798
6799        set_ch_parm = (struct set_ch_parm *)pbuf;
6800
6801        DBG_871X(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
6802                FUNC_NDEV_ARG(padapter->pnetdev),
6803                set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
6804
6805        pmlmeext->cur_channel = set_ch_parm->ch;
6806        pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
6807        pmlmeext->cur_bwmode = set_ch_parm->bw;
6808
6809        set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
6810
6811        return  H2C_SUCCESS;
6812}
6813
6814u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf)
6815{
6816        struct SetChannelPlan_param *setChannelPlan_param;
6817        struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
6818
6819        if (!pbuf)
6820                return H2C_PARAMETERS_ERROR;
6821
6822        setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
6823
6824        pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
6825        init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
6826
6827        if ((padapter->rtw_wdev != NULL) && (padapter->rtw_wdev->wiphy)) {
6828                struct regulatory_request request;
6829                request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
6830                rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request);
6831        }
6832
6833        return  H2C_SUCCESS;
6834}
6835
6836u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf)
6837{
6838        struct LedBlink_param *ledBlink_param;
6839
6840        if (!pbuf)
6841                return H2C_PARAMETERS_ERROR;
6842
6843        ledBlink_param = (struct LedBlink_param *)pbuf;
6844        return  H2C_SUCCESS;
6845}
6846
6847u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf)
6848{
6849        return  H2C_REJECTED;
6850}
6851
6852/*  TDLS_ESTABLISHED    : write RCR DATA BIT */
6853/*  TDLS_CS_OFF         : go back to the channel linked with AP, terminating channel switch procedure */
6854/*  TDLS_INIT_CH_SEN    : init channel sensing, receive all data and mgnt frame */
6855/*  TDLS_DONE_CH_SEN: channel sensing and report candidate channel */
6856/*  TDLS_OFF_CH         : first time set channel to off channel */
6857/*  TDLS_BASE_CH                : go back tp the channel linked with AP when set base channel as target channel */
6858/*  TDLS_P_OFF_CH       : periodically go to off channel */
6859/*  TDLS_P_BASE_CH      : periodically go back to base channel */
6860/*  TDLS_RS_RCR         : restore RCR */
6861/*  TDLS_TEAR_STA       : free tdls sta */
6862u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf)
6863{
6864        return H2C_REJECTED;
6865}
6866
6867u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf)
6868{
6869        struct RunInThread_param *p;
6870
6871
6872        if (NULL == pbuf)
6873                return H2C_PARAMETERS_ERROR;
6874        p = (struct RunInThread_param *)pbuf;
6875
6876        if (p->func)
6877                p->func(p->context);
6878
6879        return H2C_SUCCESS;
6880}
6881