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