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