158391efdSNathan Chancellor // SPDX-License-Identifier: GPL-2.0 2554c0a3aSHans de Goede /****************************************************************************** 3554c0a3aSHans de Goede * 4554c0a3aSHans de Goede * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. 5554c0a3aSHans de Goede * 6554c0a3aSHans de Goede ******************************************************************************/ 7554c0a3aSHans de Goede #define _RTW_MLME_EXT_C_ 8554c0a3aSHans de Goede 9554c0a3aSHans de Goede #include <drv_types.h> 10554c0a3aSHans de Goede #include <rtw_debug.h> 11554c0a3aSHans de Goede #include <rtw_wifi_regd.h> 12d312a47fSNishka Dasgupta #include <hal_btcoex.h> 1360db8d10SJérémy Lefaure #include <linux/kernel.h> 14d48603afSRoss Schmidt #include <asm/unaligned.h> 15554c0a3aSHans de Goede 16554c0a3aSHans de Goede static struct mlme_handler mlme_sta_tbl[] = { 17554c0a3aSHans de Goede {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq}, 18554c0a3aSHans de Goede {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp}, 19554c0a3aSHans de Goede {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq}, 20554c0a3aSHans de Goede {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp}, 21554c0a3aSHans de Goede {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq}, 22554c0a3aSHans de Goede {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp}, 23554c0a3aSHans de Goede 24554c0a3aSHans de Goede /*---------------------------------------------------------- 25554c0a3aSHans de Goede below 2 are reserved 26554c0a3aSHans de Goede -----------------------------------------------------------*/ 27554c0a3aSHans de Goede {0, "DoReserved", &DoReserved}, 28554c0a3aSHans de Goede {0, "DoReserved", &DoReserved}, 29554c0a3aSHans de Goede {WIFI_BEACON, "OnBeacon", &OnBeacon}, 30554c0a3aSHans de Goede {WIFI_ATIM, "OnATIM", &OnAtim}, 31554c0a3aSHans de Goede {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc}, 32554c0a3aSHans de Goede {WIFI_AUTH, "OnAuth", &OnAuthClient}, 33554c0a3aSHans de Goede {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth}, 34554c0a3aSHans de Goede {WIFI_ACTION, "OnAction", &OnAction}, 35554c0a3aSHans de Goede {WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction}, 36554c0a3aSHans de Goede }; 37554c0a3aSHans de Goede 38554c0a3aSHans de Goede static struct action_handler OnAction_tbl[] = { 39554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct}, 40554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &DoReserved}, 41554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &DoReserved}, 42554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back}, 43554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public}, 44554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved}, 45554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved}, 46554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht}, 47554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query}, 48554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved}, 49554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved}, 50554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &DoReserved}, 51554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &DoReserved}, 52554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved}, 53554c0a3aSHans de Goede }; 54554c0a3aSHans de Goede 55554c0a3aSHans de Goede static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; 56554c0a3aSHans de Goede 57554c0a3aSHans de Goede /************************************************** 58554c0a3aSHans de Goede OUI definitions for the vendor specific IE 59554c0a3aSHans de Goede ***************************************************/ 60554c0a3aSHans de Goede unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; 61554c0a3aSHans de Goede unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02}; 62554c0a3aSHans de Goede unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; 63554c0a3aSHans de Goede unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09}; 64554c0a3aSHans de Goede unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A}; 65554c0a3aSHans de Goede 66554c0a3aSHans de Goede unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; 67554c0a3aSHans de Goede unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; 68554c0a3aSHans de Goede 69554c0a3aSHans de Goede static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20}; 70554c0a3aSHans de Goede 71554c0a3aSHans de Goede /******************************************************** 72554c0a3aSHans de Goede ChannelPlan definitions 73554c0a3aSHans de Goede *********************************************************/ 74554c0a3aSHans de Goede static RT_CHANNEL_PLAN_2G RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = { 75554c0a3aSHans de Goede {{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 */ 76554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */ 77554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */ 78554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */ 79554c0a3aSHans de Goede {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */ 80554c0a3aSHans de Goede {{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 */ 81554c0a3aSHans de Goede {{}, 0}, /* 0x06, RT_CHANNEL_DOMAIN_2G_NULL */ 82554c0a3aSHans de Goede }; 83554c0a3aSHans de Goede 84554c0a3aSHans de Goede static RT_CHANNEL_PLAN_5G RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = { 85554c0a3aSHans de Goede {{}, 0}, /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */ 86554c0a3aSHans de Goede {{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 */ 87554c0a3aSHans de Goede {{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 */ 88554c0a3aSHans de Goede {{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 */ 89554c0a3aSHans de Goede {{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 */ 90554c0a3aSHans de Goede {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */ 91554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */ 92554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12}, /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */ 93554c0a3aSHans de Goede {{149, 153, 157, 161, 165}, 5}, /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */ 94554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */ 95554c0a3aSHans de Goede {{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 */ 96554c0a3aSHans de Goede {{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 */ 97554c0a3aSHans de Goede {{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 */ 98554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */ 99554c0a3aSHans de Goede {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */ 100554c0a3aSHans de Goede {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15}, /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */ 101554c0a3aSHans de Goede {{56, 60, 64, 149, 153, 157, 161, 165}, 8}, /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */ 102554c0a3aSHans de Goede {{149, 153, 157, 161, 165}, 5}, /* 0x11, RT_CHANNEL_DOMAIN_5G_NCC3 */ 103554c0a3aSHans de Goede {{36, 40, 44, 48}, 4}, /* 0x12, RT_CHANNEL_DOMAIN_5G_ETSI4 */ 104554c0a3aSHans de Goede {{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 */ 105554c0a3aSHans de Goede {{149, 153, 157, 161}, 4}, /* 0x14, RT_CHANNEL_DOMAIN_5G_FCC8 */ 106554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x15, RT_CHANNEL_DOMAIN_5G_ETSI6 */ 107554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x16, RT_CHANNEL_DOMAIN_5G_ETSI7 */ 108554c0a3aSHans de Goede {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x17, RT_CHANNEL_DOMAIN_5G_ETSI8 */ 109554c0a3aSHans de Goede {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x18, RT_CHANNEL_DOMAIN_5G_ETSI9 */ 110554c0a3aSHans de Goede {{149, 153, 157, 161, 165}, 5}, /* 0x19, RT_CHANNEL_DOMAIN_5G_ETSI10 */ 111554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165}, 16}, /* 0x1A, RT_CHANNEL_DOMAIN_5G_ETSI11 */ 112554c0a3aSHans de Goede {{52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17}, /* 0x1B, RT_CHANNEL_DOMAIN_5G_NCC4 */ 113554c0a3aSHans de Goede {{149, 153, 157, 161}, 4}, /* 0x1C, RT_CHANNEL_DOMAIN_5G_ETSI12 */ 114554c0a3aSHans de Goede {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17}, /* 0x1D, RT_CHANNEL_DOMAIN_5G_FCC9 */ 115554c0a3aSHans de Goede {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140}, 12}, /* 0x1E, RT_CHANNEL_DOMAIN_5G_ETSI13 */ 116554c0a3aSHans de Goede {{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 */ 117554c0a3aSHans de Goede 118554c0a3aSHans de Goede /* Driver self defined for old channel plan Compatible , Remember to modify if have new channel plan definition ===== */ 119554c0a3aSHans de Goede {{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 */ 120554c0a3aSHans de Goede {{36, 40, 44, 48}, 4}, /* 0x21, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */ 121554c0a3aSHans de Goede {{36, 40, 44, 48, 149, 153, 157, 161}, 8}, /* 0x22, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */ 122554c0a3aSHans de Goede }; 123554c0a3aSHans de Goede 124554c0a3aSHans de Goede static RT_CHANNEL_PLAN_MAP RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { 125554c0a3aSHans de Goede /* 0x00 ~ 0x1F , Old Define ===== */ 126554c0a3aSHans de Goede {0x02, 0x20}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */ 127554c0a3aSHans de Goede {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */ 128554c0a3aSHans de Goede {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */ 129554c0a3aSHans de Goede {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */ 130554c0a3aSHans de Goede {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */ 131554c0a3aSHans de Goede {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */ 132554c0a3aSHans de Goede {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */ 133554c0a3aSHans de Goede {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */ 134554c0a3aSHans de Goede {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */ 135554c0a3aSHans de Goede {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */ 136554c0a3aSHans de Goede {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */ 137554c0a3aSHans de Goede {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */ 138554c0a3aSHans de Goede {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */ 139554c0a3aSHans de Goede {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */ 140554c0a3aSHans de Goede {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */ 141554c0a3aSHans de Goede {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */ 142554c0a3aSHans de Goede {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ 143554c0a3aSHans de Goede {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ 144554c0a3aSHans de Goede {0x01, 0x21}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ 145554c0a3aSHans de Goede {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */ 146554c0a3aSHans de Goede {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ 147554c0a3aSHans de Goede {0x00, 0x21}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ 148554c0a3aSHans de Goede {0x00, 0x22}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ 149554c0a3aSHans de Goede {0x03, 0x21}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ 150554c0a3aSHans de Goede {0x06, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */ 151554c0a3aSHans de Goede {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */ 152554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1A, */ 153554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1B, */ 154554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1C, */ 155554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1D, */ 156554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1E, */ 157554c0a3aSHans de Goede {0x06, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */ 158554c0a3aSHans de Goede /* 0x20 ~ 0x7F , New Define ===== */ 159554c0a3aSHans de Goede {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ 160554c0a3aSHans de Goede {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ 161554c0a3aSHans de Goede {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */ 162554c0a3aSHans de Goede {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */ 163554c0a3aSHans de Goede {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */ 164554c0a3aSHans de Goede {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */ 165554c0a3aSHans de Goede {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */ 166554c0a3aSHans de Goede {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */ 167554c0a3aSHans de Goede {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */ 168554c0a3aSHans de Goede {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */ 169554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2A, */ 170554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2B, */ 171554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2C, */ 172554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2D, */ 173554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2E, */ 174554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2F, */ 175554c0a3aSHans de Goede {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */ 176554c0a3aSHans de Goede {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */ 177554c0a3aSHans de Goede {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */ 178554c0a3aSHans de Goede {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */ 179554c0a3aSHans de Goede {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */ 180554c0a3aSHans de Goede {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */ 181554c0a3aSHans de Goede {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */ 182554c0a3aSHans de Goede {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */ 183554c0a3aSHans de Goede {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */ 184554c0a3aSHans de Goede {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */ 185554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3A, */ 186554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3B, */ 187554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3C, */ 188554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3D, */ 189554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3E, */ 190554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3F, */ 191554c0a3aSHans de Goede {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */ 192554c0a3aSHans de Goede {0x05, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */ 193554c0a3aSHans de Goede {0x01, 0x12}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */ 194554c0a3aSHans de Goede {0x02, 0x05}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */ 195554c0a3aSHans de Goede {0x02, 0x11}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */ 196554c0a3aSHans de Goede {0x00, 0x13}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */ 197554c0a3aSHans de Goede {0x02, 0x14}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */ 198554c0a3aSHans de Goede {0x00, 0x15}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */ 199554c0a3aSHans de Goede {0x00, 0x16}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */ 200554c0a3aSHans de Goede {0x00, 0x17}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */ 201554c0a3aSHans de Goede {0x00, 0x18}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */ 202554c0a3aSHans de Goede {0x00, 0x19}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */ 203554c0a3aSHans de Goede {0x00, 0x1A}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */ 204554c0a3aSHans de Goede {0x02, 0x1B}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */ 205554c0a3aSHans de Goede {0x00, 0x1C}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */ 206554c0a3aSHans de Goede {0x02, 0x1D}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */ 207554c0a3aSHans de Goede {0x00, 0x1E}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */ 208554c0a3aSHans de Goede {0x02, 0x1F}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */ 209554c0a3aSHans de Goede }; 210554c0a3aSHans de Goede 2114d17363dSAndreas Hellmich /* use the combination for max channel numbers */ 2124d17363dSAndreas Hellmich static RT_CHANNEL_PLAN_MAP RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; 213554c0a3aSHans de Goede 2144d17363dSAndreas Hellmich /* Search the @param ch in given @param ch_set 215554c0a3aSHans de Goede * @ch_set: the given channel set 216554c0a3aSHans de Goede * @ch: the given channel number 217554c0a3aSHans de Goede * 218554c0a3aSHans de Goede * return the index of channel_num in channel_set, -1 if not found 219554c0a3aSHans de Goede */ 220554c0a3aSHans de Goede int rtw_ch_set_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch) 221554c0a3aSHans de Goede { 222554c0a3aSHans de Goede int i; 223c926f022SSimran Singhal 224554c0a3aSHans de Goede for (i = 0; ch_set[i].ChannelNum != 0; i++) { 225554c0a3aSHans de Goede if (ch == ch_set[i].ChannelNum) 226554c0a3aSHans de Goede break; 227554c0a3aSHans de Goede } 228554c0a3aSHans de Goede 229554c0a3aSHans de Goede if (i >= ch_set[i].ChannelNum) 230554c0a3aSHans de Goede return -1; 231554c0a3aSHans de Goede return i; 232554c0a3aSHans de Goede } 233554c0a3aSHans de Goede 2344d17363dSAndreas Hellmich /* Check the @param ch is fit with setband setting of @param adapter 235554c0a3aSHans de Goede * @adapter: the given adapter 236554c0a3aSHans de Goede * @ch: the given channel number 237554c0a3aSHans de Goede * 238554c0a3aSHans de Goede * return true when check valid, false not valid 239554c0a3aSHans de Goede */ 240554c0a3aSHans de Goede bool rtw_mlme_band_check(struct adapter *adapter, const u32 ch) 241554c0a3aSHans de Goede { 242554c0a3aSHans de Goede if (adapter->setband == GHZ24_50 /* 2.4G and 5G */ 243554c0a3aSHans de Goede || (adapter->setband == GHZ_24 && ch < 35) /* 2.4G only */ 244554c0a3aSHans de Goede || (adapter->setband == GHZ_50 && ch > 35) /* 5G only */ 245554c0a3aSHans de Goede ) { 246554c0a3aSHans de Goede return true; 247554c0a3aSHans de Goede } 248554c0a3aSHans de Goede return false; 249554c0a3aSHans de Goede } 250554c0a3aSHans de Goede 251554c0a3aSHans de Goede /**************************************************************************** 252554c0a3aSHans de Goede 253554c0a3aSHans de Goede Following are the initialization functions for WiFi MLME 254554c0a3aSHans de Goede 255554c0a3aSHans de Goede *****************************************************************************/ 256554c0a3aSHans de Goede 257554c0a3aSHans de Goede int init_hw_mlme_ext(struct adapter *padapter) 258554c0a3aSHans de Goede { 259554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 260554c0a3aSHans de Goede 261554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 262554c0a3aSHans de Goede return _SUCCESS; 263554c0a3aSHans de Goede } 264554c0a3aSHans de Goede 265554c0a3aSHans de Goede void init_mlme_default_rate_set(struct adapter *padapter) 266554c0a3aSHans de Goede { 267554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 268554c0a3aSHans de Goede 269554c0a3aSHans de Goede 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}; 270554c0a3aSHans de Goede unsigned char mixed_basicrate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,}; 271554c0a3aSHans de Goede unsigned char supported_mcs_set[16] = {0xff, 0xff, 0x00, 0x00, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; 272554c0a3aSHans de Goede 273554c0a3aSHans de Goede memcpy(pmlmeext->datarate, mixed_datarate, NumRates); 274554c0a3aSHans de Goede memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates); 275554c0a3aSHans de Goede 276554c0a3aSHans de Goede memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set)); 277554c0a3aSHans de Goede } 278554c0a3aSHans de Goede 279554c0a3aSHans de Goede static void init_mlme_ext_priv_value(struct adapter *padapter) 280554c0a3aSHans de Goede { 281554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 282c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 283554c0a3aSHans de Goede 284554c0a3aSHans de Goede atomic_set(&pmlmeext->event_seq, 0); 285554c0a3aSHans de Goede pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */ 286554c0a3aSHans de Goede pmlmeext->sa_query_seq = 0; 287554c0a3aSHans de Goede pmlmeext->mgnt_80211w_IPN = 0; 288554c0a3aSHans de Goede pmlmeext->mgnt_80211w_IPN_rx = 0; 289554c0a3aSHans de Goede pmlmeext->cur_channel = padapter->registrypriv.channel; 290554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 291554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 292554c0a3aSHans de Goede 293554c0a3aSHans de Goede pmlmeext->retry = 0; 294554c0a3aSHans de Goede 295554c0a3aSHans de Goede pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode; 296554c0a3aSHans de Goede 297554c0a3aSHans de Goede init_mlme_default_rate_set(padapter); 298554c0a3aSHans de Goede 299554c0a3aSHans de Goede pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; 300554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_DISABLE; 301554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = 0; 302554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt = 0; 303554c0a3aSHans de Goede pmlmeext->scan_abort = false; 304554c0a3aSHans de Goede 305554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 306554c0a3aSHans de Goede pmlmeinfo->reauth_count = 0; 307554c0a3aSHans de Goede pmlmeinfo->reassoc_count = 0; 308554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 309554c0a3aSHans de Goede pmlmeinfo->auth_seq = 0; 310554c0a3aSHans de Goede pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; 311554c0a3aSHans de Goede pmlmeinfo->key_index = 0; 312554c0a3aSHans de Goede pmlmeinfo->iv = 0; 313554c0a3aSHans de Goede 314554c0a3aSHans de Goede pmlmeinfo->enc_algo = _NO_PRIVACY_; 315554c0a3aSHans de Goede pmlmeinfo->authModeToggle = 0; 316554c0a3aSHans de Goede 317554c0a3aSHans de Goede memset(pmlmeinfo->chg_txt, 0, 128); 318554c0a3aSHans de Goede 319554c0a3aSHans de Goede pmlmeinfo->slotTime = SHORT_SLOT_TIME; 320554c0a3aSHans de Goede pmlmeinfo->preamble_mode = PREAMBLE_AUTO; 321554c0a3aSHans de Goede 322554c0a3aSHans de Goede pmlmeinfo->dialogToken = 0; 323554c0a3aSHans de Goede 324554c0a3aSHans de Goede pmlmeext->action_public_rxseq = 0xffff; 325554c0a3aSHans de Goede pmlmeext->action_public_dialog_token = 0xff; 326554c0a3aSHans de Goede } 327554c0a3aSHans de Goede 328554c0a3aSHans de Goede static int has_channel(RT_CHANNEL_INFO *channel_set, 329554c0a3aSHans de Goede u8 chanset_size, 3303520c7a4SHenriette Hofmeier u8 chan) 3313520c7a4SHenriette Hofmeier { 332554c0a3aSHans de Goede int i; 333554c0a3aSHans de Goede 334554c0a3aSHans de Goede for (i = 0; i < chanset_size; i++) { 335554c0a3aSHans de Goede if (channel_set[i].ChannelNum == chan) { 336554c0a3aSHans de Goede return 1; 337554c0a3aSHans de Goede } 338554c0a3aSHans de Goede } 339554c0a3aSHans de Goede 340554c0a3aSHans de Goede return 0; 341554c0a3aSHans de Goede } 342554c0a3aSHans de Goede 343554c0a3aSHans de Goede static void init_channel_list(struct adapter *padapter, RT_CHANNEL_INFO *channel_set, 344554c0a3aSHans de Goede u8 chanset_size, 3453520c7a4SHenriette Hofmeier struct p2p_channels *channel_list) 3463520c7a4SHenriette Hofmeier { 347554c0a3aSHans de Goede 34853e3a7e1SColin Ian King static const struct p2p_oper_class_map op_class[] = { 349554c0a3aSHans de Goede { IEEE80211G, 81, 1, 13, 1, BW20 }, 350554c0a3aSHans de Goede { IEEE80211G, 82, 14, 14, 1, BW20 }, 351554c0a3aSHans de Goede { IEEE80211A, 115, 36, 48, 4, BW20 }, 352554c0a3aSHans de Goede { IEEE80211A, 116, 36, 44, 8, BW40PLUS }, 353554c0a3aSHans de Goede { IEEE80211A, 117, 40, 48, 8, BW40MINUS }, 354554c0a3aSHans de Goede { IEEE80211A, 124, 149, 161, 4, BW20 }, 355554c0a3aSHans de Goede { IEEE80211A, 125, 149, 169, 4, BW20 }, 356554c0a3aSHans de Goede { IEEE80211A, 126, 149, 157, 8, BW40PLUS }, 357554c0a3aSHans de Goede { IEEE80211A, 127, 153, 161, 8, BW40MINUS }, 358554c0a3aSHans de Goede { -1, 0, 0, 0, 0, BW20 } 359554c0a3aSHans de Goede }; 360554c0a3aSHans de Goede 361554c0a3aSHans de Goede int cla, op; 362554c0a3aSHans de Goede 363554c0a3aSHans de Goede cla = 0; 364554c0a3aSHans de Goede 365554c0a3aSHans de Goede for (op = 0; op_class[op].op_class; op++) { 366554c0a3aSHans de Goede u8 ch; 36753e3a7e1SColin Ian King const struct p2p_oper_class_map *o = &op_class[op]; 368554c0a3aSHans de Goede struct p2p_reg_class *reg = NULL; 369554c0a3aSHans de Goede 370554c0a3aSHans de Goede for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { 371a65f0d18SVatsala Narang if (!has_channel(channel_set, chanset_size, ch)) 372554c0a3aSHans de Goede continue; 373554c0a3aSHans de Goede 374554c0a3aSHans de Goede if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc)) 375554c0a3aSHans de Goede continue; 376554c0a3aSHans de Goede 377554c0a3aSHans de Goede if ((0 < (padapter->registrypriv.bw_mode & 0xf0)) && 378554c0a3aSHans de Goede ((BW40MINUS == o->bw) || (BW40PLUS == o->bw))) 379554c0a3aSHans de Goede continue; 380554c0a3aSHans de Goede 38141452327SVatsala Narang if (!reg) { 382554c0a3aSHans de Goede reg = &channel_list->reg_class[cla]; 383554c0a3aSHans de Goede cla++; 384554c0a3aSHans de Goede reg->reg_class = o->op_class; 385554c0a3aSHans de Goede reg->channels = 0; 386554c0a3aSHans de Goede } 387554c0a3aSHans de Goede reg->channel[reg->channels] = ch; 388554c0a3aSHans de Goede reg->channels++; 389554c0a3aSHans de Goede } 390554c0a3aSHans de Goede } 391554c0a3aSHans de Goede channel_list->reg_classes = cla; 392554c0a3aSHans de Goede 393554c0a3aSHans de Goede } 394554c0a3aSHans de Goede 395554c0a3aSHans de Goede static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, RT_CHANNEL_INFO *channel_set) 396554c0a3aSHans de Goede { 397554c0a3aSHans de Goede u8 index, chanset_size = 0; 398554c0a3aSHans de Goede u8 b5GBand = false, b2_4GBand = false; 399554c0a3aSHans de Goede u8 Index2G = 0, Index5G = 0; 400554c0a3aSHans de Goede 401554c0a3aSHans de Goede memset(channel_set, 0, sizeof(RT_CHANNEL_INFO)*MAX_CHANNEL_NUM); 402554c0a3aSHans de Goede 403554c0a3aSHans de Goede if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) { 404554c0a3aSHans de Goede DBG_871X("ChannelPlan ID %x error !!!!!\n", ChannelPlan); 405554c0a3aSHans de Goede return chanset_size; 406554c0a3aSHans de Goede } 407554c0a3aSHans de Goede 408554c0a3aSHans de Goede if (IsSupported24G(padapter->registrypriv.wireless_mode)) { 409554c0a3aSHans de Goede b2_4GBand = true; 410554c0a3aSHans de Goede if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan) 411554c0a3aSHans de Goede Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; 412554c0a3aSHans de Goede else 413554c0a3aSHans de Goede Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G; 414554c0a3aSHans de Goede } 415554c0a3aSHans de Goede 416554c0a3aSHans de Goede if (b2_4GBand) { 417554c0a3aSHans de Goede for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) { 418554c0a3aSHans de Goede channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index]; 419554c0a3aSHans de Goede 420554c0a3aSHans de Goede if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */ 421554c0a3aSHans de Goede (RT_CHANNEL_DOMAIN_GLOBAL_NULL == ChannelPlan)) { 422554c0a3aSHans de Goede if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11) 423554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 424554c0a3aSHans de Goede else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14)) 425554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 426554c0a3aSHans de Goede } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan || 427554c0a3aSHans de Goede RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan || 428554c0a3aSHans de Goede RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { /* channel 12~13, passive scan */ 429554c0a3aSHans de Goede if (channel_set[chanset_size].ChannelNum <= 11) 430554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 431554c0a3aSHans de Goede else 432554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 433554c0a3aSHans de Goede } else 434554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 435554c0a3aSHans de Goede 436554c0a3aSHans de Goede chanset_size++; 437554c0a3aSHans de Goede } 438554c0a3aSHans de Goede } 439554c0a3aSHans de Goede 440554c0a3aSHans de Goede if (b5GBand) { 441554c0a3aSHans de Goede for (index = 0; index < RTW_ChannelPlan5G[Index5G].Len; index++) { 442554c0a3aSHans de Goede if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48 443554c0a3aSHans de Goede || RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) { 444554c0a3aSHans de Goede channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index]; 445554c0a3aSHans de Goede if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)/* passive scan for all 5G channels */ 446554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 447554c0a3aSHans de Goede else 448554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 449554c0a3aSHans de Goede DBG_871X("%s(): channel_set[%d].ChannelNum = %d\n", __func__, chanset_size, channel_set[chanset_size].ChannelNum); 450554c0a3aSHans de Goede chanset_size++; 451554c0a3aSHans de Goede } 452554c0a3aSHans de Goede } 453554c0a3aSHans de Goede } 454554c0a3aSHans de Goede 455554c0a3aSHans de Goede DBG_871X("%s ChannelPlan ID %x Chan num:%d \n", __func__, ChannelPlan, chanset_size); 456554c0a3aSHans de Goede return chanset_size; 457554c0a3aSHans de Goede } 458554c0a3aSHans de Goede 459067756acSHariprasad Kelam void init_mlme_ext_priv(struct adapter *padapter) 460554c0a3aSHans de Goede { 461554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 462554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 463c872ed07SVatsala Narang struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 464c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 465554c0a3aSHans de Goede 466554c0a3aSHans de Goede pmlmeext->padapter = padapter; 467554c0a3aSHans de Goede 468554c0a3aSHans de Goede /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */ 469554c0a3aSHans de Goede 470554c0a3aSHans de Goede init_mlme_ext_priv_value(padapter); 4712646633fSAastha Gupta pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req; 472554c0a3aSHans de Goede 473554c0a3aSHans de Goede init_mlme_ext_timer(padapter); 474554c0a3aSHans de Goede 475554c0a3aSHans de Goede init_mlme_ap_info(padapter); 476554c0a3aSHans de Goede 477554c0a3aSHans de Goede pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set); 478554c0a3aSHans de Goede init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); 479554c0a3aSHans de Goede pmlmeext->last_scan_time = 0; 480554c0a3aSHans de Goede pmlmeext->chan_scan_time = SURVEY_TO; 481554c0a3aSHans de Goede pmlmeext->mlmeext_init = true; 482554c0a3aSHans de Goede pmlmeext->active_keep_alive_check = true; 483554c0a3aSHans de Goede 484554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 485554c0a3aSHans de Goede pmlmeext->fixed_chan = 0xFF; 486554c0a3aSHans de Goede #endif 487554c0a3aSHans de Goede } 488554c0a3aSHans de Goede 489554c0a3aSHans de Goede void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) 490554c0a3aSHans de Goede { 491554c0a3aSHans de Goede struct adapter *padapter = pmlmeext->padapter; 492554c0a3aSHans de Goede 493554c0a3aSHans de Goede if (!padapter) 494554c0a3aSHans de Goede return; 495554c0a3aSHans de Goede 4960ad02fa8SGeorgiana Chelu if (padapter->bDriverStopped) { 497554c0a3aSHans de Goede del_timer_sync(&pmlmeext->survey_timer); 498554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 499554c0a3aSHans de Goede /* del_timer_sync(&pmlmeext->ADDBA_timer); */ 500554c0a3aSHans de Goede } 501554c0a3aSHans de Goede } 502554c0a3aSHans de Goede 503554c0a3aSHans de Goede static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame) 504554c0a3aSHans de Goede { 505554c0a3aSHans de Goede u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 506554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 507554c0a3aSHans de Goede 508554c0a3aSHans de Goede if (ptable->func) { 509554c0a3aSHans de Goede /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ 510554c0a3aSHans de Goede if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && 511554c0a3aSHans de Goede memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) 512554c0a3aSHans de Goede return; 513554c0a3aSHans de Goede 514554c0a3aSHans de Goede ptable->func(padapter, precv_frame); 515554c0a3aSHans de Goede } 516554c0a3aSHans de Goede } 517554c0a3aSHans de Goede 518554c0a3aSHans de Goede void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame) 519554c0a3aSHans de Goede { 520554c0a3aSHans de Goede int index; 521554c0a3aSHans de Goede struct mlme_handler *ptable; 522554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 523554c0a3aSHans de Goede u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 524554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 525554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe)); 526554c0a3aSHans de Goede struct dvobj_priv *psdpriv = padapter->dvobj; 527554c0a3aSHans de Goede struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; 528554c0a3aSHans de Goede 529554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, 530554c0a3aSHans de Goede ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n", 531554c0a3aSHans de Goede GetFrameType(pframe), GetFrameSubType(pframe))); 532554c0a3aSHans de Goede 533554c0a3aSHans de Goede if (GetFrameType(pframe) != WIFI_MGT_TYPE) { 534554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe))); 535554c0a3aSHans de Goede return; 536554c0a3aSHans de Goede } 537554c0a3aSHans de Goede 538554c0a3aSHans de Goede /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ 539554c0a3aSHans de Goede if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && 540554c0a3aSHans de Goede memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) { 541554c0a3aSHans de Goede return; 542554c0a3aSHans de Goede } 543554c0a3aSHans de Goede 544554c0a3aSHans de Goede ptable = mlme_sta_tbl; 545554c0a3aSHans de Goede 546554c0a3aSHans de Goede index = GetFrameSubType(pframe) >> 4; 547554c0a3aSHans de Goede 54860db8d10SJérémy Lefaure if (index >= ARRAY_SIZE(mlme_sta_tbl)) { 549554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Currently we do not support reserved sub-fr-type =%d\n", index)); 550554c0a3aSHans de Goede return; 551554c0a3aSHans de Goede } 552554c0a3aSHans de Goede ptable += index; 553554c0a3aSHans de Goede 55434557e23SIzabela Bakollari if (psta) { 555554c0a3aSHans de Goede if (GetRetry(pframe)) { 556554c0a3aSHans de Goede if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) { 557554c0a3aSHans de Goede /* drop the duplicate management frame */ 558554c0a3aSHans de Goede pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++; 559554c0a3aSHans de Goede DBG_871X("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num); 560554c0a3aSHans de Goede return; 561554c0a3aSHans de Goede } 562554c0a3aSHans de Goede } 563554c0a3aSHans de Goede psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num; 564554c0a3aSHans de Goede } 565554c0a3aSHans de Goede 566554c0a3aSHans de Goede switch (GetFrameSubType(pframe)) { 567554c0a3aSHans de Goede case WIFI_AUTH: 5680ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) 569554c0a3aSHans de Goede ptable->func = &OnAuth; 570554c0a3aSHans de Goede else 571554c0a3aSHans de Goede ptable->func = &OnAuthClient; 57252a1d9d4SGustavo A. R. Silva fallthrough; 573554c0a3aSHans de Goede case WIFI_ASSOCREQ: 574554c0a3aSHans de Goede case WIFI_REASSOCREQ: 575554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 576554c0a3aSHans de Goede break; 577554c0a3aSHans de Goede case WIFI_PROBEREQ: 578554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 579554c0a3aSHans de Goede break; 580554c0a3aSHans de Goede case WIFI_BEACON: 581554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 582554c0a3aSHans de Goede break; 583554c0a3aSHans de Goede case WIFI_ACTION: 584554c0a3aSHans de Goede /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */ 585554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 586554c0a3aSHans de Goede break; 587554c0a3aSHans de Goede default: 588554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 589554c0a3aSHans de Goede break; 590554c0a3aSHans de Goede } 591554c0a3aSHans de Goede } 592554c0a3aSHans de Goede 593554c0a3aSHans de Goede /**************************************************************************** 594554c0a3aSHans de Goede 595554c0a3aSHans de Goede Following are the callback functions for each subtype of the management frames 596554c0a3aSHans de Goede 597554c0a3aSHans de Goede *****************************************************************************/ 598554c0a3aSHans de Goede 599554c0a3aSHans de Goede unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame) 600554c0a3aSHans de Goede { 601554c0a3aSHans de Goede unsigned int ielen; 602554c0a3aSHans de Goede unsigned char *p; 603554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 604554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 605c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 606c872ed07SVatsala Narang struct wlan_bssid_ex *cur = &pmlmeinfo->network; 607554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 608554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 609554c0a3aSHans de Goede u8 is_valid_p2p_probereq = false; 610554c0a3aSHans de Goede 611554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) 612554c0a3aSHans de Goede return _SUCCESS; 613554c0a3aSHans de Goede 614554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) == false && 615554c0a3aSHans de Goede check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) { 616554c0a3aSHans de Goede return _SUCCESS; 617554c0a3aSHans de Goede } 618554c0a3aSHans de Goede 619554c0a3aSHans de Goede 620554c0a3aSHans de Goede /* DBG_871X("+OnProbeReq\n"); */ 621554c0a3aSHans de Goede 622554c0a3aSHans de Goede #ifdef CONFIG_AUTO_AP_MODE 6230ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, _FW_LINKED) && 6240ad02fa8SGeorgiana Chelu pmlmepriv->cur_network.join_res) { 625554c0a3aSHans de Goede struct sta_info *psta; 626554c0a3aSHans de Goede u8 *mac_addr, *peer_addr; 627554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 628554c0a3aSHans de Goede u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A}; 629554c0a3aSHans de Goede /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */ 630554c0a3aSHans de Goede 631b05cc3a9SRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_VENDOR_SPECIFIC, (int *)&ielen, 632554c0a3aSHans de Goede len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); 633554c0a3aSHans de Goede 634554c0a3aSHans de Goede if (!p || ielen != 14) 635554c0a3aSHans de Goede goto _non_rc_device; 636554c0a3aSHans de Goede 637554c0a3aSHans de Goede if (memcmp(p+2, RC_OUI, sizeof(RC_OUI))) 638554c0a3aSHans de Goede goto _non_rc_device; 639554c0a3aSHans de Goede 640554c0a3aSHans de Goede if (memcmp(p+6, get_sa(pframe), ETH_ALEN)) { 641bbda3ac4SRoss Schmidt DBG_871X("%s, do rc pairing (%pM), but mac addr mismatch!(%pM)\n", __func__, 642554c0a3aSHans de Goede MAC_ARG(get_sa(pframe)), MAC_ARG(p+6)); 643554c0a3aSHans de Goede 644554c0a3aSHans de Goede goto _non_rc_device; 645554c0a3aSHans de Goede } 646554c0a3aSHans de Goede 647bbda3ac4SRoss Schmidt DBG_871X("%s, got the pairing device(%pM)\n", __func__, MAC_ARG(get_sa(pframe))); 648554c0a3aSHans de Goede 649554c0a3aSHans de Goede /* new a station */ 650554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, get_sa(pframe)); 651554c0a3aSHans de Goede if (psta == NULL) { 652554c0a3aSHans de Goede /* allocate a new one */ 653bbda3ac4SRoss Schmidt DBG_871X("going to alloc stainfo for rc =%pM\n", MAC_ARG(get_sa(pframe))); 654554c0a3aSHans de Goede psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe)); 65541452327SVatsala Narang if (!psta) { 656554c0a3aSHans de Goede /* TODO: */ 657554c0a3aSHans de Goede DBG_871X(" Exceed the upper limit of supported clients...\n"); 658554c0a3aSHans de Goede return _SUCCESS; 659554c0a3aSHans de Goede } 660554c0a3aSHans de Goede 661554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 662554c0a3aSHans de Goede if (list_empty(&psta->asoc_list)) { 663554c0a3aSHans de Goede psta->expire_to = pstapriv->expire_to; 664554c0a3aSHans de Goede list_add_tail(&psta->asoc_list, &pstapriv->asoc_list); 665554c0a3aSHans de Goede pstapriv->asoc_list_cnt++; 666554c0a3aSHans de Goede } 667554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 668554c0a3aSHans de Goede 669554c0a3aSHans de Goede /* generate pairing ID */ 670554c0a3aSHans de Goede mac_addr = myid(&(padapter->eeprompriv)); 671554c0a3aSHans de Goede peer_addr = psta->hwaddr; 672554c0a3aSHans de Goede psta->pid = (u16)(((mac_addr[4]<<8) + mac_addr[5]) + ((peer_addr[4]<<8) + peer_addr[5])); 673554c0a3aSHans de Goede 674554c0a3aSHans de Goede /* update peer stainfo */ 675554c0a3aSHans de Goede psta->isrc = true; 676554c0a3aSHans de Goede /* psta->aid = 0; */ 677554c0a3aSHans de Goede /* psta->mac_id = 2; */ 678554c0a3aSHans de Goede 679554c0a3aSHans de Goede /* get a unique AID */ 680554c0a3aSHans de Goede if (psta->aid > 0) { 681554c0a3aSHans de Goede DBG_871X("old AID %d\n", psta->aid); 682554c0a3aSHans de Goede } else { 683554c0a3aSHans de Goede for (psta->aid = 1; psta->aid <= NUM_STA; psta->aid++) 684554c0a3aSHans de Goede if (pstapriv->sta_aid[psta->aid - 1] == NULL) 685554c0a3aSHans de Goede break; 686554c0a3aSHans de Goede 687554c0a3aSHans de Goede if (psta->aid > pstapriv->max_num_sta) { 688554c0a3aSHans de Goede psta->aid = 0; 689554c0a3aSHans de Goede DBG_871X("no room for more AIDs\n"); 690554c0a3aSHans de Goede return _SUCCESS; 6919358bd52SVatsala Narang } 692554c0a3aSHans de Goede pstapriv->sta_aid[psta->aid - 1] = psta; 693554c0a3aSHans de Goede DBG_871X("allocate new AID = (%d)\n", psta->aid); 694554c0a3aSHans de Goede } 695554c0a3aSHans de Goede 696554c0a3aSHans de Goede psta->qos_option = 1; 697554c0a3aSHans de Goede psta->bw_mode = CHANNEL_WIDTH_20; 698554c0a3aSHans de Goede psta->ieee8021x_blocked = false; 699554c0a3aSHans de Goede psta->htpriv.ht_option = true; 700554c0a3aSHans de Goede psta->htpriv.ampdu_enable = false; 701554c0a3aSHans de Goede psta->htpriv.sgi_20m = false; 702554c0a3aSHans de Goede psta->htpriv.sgi_40m = false; 703554c0a3aSHans de Goede psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 704554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ 705554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ 706554c0a3aSHans de Goede 707554c0a3aSHans de Goede rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true); 708554c0a3aSHans de Goede 709554c0a3aSHans de Goede memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); 710554c0a3aSHans de Goede 711554c0a3aSHans de Goede spin_lock_bh(&psta->lock); 712554c0a3aSHans de Goede psta->state |= _FW_LINKED; 713554c0a3aSHans de Goede spin_unlock_bh(&psta->lock); 714554c0a3aSHans de Goede 715554c0a3aSHans de Goede report_add_sta_event(padapter, psta->hwaddr, psta->aid); 716554c0a3aSHans de Goede 717554c0a3aSHans de Goede } 718554c0a3aSHans de Goede 719554c0a3aSHans de Goede issue_probersp(padapter, get_sa(pframe), false); 720554c0a3aSHans de Goede 721554c0a3aSHans de Goede return _SUCCESS; 722554c0a3aSHans de Goede 723554c0a3aSHans de Goede } 724554c0a3aSHans de Goede 725554c0a3aSHans de Goede _non_rc_device: 726554c0a3aSHans de Goede 727554c0a3aSHans de Goede return _SUCCESS; 728554c0a3aSHans de Goede 729554c0a3aSHans de Goede #endif /* CONFIG_AUTO_AP_MODE */ 730554c0a3aSHans de Goede 7313f15277bSRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_SSID, (int *)&ielen, 732554c0a3aSHans de Goede len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); 733554c0a3aSHans de Goede 734554c0a3aSHans de Goede 735554c0a3aSHans de Goede /* check (wildcard) SSID */ 73634557e23SIzabela Bakollari if (p) { 7370ad02fa8SGeorgiana Chelu if (is_valid_p2p_probereq) 738554c0a3aSHans de Goede goto _issue_probersp; 739554c0a3aSHans de Goede 740554c0a3aSHans de Goede if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) 741554c0a3aSHans de Goede || (ielen == 0 && pmlmeinfo->hidden_ssid_mode) 742554c0a3aSHans de Goede ) 743554c0a3aSHans de Goede return _SUCCESS; 744554c0a3aSHans de Goede 745554c0a3aSHans de Goede _issue_probersp: 7460ad02fa8SGeorgiana Chelu if ((check_fwstate(pmlmepriv, _FW_LINKED) && 7470ad02fa8SGeorgiana Chelu pmlmepriv->cur_network.join_res) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { 748554c0a3aSHans de Goede /* DBG_871X("+issue_probersp during ap mode\n"); */ 749554c0a3aSHans de Goede issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq); 750554c0a3aSHans de Goede } 751554c0a3aSHans de Goede 752554c0a3aSHans de Goede } 753554c0a3aSHans de Goede 754554c0a3aSHans de Goede return _SUCCESS; 755554c0a3aSHans de Goede 756554c0a3aSHans de Goede } 757554c0a3aSHans de Goede 758554c0a3aSHans de Goede unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame) 759554c0a3aSHans de Goede { 760554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 761554c0a3aSHans de Goede 762554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 763554c0a3aSHans de Goede report_survey_event(padapter, precv_frame); 764554c0a3aSHans de Goede return _SUCCESS; 765554c0a3aSHans de Goede } 766554c0a3aSHans de Goede 767554c0a3aSHans de Goede return _SUCCESS; 768554c0a3aSHans de Goede 769554c0a3aSHans de Goede } 770554c0a3aSHans de Goede 771554c0a3aSHans de Goede unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame) 772554c0a3aSHans de Goede { 773554c0a3aSHans de Goede int cam_idx; 774554c0a3aSHans de Goede struct sta_info *psta; 775554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 776554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 777554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 778554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 779554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 780554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 781554c0a3aSHans de Goede struct wlan_bssid_ex *pbss; 782554c0a3aSHans de Goede int ret = _SUCCESS; 783554c0a3aSHans de Goede u8 *p = NULL; 784554c0a3aSHans de Goede u32 ielen = 0; 785554c0a3aSHans de Goede 786554c0a3aSHans de Goede 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_); 78734557e23SIzabela Bakollari if (p && ielen > 0) { 788554c0a3aSHans de Goede if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) { 789554c0a3aSHans de Goede /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */ 790bbda3ac4SRoss Schmidt DBG_871X("[WIFIDBG] Error in ESR IE is detected in Beacon of BSSID:%pM. Fix the length of ESR IE to avoid failed Beacon parsing.\n", MAC_ARG(GetAddr3Ptr(pframe))); 791554c0a3aSHans de Goede *(p + 1) = ielen - 1; 792554c0a3aSHans de Goede } 793554c0a3aSHans de Goede } 794554c0a3aSHans de Goede 795554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 796554c0a3aSHans de Goede report_survey_event(padapter, precv_frame); 797554c0a3aSHans de Goede return _SUCCESS; 798554c0a3aSHans de Goede } 799554c0a3aSHans de Goede 800554c0a3aSHans de Goede if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) { 801554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { 802554c0a3aSHans de Goede /* we should update current network before auth, or some IE is wrong */ 8032ef2b7c2SJoe Perches pbss = rtw_malloc(sizeof(struct wlan_bssid_ex)); 804554c0a3aSHans de Goede if (pbss) { 805554c0a3aSHans de Goede if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) { 806554c0a3aSHans de Goede update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true); 807554c0a3aSHans de Goede rtw_get_bcn_info(&(pmlmepriv->cur_network)); 808554c0a3aSHans de Goede } 8098f24f505SMadhumitha Prabakaran kfree(pbss); 810554c0a3aSHans de Goede } 811554c0a3aSHans de Goede 812554c0a3aSHans de Goede /* check the vendor of the assoc AP */ 813554c0a3aSHans de Goede pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr)); 814554c0a3aSHans de Goede 815554c0a3aSHans de Goede /* update TSF Value */ 816554c0a3aSHans de Goede update_TSF(pmlmeext, pframe, len); 817554c0a3aSHans de Goede 818554c0a3aSHans de Goede /* reset for adaptive_early_32k */ 819554c0a3aSHans de Goede pmlmeext->adaptive_tsf_done = false; 820554c0a3aSHans de Goede pmlmeext->DrvBcnEarly = 0xff; 821554c0a3aSHans de Goede pmlmeext->DrvBcnTimeOut = 0xff; 822554c0a3aSHans de Goede pmlmeext->bcn_cnt = 0; 823554c0a3aSHans de Goede memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt)); 824554c0a3aSHans de Goede memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio)); 825554c0a3aSHans de Goede 826554c0a3aSHans de Goede /* start auth */ 827554c0a3aSHans de Goede start_clnt_auth(padapter); 828554c0a3aSHans de Goede 829554c0a3aSHans de Goede return _SUCCESS; 830554c0a3aSHans de Goede } 831554c0a3aSHans de Goede 832554c0a3aSHans de Goede if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { 833554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 83434557e23SIzabela Bakollari if (psta) { 835554c0a3aSHans de Goede ret = rtw_check_bcn_info(padapter, pframe, len); 836554c0a3aSHans de Goede if (!ret) { 837554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "ap has changed, disconnect now\n "); 838554c0a3aSHans de Goede receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 0); 839554c0a3aSHans de Goede return _SUCCESS; 840554c0a3aSHans de Goede } 841554c0a3aSHans de Goede /* update WMM, ERP in the beacon */ 842554c0a3aSHans de Goede /* todo: the timer is used instead of the number of the beacon received */ 843554c0a3aSHans de Goede if ((sta_rx_pkts(psta) & 0xf) == 0) 844554c0a3aSHans de Goede /* DBG_871X("update_bcn_info\n"); */ 845554c0a3aSHans de Goede update_beacon_info(padapter, pframe, len, psta); 846554c0a3aSHans de Goede 847554c0a3aSHans de Goede adaptive_early_32k(pmlmeext, pframe, len); 848554c0a3aSHans de Goede } 849554c0a3aSHans de Goede } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 850554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 85134557e23SIzabela Bakollari if (psta) { 852554c0a3aSHans de Goede /* update WMM, ERP in the beacon */ 853554c0a3aSHans de Goede /* todo: the timer is used instead of the number of the beacon received */ 854554c0a3aSHans de Goede if ((sta_rx_pkts(psta) & 0xf) == 0) { 855554c0a3aSHans de Goede /* DBG_871X("update_bcn_info\n"); */ 856554c0a3aSHans de Goede update_beacon_info(padapter, pframe, len, psta); 857554c0a3aSHans de Goede } 858554c0a3aSHans de Goede } else { 859554c0a3aSHans de Goede /* allocate a new CAM entry for IBSS station */ 860554c0a3aSHans de Goede cam_idx = allocate_fw_sta_entry(padapter); 861554c0a3aSHans de Goede if (cam_idx == NUM_STA) 862554c0a3aSHans de Goede goto _END_ONBEACON_; 863554c0a3aSHans de Goede 864554c0a3aSHans de Goede /* get supported rate */ 865554c0a3aSHans de Goede 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) { 866554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[cam_idx].status = 0; 867554c0a3aSHans de Goede goto _END_ONBEACON_; 868554c0a3aSHans de Goede } 869554c0a3aSHans de Goede 870554c0a3aSHans de Goede /* update TSF Value */ 871554c0a3aSHans de Goede update_TSF(pmlmeext, pframe, len); 872554c0a3aSHans de Goede 873554c0a3aSHans de Goede /* report sta add event */ 874554c0a3aSHans de Goede report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx); 875554c0a3aSHans de Goede } 876554c0a3aSHans de Goede } 877554c0a3aSHans de Goede } 878554c0a3aSHans de Goede 879554c0a3aSHans de Goede _END_ONBEACON_: 880554c0a3aSHans de Goede 881554c0a3aSHans de Goede return _SUCCESS; 882554c0a3aSHans de Goede 883554c0a3aSHans de Goede } 884554c0a3aSHans de Goede 885554c0a3aSHans de Goede unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame) 886554c0a3aSHans de Goede { 887554c0a3aSHans de Goede unsigned int auth_mode, seq, ie_len; 888554c0a3aSHans de Goede unsigned char *sa, *p; 889554c0a3aSHans de Goede u16 algorithm; 890554c0a3aSHans de Goede int status; 891554c0a3aSHans de Goede static struct sta_info stat; 892554c0a3aSHans de Goede struct sta_info *pstat = NULL; 893554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 894554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 895554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 896554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 897554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 898554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 899554c0a3aSHans de Goede u8 offset = 0; 900554c0a3aSHans de Goede 901554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 902554c0a3aSHans de Goede return _FAIL; 903554c0a3aSHans de Goede 904554c0a3aSHans de Goede DBG_871X("+OnAuth\n"); 905554c0a3aSHans de Goede 906554c0a3aSHans de Goede sa = GetAddr2Ptr(pframe); 907554c0a3aSHans de Goede 908554c0a3aSHans de Goede auth_mode = psecuritypriv->dot11AuthAlgrthm; 909554c0a3aSHans de Goede 910554c0a3aSHans de Goede if (GetPrivacy(pframe)) { 911554c0a3aSHans de Goede u8 *iv; 912554c0a3aSHans de Goede struct rx_pkt_attrib *prxattrib = &(precv_frame->u.hdr.attrib); 913554c0a3aSHans de Goede 914554c0a3aSHans de Goede prxattrib->hdrlen = WLAN_HDR_A3_LEN; 915554c0a3aSHans de Goede prxattrib->encrypt = _WEP40_; 916554c0a3aSHans de Goede 917554c0a3aSHans de Goede iv = pframe+prxattrib->hdrlen; 918554c0a3aSHans de Goede prxattrib->key_index = ((iv[3]>>6)&0x3); 919554c0a3aSHans de Goede 920554c0a3aSHans de Goede prxattrib->iv_len = 4; 921554c0a3aSHans de Goede prxattrib->icv_len = 4; 922554c0a3aSHans de Goede 923554c0a3aSHans de Goede rtw_wep_decrypt(padapter, (u8 *)precv_frame); 924554c0a3aSHans de Goede 925554c0a3aSHans de Goede offset = 4; 926554c0a3aSHans de Goede } 927554c0a3aSHans de Goede 928554c0a3aSHans de Goede algorithm = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset)); 929554c0a3aSHans de Goede seq = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2)); 930554c0a3aSHans de Goede 931554c0a3aSHans de Goede DBG_871X("auth alg =%x, seq =%X\n", algorithm, seq); 932554c0a3aSHans de Goede 933554c0a3aSHans de Goede if (auth_mode == 2 && 934554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ && 935554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm != _WEP104_) 936554c0a3aSHans de Goede auth_mode = 0; 937554c0a3aSHans de Goede 938554c0a3aSHans de Goede if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */ 939554c0a3aSHans de Goede (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */ 940554c0a3aSHans de Goede DBG_871X("auth rejected due to bad alg [alg =%d, auth_mib =%d] %02X%02X%02X%02X%02X%02X\n", 941554c0a3aSHans de Goede algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]); 942554c0a3aSHans de Goede 9436d75b504SRoss Schmidt status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; 944554c0a3aSHans de Goede 945554c0a3aSHans de Goede goto auth_fail; 946554c0a3aSHans de Goede } 947554c0a3aSHans de Goede 948554c0a3aSHans de Goede if (rtw_access_ctrl(padapter, sa) == false) { 9496d75b504SRoss Schmidt status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 950554c0a3aSHans de Goede goto auth_fail; 951554c0a3aSHans de Goede } 952554c0a3aSHans de Goede 953554c0a3aSHans de Goede pstat = rtw_get_stainfo(pstapriv, sa); 954554c0a3aSHans de Goede if (pstat == NULL) { 955554c0a3aSHans de Goede 956554c0a3aSHans de Goede /* allocate a new one */ 957bbda3ac4SRoss Schmidt DBG_871X("going to alloc stainfo for sa =%pM\n", MAC_ARG(sa)); 958554c0a3aSHans de Goede pstat = rtw_alloc_stainfo(pstapriv, sa); 959554c0a3aSHans de Goede if (pstat == NULL) { 960554c0a3aSHans de Goede DBG_871X(" Exceed the upper limit of supported clients...\n"); 9616d75b504SRoss Schmidt status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 962554c0a3aSHans de Goede goto auth_fail; 963554c0a3aSHans de Goede } 964554c0a3aSHans de Goede 965554c0a3aSHans de Goede pstat->state = WIFI_FW_AUTH_NULL; 966554c0a3aSHans de Goede pstat->auth_seq = 0; 967554c0a3aSHans de Goede 968554c0a3aSHans de Goede /* pstat->flags = 0; */ 969554c0a3aSHans de Goede /* pstat->capability = 0; */ 970554c0a3aSHans de Goede } else { 971554c0a3aSHans de Goede 972554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 973554c0a3aSHans de Goede if (list_empty(&pstat->asoc_list) == false) { 974554c0a3aSHans de Goede list_del_init(&pstat->asoc_list); 975554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 976554c0a3aSHans de Goede if (pstat->expire_to > 0) { 977554c0a3aSHans de Goede /* TODO: STA re_auth within expire_to */ 978554c0a3aSHans de Goede } 979554c0a3aSHans de Goede } 980554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 981554c0a3aSHans de Goede 982554c0a3aSHans de Goede if (seq == 1) { 983554c0a3aSHans de Goede /* TODO: STA re_auth and auth timeout */ 984554c0a3aSHans de Goede } 985554c0a3aSHans de Goede } 986554c0a3aSHans de Goede 987554c0a3aSHans de Goede spin_lock_bh(&pstapriv->auth_list_lock); 988554c0a3aSHans de Goede if (list_empty(&pstat->auth_list)) { 989554c0a3aSHans de Goede 990554c0a3aSHans de Goede list_add_tail(&pstat->auth_list, &pstapriv->auth_list); 991554c0a3aSHans de Goede pstapriv->auth_list_cnt++; 992554c0a3aSHans de Goede } 993554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->auth_list_lock); 994554c0a3aSHans de Goede 995554c0a3aSHans de Goede if (pstat->auth_seq == 0) 996554c0a3aSHans de Goede pstat->expire_to = pstapriv->auth_to; 997554c0a3aSHans de Goede 998554c0a3aSHans de Goede 999554c0a3aSHans de Goede if ((pstat->auth_seq + 1) != seq) { 1000554c0a3aSHans de Goede DBG_871X("(1)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n", 1001554c0a3aSHans de Goede seq, pstat->auth_seq+1); 10026d75b504SRoss Schmidt status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; 1003554c0a3aSHans de Goede goto auth_fail; 1004554c0a3aSHans de Goede } 1005554c0a3aSHans de Goede 1006554c0a3aSHans de Goede if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) { 1007554c0a3aSHans de Goede if (seq == 1) { 1008554c0a3aSHans de Goede pstat->state &= ~WIFI_FW_AUTH_NULL; 1009554c0a3aSHans de Goede pstat->state |= WIFI_FW_AUTH_SUCCESS; 1010554c0a3aSHans de Goede pstat->expire_to = pstapriv->assoc_to; 1011554c0a3aSHans de Goede pstat->authalg = algorithm; 1012554c0a3aSHans de Goede } else { 1013554c0a3aSHans de Goede DBG_871X("(2)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n", 1014554c0a3aSHans de Goede seq, pstat->auth_seq+1); 10156d75b504SRoss Schmidt status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; 1016554c0a3aSHans de Goede goto auth_fail; 1017554c0a3aSHans de Goede } 1018554c0a3aSHans de Goede } else { /* shared system or auto authentication */ 1019554c0a3aSHans de Goede if (seq == 1) { 1020554c0a3aSHans de Goede /* prepare for the challenging txt... */ 1021554c0a3aSHans de Goede memset((void *)pstat->chg_txt, 78, 128); 1022554c0a3aSHans de Goede 1023554c0a3aSHans de Goede pstat->state &= ~WIFI_FW_AUTH_NULL; 1024554c0a3aSHans de Goede pstat->state |= WIFI_FW_AUTH_STATE; 1025554c0a3aSHans de Goede pstat->authalg = algorithm; 1026554c0a3aSHans de Goede pstat->auth_seq = 2; 1027554c0a3aSHans de Goede } else if (seq == 3) { 1028554c0a3aSHans de Goede /* checking for challenging txt... */ 1029554c0a3aSHans de Goede DBG_871X("checking for challenging txt...\n"); 1030554c0a3aSHans de Goede 1031554c0a3aSHans de Goede p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&ie_len, 1032554c0a3aSHans de Goede len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); 1033554c0a3aSHans de Goede 1034554c0a3aSHans de Goede if ((p == NULL) || (ie_len <= 0)) { 1035554c0a3aSHans de Goede DBG_871X("auth rejected because challenge failure!(1)\n"); 10366d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1037554c0a3aSHans de Goede goto auth_fail; 1038554c0a3aSHans de Goede } 1039554c0a3aSHans de Goede 1040554c0a3aSHans de Goede if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) { 1041554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_AUTH_STATE); 1042554c0a3aSHans de Goede pstat->state |= WIFI_FW_AUTH_SUCCESS; 1043554c0a3aSHans de Goede /* challenging txt is correct... */ 1044554c0a3aSHans de Goede pstat->expire_to = pstapriv->assoc_to; 1045554c0a3aSHans de Goede } else { 1046554c0a3aSHans de Goede DBG_871X("auth rejected because challenge failure!\n"); 10476d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1048554c0a3aSHans de Goede goto auth_fail; 1049554c0a3aSHans de Goede } 1050554c0a3aSHans de Goede } else { 1051554c0a3aSHans de Goede DBG_871X("(3)auth rejected because out of seq [rx_seq =%d, exp_seq =%d]!\n", 1052554c0a3aSHans de Goede seq, pstat->auth_seq+1); 10536d75b504SRoss Schmidt status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; 1054554c0a3aSHans de Goede goto auth_fail; 1055554c0a3aSHans de Goede } 1056554c0a3aSHans de Goede } 1057554c0a3aSHans de Goede 1058554c0a3aSHans de Goede 1059554c0a3aSHans de Goede /* Now, we are going to issue_auth... */ 1060554c0a3aSHans de Goede pstat->auth_seq = seq + 1; 1061554c0a3aSHans de Goede 10626d75b504SRoss Schmidt issue_auth(padapter, pstat, (unsigned short)(WLAN_STATUS_SUCCESS)); 1063554c0a3aSHans de Goede 1064554c0a3aSHans de Goede if (pstat->state & WIFI_FW_AUTH_SUCCESS) 1065554c0a3aSHans de Goede pstat->auth_seq = 0; 1066554c0a3aSHans de Goede 1067554c0a3aSHans de Goede 1068554c0a3aSHans de Goede return _SUCCESS; 1069554c0a3aSHans de Goede 1070554c0a3aSHans de Goede auth_fail: 1071554c0a3aSHans de Goede 1072554c0a3aSHans de Goede if (pstat) 1073554c0a3aSHans de Goede rtw_free_stainfo(padapter, pstat); 1074554c0a3aSHans de Goede 1075554c0a3aSHans de Goede pstat = &stat; 1076554c0a3aSHans de Goede memset((char *)pstat, '\0', sizeof(stat)); 1077554c0a3aSHans de Goede pstat->auth_seq = 2; 1078554c0a3aSHans de Goede memcpy(pstat->hwaddr, sa, 6); 1079554c0a3aSHans de Goede 1080554c0a3aSHans de Goede issue_auth(padapter, pstat, (unsigned short)status); 1081554c0a3aSHans de Goede 1082554c0a3aSHans de Goede return _FAIL; 1083554c0a3aSHans de Goede 1084554c0a3aSHans de Goede } 1085554c0a3aSHans de Goede 1086554c0a3aSHans de Goede unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame) 1087554c0a3aSHans de Goede { 10883a0514a9SJason Yan unsigned int seq, len, status, offset; 1089554c0a3aSHans de Goede unsigned char *p; 1090554c0a3aSHans de Goede unsigned int go2asoc = 0; 1091554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1092554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1093554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1094554c0a3aSHans de Goede uint pkt_len = precv_frame->u.hdr.len; 1095554c0a3aSHans de Goede 1096554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1097554c0a3aSHans de Goede 1098554c0a3aSHans de Goede /* check A1 matches or not */ 1099554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) 1100554c0a3aSHans de Goede return _SUCCESS; 1101554c0a3aSHans de Goede 1102554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE)) 1103554c0a3aSHans de Goede return _SUCCESS; 1104554c0a3aSHans de Goede 1105554c0a3aSHans de Goede offset = (GetPrivacy(pframe)) ? 4 : 0; 1106554c0a3aSHans de Goede 1107554c0a3aSHans de Goede seq = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2)); 1108554c0a3aSHans de Goede status = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4)); 1109554c0a3aSHans de Goede 1110554c0a3aSHans de Goede if (status != 0) { 1111554c0a3aSHans de Goede DBG_871X("clnt auth fail, status: %d\n", status); 1112554c0a3aSHans de Goede if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ 1113554c0a3aSHans de Goede if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) 1114554c0a3aSHans de Goede pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; 1115554c0a3aSHans de Goede else 1116554c0a3aSHans de Goede pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; 1117554c0a3aSHans de Goede /* pmlmeinfo->reauth_count = 0; */ 1118554c0a3aSHans de Goede } 1119554c0a3aSHans de Goede 1120554c0a3aSHans de Goede set_link_timer(pmlmeext, 1); 1121554c0a3aSHans de Goede goto authclnt_fail; 1122554c0a3aSHans de Goede } 1123554c0a3aSHans de Goede 1124554c0a3aSHans de Goede if (seq == 2) { 1125554c0a3aSHans de Goede if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { 1126554c0a3aSHans de Goede /* legendary shared system */ 1127554c0a3aSHans de Goede p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len, 1128554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); 1129554c0a3aSHans de Goede 1130554c0a3aSHans de Goede if (p == NULL) { 1131554c0a3aSHans de Goede /* DBG_871X("marc: no challenge text?\n"); */ 1132554c0a3aSHans de Goede goto authclnt_fail; 1133554c0a3aSHans de Goede } 1134554c0a3aSHans de Goede 1135554c0a3aSHans de Goede memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len); 1136554c0a3aSHans de Goede pmlmeinfo->auth_seq = 3; 1137554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 1138554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 1139554c0a3aSHans de Goede 1140554c0a3aSHans de Goede return _SUCCESS; 1141554c0a3aSHans de Goede } else { 1142554c0a3aSHans de Goede /* open system */ 1143554c0a3aSHans de Goede go2asoc = 1; 1144554c0a3aSHans de Goede } 1145554c0a3aSHans de Goede } else if (seq == 4) { 1146554c0a3aSHans de Goede if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { 1147554c0a3aSHans de Goede go2asoc = 1; 1148554c0a3aSHans de Goede } else { 1149554c0a3aSHans de Goede goto authclnt_fail; 1150554c0a3aSHans de Goede } 1151554c0a3aSHans de Goede } else { 1152554c0a3aSHans de Goede /* this is also illegal */ 1153554c0a3aSHans de Goede /* DBG_871X("marc: clnt auth failed due to illegal seq =%x\n", seq); */ 1154554c0a3aSHans de Goede goto authclnt_fail; 1155554c0a3aSHans de Goede } 1156554c0a3aSHans de Goede 1157554c0a3aSHans de Goede if (go2asoc) { 1158554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "auth success, start assoc\n"); 1159554c0a3aSHans de Goede start_clnt_assoc(padapter); 1160554c0a3aSHans de Goede return _SUCCESS; 1161554c0a3aSHans de Goede } 1162554c0a3aSHans de Goede 1163554c0a3aSHans de Goede authclnt_fail: 1164554c0a3aSHans de Goede 1165554c0a3aSHans de Goede /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */ 1166554c0a3aSHans de Goede 1167554c0a3aSHans de Goede return _FAIL; 1168554c0a3aSHans de Goede 1169554c0a3aSHans de Goede } 1170554c0a3aSHans de Goede 1171554c0a3aSHans de Goede unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame) 1172554c0a3aSHans de Goede { 117347548aa9SJason Yan u16 capab_info; 1174554c0a3aSHans de Goede struct rtw_ieee802_11_elems elems; 1175554c0a3aSHans de Goede struct sta_info *pstat; 1176554c0a3aSHans de Goede unsigned char reassoc, *p, *pos, *wpa_ie; 1177554c0a3aSHans de Goede unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; 1178554c0a3aSHans de Goede int i, ie_len, wpa_ie_len, left; 1179554c0a3aSHans de Goede unsigned char supportRate[16]; 1180554c0a3aSHans de Goede int supportRateNum; 11816d75b504SRoss Schmidt unsigned short status = WLAN_STATUS_SUCCESS; 1182554c0a3aSHans de Goede unsigned short frame_type, ie_offset = 0; 1183554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1184554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 1185554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1186554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1187554c0a3aSHans de Goede struct wlan_bssid_ex *cur = &(pmlmeinfo->network); 1188554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1189554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1190554c0a3aSHans de Goede uint pkt_len = precv_frame->u.hdr.len; 1191554c0a3aSHans de Goede 1192554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 1193554c0a3aSHans de Goede return _FAIL; 1194554c0a3aSHans de Goede 1195554c0a3aSHans de Goede frame_type = GetFrameSubType(pframe); 1196554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) { 1197554c0a3aSHans de Goede reassoc = 0; 1198554c0a3aSHans de Goede ie_offset = _ASOCREQ_IE_OFFSET_; 1199554c0a3aSHans de Goede } else { /* WIFI_REASSOCREQ */ 1200554c0a3aSHans de Goede reassoc = 1; 1201554c0a3aSHans de Goede ie_offset = _REASOCREQ_IE_OFFSET_; 1202554c0a3aSHans de Goede } 1203554c0a3aSHans de Goede 1204554c0a3aSHans de Goede 12057d0b4f3cSQuytelda Kahja if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset) { 1206554c0a3aSHans de Goede DBG_871X("handle_assoc(reassoc =%d) - too short payload (len =%lu)" 1207554c0a3aSHans de Goede "\n", reassoc, (unsigned long)pkt_len); 1208554c0a3aSHans de Goede return _FAIL; 1209554c0a3aSHans de Goede } 1210554c0a3aSHans de Goede 1211554c0a3aSHans de Goede pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 121241452327SVatsala Narang if (!pstat) { 12135ed3e6f2SRoss Schmidt status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; 1214554c0a3aSHans de Goede goto asoc_class2_error; 1215554c0a3aSHans de Goede } 1216554c0a3aSHans de Goede 1217d48603afSRoss Schmidt capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN); 1218554c0a3aSHans de Goede /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */ 1219554c0a3aSHans de Goede 12207d0b4f3cSQuytelda Kahja left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset); 12217d0b4f3cSQuytelda Kahja pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset); 1222554c0a3aSHans de Goede 1223554c0a3aSHans de Goede 1224554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1225554c0a3aSHans de Goede 1226554c0a3aSHans de Goede /* check if this stat has been successfully authenticated/assocated */ 1227554c0a3aSHans de Goede if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) { 1228554c0a3aSHans de Goede if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) { 12295ed3e6f2SRoss Schmidt status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; 1230554c0a3aSHans de Goede goto asoc_class2_error; 1231554c0a3aSHans de Goede } else { 1232554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); 1233554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_STATE; 1234554c0a3aSHans de Goede } 1235554c0a3aSHans de Goede } else { 1236554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_AUTH_SUCCESS); 1237554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_STATE; 1238554c0a3aSHans de Goede } 1239554c0a3aSHans de Goede 1240554c0a3aSHans de Goede 1241554c0a3aSHans de Goede pstat->capability = capab_info; 1242554c0a3aSHans de Goede 1243554c0a3aSHans de Goede /* now parse all ieee802_11 ie to point to elems */ 1244554c0a3aSHans de Goede if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed || 1245554c0a3aSHans de Goede !elems.ssid) { 1246bbda3ac4SRoss Schmidt DBG_871X("STA %pM sent invalid association request\n", 1247554c0a3aSHans de Goede MAC_ARG(pstat->hwaddr)); 12486d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1249554c0a3aSHans de Goede goto OnAssocReqFail; 1250554c0a3aSHans de Goede } 1251554c0a3aSHans de Goede 1252554c0a3aSHans de Goede /* now we should check all the fields... */ 1253554c0a3aSHans de Goede /* checking SSID */ 12543f15277bSRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SSID, &ie_len, 1255554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - ie_offset); 1256554c0a3aSHans de Goede 12576493a78fSAymen Qader if (!p || ie_len == 0) { 12586493a78fSAymen Qader /* broadcast ssid, however it is not allowed in assocreq */ 12596d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 12606493a78fSAymen Qader goto OnAssocReqFail; 12616493a78fSAymen Qader } else { 1262554c0a3aSHans de Goede /* check if ssid match */ 1263554c0a3aSHans de Goede if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength)) 12646d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1265554c0a3aSHans de Goede 1266554c0a3aSHans de Goede if (ie_len != cur->Ssid.SsidLength) 12676d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1268554c0a3aSHans de Goede } 1269554c0a3aSHans de Goede 12706d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 1271554c0a3aSHans de Goede goto OnAssocReqFail; 1272554c0a3aSHans de Goede 1273554c0a3aSHans de Goede /* check if the supported rate is ok */ 1274c34c45edSRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SUPP_RATES, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); 1275554c0a3aSHans de Goede if (p == NULL) { 1276554c0a3aSHans de Goede DBG_871X("Rx a sta assoc-req which supported rate is empty!\n"); 1277554c0a3aSHans de Goede /* use our own rate set as statoin used */ 1278554c0a3aSHans de Goede /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ 1279554c0a3aSHans de Goede /* supportRateNum = AP_BSSRATE_LEN; */ 1280554c0a3aSHans de Goede 12816d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1282554c0a3aSHans de Goede goto OnAssocReqFail; 1283554c0a3aSHans de Goede } else { 1284554c0a3aSHans de Goede memcpy(supportRate, p+2, ie_len); 1285554c0a3aSHans de Goede supportRateNum = ie_len; 1286554c0a3aSHans de Goede 1287554c0a3aSHans de Goede p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_, &ie_len, 1288554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - ie_offset); 1289554c0a3aSHans de Goede if (p != NULL) { 1290554c0a3aSHans de Goede 1291554c0a3aSHans de Goede if (supportRateNum <= sizeof(supportRate)) { 1292554c0a3aSHans de Goede memcpy(supportRate+supportRateNum, p+2, ie_len); 1293554c0a3aSHans de Goede supportRateNum += ie_len; 1294554c0a3aSHans de Goede } 1295554c0a3aSHans de Goede } 1296554c0a3aSHans de Goede } 1297554c0a3aSHans de Goede 1298554c0a3aSHans de Goede /* todo: mask supportRate between AP & STA -> move to update raid */ 1299554c0a3aSHans de Goede /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */ 1300554c0a3aSHans de Goede 1301554c0a3aSHans de Goede /* update station supportRate */ 1302554c0a3aSHans de Goede pstat->bssratelen = supportRateNum; 1303554c0a3aSHans de Goede memcpy(pstat->bssrateset, supportRate, supportRateNum); 1304554c0a3aSHans de Goede UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen); 1305554c0a3aSHans de Goede 1306554c0a3aSHans de Goede /* check RSN/WPA/WPS */ 1307554c0a3aSHans de Goede pstat->dot8021xalg = 0; 1308554c0a3aSHans de Goede pstat->wpa_psk = 0; 1309554c0a3aSHans de Goede pstat->wpa_group_cipher = 0; 1310554c0a3aSHans de Goede pstat->wpa2_group_cipher = 0; 1311554c0a3aSHans de Goede pstat->wpa_pairwise_cipher = 0; 1312554c0a3aSHans de Goede pstat->wpa2_pairwise_cipher = 0; 1313554c0a3aSHans de Goede memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie)); 1314554c0a3aSHans de Goede if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) { 1315554c0a3aSHans de Goede 1316554c0a3aSHans de Goede int group_cipher = 0, pairwise_cipher = 0; 1317554c0a3aSHans de Goede 1318554c0a3aSHans de Goede wpa_ie = elems.rsn_ie; 1319554c0a3aSHans de Goede wpa_ie_len = elems.rsn_ie_len; 1320554c0a3aSHans de Goede 1321554c0a3aSHans de Goede if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { 1322554c0a3aSHans de Goede pstat->dot8021xalg = 1;/* psk, todo:802.1x */ 1323554c0a3aSHans de Goede pstat->wpa_psk |= BIT(1); 1324554c0a3aSHans de Goede 1325554c0a3aSHans de Goede pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher; 1326554c0a3aSHans de Goede pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher; 1327554c0a3aSHans de Goede 1328554c0a3aSHans de Goede if (!pstat->wpa2_group_cipher) 13296d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_GROUP_CIPHER; 1330554c0a3aSHans de Goede 1331554c0a3aSHans de Goede if (!pstat->wpa2_pairwise_cipher) 13326d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; 1333554c0a3aSHans de Goede } else { 1334554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1335554c0a3aSHans de Goede } 1336554c0a3aSHans de Goede 1337554c0a3aSHans de Goede } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) { 1338554c0a3aSHans de Goede 1339554c0a3aSHans de Goede int group_cipher = 0, pairwise_cipher = 0; 1340554c0a3aSHans de Goede 1341554c0a3aSHans de Goede wpa_ie = elems.wpa_ie; 1342554c0a3aSHans de Goede wpa_ie_len = elems.wpa_ie_len; 1343554c0a3aSHans de Goede 1344554c0a3aSHans de Goede if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { 1345554c0a3aSHans de Goede pstat->dot8021xalg = 1;/* psk, todo:802.1x */ 1346554c0a3aSHans de Goede pstat->wpa_psk |= BIT(0); 1347554c0a3aSHans de Goede 1348554c0a3aSHans de Goede pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher; 1349554c0a3aSHans de Goede pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher; 1350554c0a3aSHans de Goede 1351554c0a3aSHans de Goede if (!pstat->wpa_group_cipher) 13526d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_GROUP_CIPHER; 1353554c0a3aSHans de Goede 1354554c0a3aSHans de Goede if (!pstat->wpa_pairwise_cipher) 13556d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; 1356554c0a3aSHans de Goede 1357554c0a3aSHans de Goede } else { 1358554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1359554c0a3aSHans de Goede } 1360554c0a3aSHans de Goede 1361554c0a3aSHans de Goede } else { 1362554c0a3aSHans de Goede wpa_ie = NULL; 1363554c0a3aSHans de Goede wpa_ie_len = 0; 1364554c0a3aSHans de Goede } 1365554c0a3aSHans de Goede 13666d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 1367554c0a3aSHans de Goede goto OnAssocReqFail; 1368554c0a3aSHans de Goede 1369554c0a3aSHans de Goede pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); 137041452327SVatsala Narang if (!wpa_ie) { 1371554c0a3aSHans de Goede if (elems.wps_ie) { 1372554c0a3aSHans de Goede DBG_871X("STA included WPS IE in " 1373554c0a3aSHans de Goede "(Re)Association Request - assume WPS is " 1374554c0a3aSHans de Goede "used\n"); 1375554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WPS; 1376554c0a3aSHans de Goede /* wpabuf_free(sta->wps_ie); */ 1377554c0a3aSHans de Goede /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */ 1378554c0a3aSHans de Goede /* elems.wps_ie_len - 4); */ 1379554c0a3aSHans de Goede } else { 1380554c0a3aSHans de Goede DBG_871X("STA did not include WPA/RSN IE " 1381554c0a3aSHans de Goede "in (Re)Association Request - possible WPS " 1382554c0a3aSHans de Goede "use\n"); 1383554c0a3aSHans de Goede pstat->flags |= WLAN_STA_MAYBE_WPS; 1384554c0a3aSHans de Goede } 1385554c0a3aSHans de Goede 1386554c0a3aSHans de Goede 1387554c0a3aSHans de Goede /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */ 1388554c0a3aSHans de Goede /* that the selected registrar of AP is _FLASE */ 1389554c0a3aSHans de Goede if ((psecuritypriv->wpa_psk > 0) 1390554c0a3aSHans de Goede && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) { 1391554c0a3aSHans de Goede if (pmlmepriv->wps_beacon_ie) { 1392554c0a3aSHans de Goede u8 selected_registrar = 0; 1393554c0a3aSHans de Goede 1394554c0a3aSHans de Goede rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL); 1395554c0a3aSHans de Goede 1396554c0a3aSHans de Goede if (!selected_registrar) { 1397554c0a3aSHans de Goede DBG_871X("selected_registrar is false , or AP is not ready to do WPS\n"); 1398554c0a3aSHans de Goede 13996d75b504SRoss Schmidt status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 1400554c0a3aSHans de Goede 1401554c0a3aSHans de Goede goto OnAssocReqFail; 1402554c0a3aSHans de Goede } 1403554c0a3aSHans de Goede } 1404554c0a3aSHans de Goede } 1405554c0a3aSHans de Goede 1406554c0a3aSHans de Goede } else { 1407554c0a3aSHans de Goede int copy_len; 1408554c0a3aSHans de Goede 1409554c0a3aSHans de Goede if (psecuritypriv->wpa_psk == 0) { 1410bbda3ac4SRoss Schmidt DBG_871X("STA %pM: WPA/RSN IE in association " 1411554c0a3aSHans de Goede "request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr)); 1412554c0a3aSHans de Goede 1413554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1414554c0a3aSHans de Goede 1415554c0a3aSHans de Goede goto OnAssocReqFail; 1416554c0a3aSHans de Goede 1417554c0a3aSHans de Goede } 1418554c0a3aSHans de Goede 1419554c0a3aSHans de Goede if (elems.wps_ie) { 1420554c0a3aSHans de Goede DBG_871X("STA included WPS IE in " 1421554c0a3aSHans de Goede "(Re)Association Request - WPS is " 1422554c0a3aSHans de Goede "used\n"); 1423554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WPS; 1424554c0a3aSHans de Goede copy_len = 0; 1425554c0a3aSHans de Goede } else { 1426554c0a3aSHans de Goede copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2); 1427554c0a3aSHans de Goede } 1428554c0a3aSHans de Goede 1429554c0a3aSHans de Goede 1430554c0a3aSHans de Goede if (copy_len > 0) 1431554c0a3aSHans de Goede memcpy(pstat->wpa_ie, wpa_ie-2, copy_len); 1432554c0a3aSHans de Goede 1433554c0a3aSHans de Goede } 1434554c0a3aSHans de Goede 1435554c0a3aSHans de Goede 1436554c0a3aSHans de Goede /* check if there is WMM IE & support WWM-PS */ 1437554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_WME; 1438554c0a3aSHans de Goede pstat->qos_option = 0; 1439554c0a3aSHans de Goede pstat->qos_info = 0; 1440554c0a3aSHans de Goede pstat->has_legacy_ac = true; 1441554c0a3aSHans de Goede pstat->uapsd_vo = 0; 1442554c0a3aSHans de Goede pstat->uapsd_vi = 0; 1443554c0a3aSHans de Goede pstat->uapsd_be = 0; 1444554c0a3aSHans de Goede pstat->uapsd_bk = 0; 1445554c0a3aSHans de Goede if (pmlmepriv->qospriv.qos_option) { 1446554c0a3aSHans de Goede p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0; 1447554c0a3aSHans de Goede for (;;) { 1448b05cc3a9SRoss Schmidt p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); 144934557e23SIzabela Bakollari if (p) { 1450554c0a3aSHans de Goede if (!memcmp(p+2, WMM_IE, 6)) { 1451554c0a3aSHans de Goede 1452554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WME; 1453554c0a3aSHans de Goede 1454554c0a3aSHans de Goede pstat->qos_option = 1; 1455554c0a3aSHans de Goede pstat->qos_info = *(p+8); 1456554c0a3aSHans de Goede 1457554c0a3aSHans de Goede pstat->max_sp_len = (pstat->qos_info>>5)&0x3; 1458554c0a3aSHans de Goede 1459554c0a3aSHans de Goede if ((pstat->qos_info&0xf) != 0xf) 1460554c0a3aSHans de Goede pstat->has_legacy_ac = true; 1461554c0a3aSHans de Goede else 1462554c0a3aSHans de Goede pstat->has_legacy_ac = false; 1463554c0a3aSHans de Goede 1464554c0a3aSHans de Goede if (pstat->qos_info&0xf) { 1465554c0a3aSHans de Goede if (pstat->qos_info&BIT(0)) 1466554c0a3aSHans de Goede pstat->uapsd_vo = BIT(0)|BIT(1); 1467554c0a3aSHans de Goede else 1468554c0a3aSHans de Goede pstat->uapsd_vo = 0; 1469554c0a3aSHans de Goede 1470554c0a3aSHans de Goede if (pstat->qos_info&BIT(1)) 1471554c0a3aSHans de Goede pstat->uapsd_vi = BIT(0)|BIT(1); 1472554c0a3aSHans de Goede else 1473554c0a3aSHans de Goede pstat->uapsd_vi = 0; 1474554c0a3aSHans de Goede 1475554c0a3aSHans de Goede if (pstat->qos_info&BIT(2)) 1476554c0a3aSHans de Goede pstat->uapsd_bk = BIT(0)|BIT(1); 1477554c0a3aSHans de Goede else 1478554c0a3aSHans de Goede pstat->uapsd_bk = 0; 1479554c0a3aSHans de Goede 1480554c0a3aSHans de Goede if (pstat->qos_info&BIT(3)) 1481554c0a3aSHans de Goede pstat->uapsd_be = BIT(0)|BIT(1); 1482554c0a3aSHans de Goede else 1483554c0a3aSHans de Goede pstat->uapsd_be = 0; 1484554c0a3aSHans de Goede 1485554c0a3aSHans de Goede } 1486554c0a3aSHans de Goede 1487554c0a3aSHans de Goede break; 1488554c0a3aSHans de Goede } 1489554c0a3aSHans de Goede } else { 1490554c0a3aSHans de Goede break; 1491554c0a3aSHans de Goede } 1492554c0a3aSHans de Goede p = p + ie_len + 2; 1493554c0a3aSHans de Goede } 1494554c0a3aSHans de Goede } 1495554c0a3aSHans de Goede 1496554c0a3aSHans de Goede /* save HT capabilities in the sta object */ 1497c25d8a7dSRoss Schmidt memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap)); 1498c25d8a7dSRoss Schmidt if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) { 1499554c0a3aSHans de Goede pstat->flags |= WLAN_STA_HT; 1500554c0a3aSHans de Goede 1501554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WME; 1502554c0a3aSHans de Goede 1503c25d8a7dSRoss Schmidt memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap)); 1504554c0a3aSHans de Goede 1505554c0a3aSHans de Goede } else 1506554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_HT; 1507554c0a3aSHans de Goede 1508554c0a3aSHans de Goede 1509554c0a3aSHans de Goede if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT)) { 15106d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1511554c0a3aSHans de Goede goto OnAssocReqFail; 1512554c0a3aSHans de Goede } 1513554c0a3aSHans de Goede 1514554c0a3aSHans de Goede 1515554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_HT) && 1516554c0a3aSHans de Goede ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) || 1517554c0a3aSHans de Goede (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) { 1518bbda3ac4SRoss Schmidt DBG_871X("HT: %pM tried to use TKIP with HT association\n", MAC_ARG(pstat->hwaddr)); 1519554c0a3aSHans de Goede 15206d75b504SRoss Schmidt /* status = WLAN_STATUS_CIPHER_SUITE_REJECTED; */ 1521554c0a3aSHans de Goede /* goto OnAssocReqFail; */ 1522554c0a3aSHans de Goede } 1523554c0a3aSHans de Goede pstat->flags |= WLAN_STA_NONERP; 1524554c0a3aSHans de Goede for (i = 0; i < pstat->bssratelen; i++) { 1525554c0a3aSHans de Goede if ((pstat->bssrateset[i] & 0x7f) > 22) { 1526554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_NONERP; 1527554c0a3aSHans de Goede break; 1528554c0a3aSHans de Goede } 1529554c0a3aSHans de Goede } 1530554c0a3aSHans de Goede 1531554c0a3aSHans de Goede if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) 1532554c0a3aSHans de Goede pstat->flags |= WLAN_STA_SHORT_PREAMBLE; 1533554c0a3aSHans de Goede else 1534554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE; 1535554c0a3aSHans de Goede 1536554c0a3aSHans de Goede 1537554c0a3aSHans de Goede 15386d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 1539554c0a3aSHans de Goede goto OnAssocReqFail; 1540554c0a3aSHans de Goede 1541554c0a3aSHans de Goede /* TODO: identify_proprietary_vendor_ie(); */ 1542554c0a3aSHans de Goede /* Realtek proprietary IE */ 1543554c0a3aSHans de Goede /* identify if this is Broadcom sta */ 1544554c0a3aSHans de Goede /* identify if this is ralink sta */ 1545554c0a3aSHans de Goede /* Customer proprietary IE */ 1546554c0a3aSHans de Goede 1547554c0a3aSHans de Goede 1548554c0a3aSHans de Goede 1549554c0a3aSHans de Goede /* get a unique AID */ 1550554c0a3aSHans de Goede if (pstat->aid > 0) { 1551554c0a3aSHans de Goede DBG_871X(" old AID %d\n", pstat->aid); 1552554c0a3aSHans de Goede } else { 155387e4a540SYoung Xiao for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) 1554554c0a3aSHans de Goede if (pstapriv->sta_aid[pstat->aid - 1] == NULL) 1555554c0a3aSHans de Goede break; 1556554c0a3aSHans de Goede 1557554c0a3aSHans de Goede /* if (pstat->aid > NUM_STA) { */ 1558554c0a3aSHans de Goede if (pstat->aid > pstapriv->max_num_sta) { 1559554c0a3aSHans de Goede 1560554c0a3aSHans de Goede pstat->aid = 0; 1561554c0a3aSHans de Goede 1562554c0a3aSHans de Goede DBG_871X(" no room for more AIDs\n"); 1563554c0a3aSHans de Goede 1564554c0a3aSHans de Goede status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 1565554c0a3aSHans de Goede 1566554c0a3aSHans de Goede goto OnAssocReqFail; 1567554c0a3aSHans de Goede 1568554c0a3aSHans de Goede 1569554c0a3aSHans de Goede } else { 1570554c0a3aSHans de Goede pstapriv->sta_aid[pstat->aid - 1] = pstat; 1571554c0a3aSHans de Goede DBG_871X("allocate new AID = (%d)\n", pstat->aid); 1572554c0a3aSHans de Goede } 1573554c0a3aSHans de Goede } 1574554c0a3aSHans de Goede 1575554c0a3aSHans de Goede 1576554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_ASSOC_STATE); 1577554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_SUCCESS; 1578554c0a3aSHans de Goede 1579554c0a3aSHans de Goede spin_lock_bh(&pstapriv->auth_list_lock); 1580554c0a3aSHans de Goede if (!list_empty(&pstat->auth_list)) { 1581554c0a3aSHans de Goede list_del_init(&pstat->auth_list); 1582554c0a3aSHans de Goede pstapriv->auth_list_cnt--; 1583554c0a3aSHans de Goede } 1584554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->auth_list_lock); 1585554c0a3aSHans de Goede 1586554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1587554c0a3aSHans de Goede if (list_empty(&pstat->asoc_list)) { 1588554c0a3aSHans de Goede pstat->expire_to = pstapriv->expire_to; 1589554c0a3aSHans de Goede list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list); 1590554c0a3aSHans de Goede pstapriv->asoc_list_cnt++; 1591554c0a3aSHans de Goede } 1592554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1593554c0a3aSHans de Goede 1594554c0a3aSHans de Goede /* now the station is qualified to join our BSS... */ 15956d75b504SRoss Schmidt if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (WLAN_STATUS_SUCCESS == status)) { 1596554c0a3aSHans de Goede /* 1 bss_cap_update & sta_info_update */ 1597554c0a3aSHans de Goede bss_cap_update_on_sta_join(padapter, pstat); 1598554c0a3aSHans de Goede sta_info_update(padapter, pstat); 1599554c0a3aSHans de Goede 1600554c0a3aSHans de Goede /* 2 issue assoc rsp before notify station join event. */ 1601554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) 1602554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); 1603554c0a3aSHans de Goede else 1604554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); 1605554c0a3aSHans de Goede 1606554c0a3aSHans de Goede spin_lock_bh(&pstat->lock); 1607554c0a3aSHans de Goede if (pstat->passoc_req) { 1608554c0a3aSHans de Goede kfree(pstat->passoc_req); 1609554c0a3aSHans de Goede pstat->passoc_req = NULL; 1610554c0a3aSHans de Goede pstat->assoc_req_len = 0; 1611554c0a3aSHans de Goede } 1612554c0a3aSHans de Goede 1613554c0a3aSHans de Goede pstat->passoc_req = rtw_zmalloc(pkt_len); 1614554c0a3aSHans de Goede if (pstat->passoc_req) { 1615554c0a3aSHans de Goede memcpy(pstat->passoc_req, pframe, pkt_len); 1616554c0a3aSHans de Goede pstat->assoc_req_len = pkt_len; 1617554c0a3aSHans de Goede } 1618554c0a3aSHans de Goede spin_unlock_bh(&pstat->lock); 1619554c0a3aSHans de Goede 1620554c0a3aSHans de Goede /* 3-(1) report sta add event */ 1621554c0a3aSHans de Goede report_add_sta_event(padapter, pstat->hwaddr, pstat->aid); 1622554c0a3aSHans de Goede } 1623554c0a3aSHans de Goede 1624554c0a3aSHans de Goede return _SUCCESS; 1625554c0a3aSHans de Goede 1626554c0a3aSHans de Goede asoc_class2_error: 1627554c0a3aSHans de Goede 1628554c0a3aSHans de Goede issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status); 1629554c0a3aSHans de Goede 1630554c0a3aSHans de Goede return _FAIL; 1631554c0a3aSHans de Goede 1632554c0a3aSHans de Goede OnAssocReqFail: 1633554c0a3aSHans de Goede 1634554c0a3aSHans de Goede pstat->aid = 0; 1635554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) 1636554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); 1637554c0a3aSHans de Goede else 1638554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); 1639554c0a3aSHans de Goede 1640554c0a3aSHans de Goede return _FAIL; 1641554c0a3aSHans de Goede } 1642554c0a3aSHans de Goede 1643554c0a3aSHans de Goede unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame) 1644554c0a3aSHans de Goede { 1645554c0a3aSHans de Goede uint i; 1646554c0a3aSHans de Goede int res; 1647554c0a3aSHans de Goede unsigned short status; 1648554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 1649554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1650554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1651554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1652554c0a3aSHans de Goede /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */ 1653554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1654554c0a3aSHans de Goede uint pkt_len = precv_frame->u.hdr.len; 1655554c0a3aSHans de Goede 1656554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1657554c0a3aSHans de Goede 1658554c0a3aSHans de Goede /* check A1 matches or not */ 1659554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) 1660554c0a3aSHans de Goede return _SUCCESS; 1661554c0a3aSHans de Goede 1662554c0a3aSHans de Goede if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) 1663554c0a3aSHans de Goede return _SUCCESS; 1664554c0a3aSHans de Goede 1665554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) 1666554c0a3aSHans de Goede return _SUCCESS; 1667554c0a3aSHans de Goede 1668554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 1669554c0a3aSHans de Goede 1670554c0a3aSHans de Goede /* status */ 1671554c0a3aSHans de Goede status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2)); 1672554c0a3aSHans de Goede if (status > 0) { 1673554c0a3aSHans de Goede DBG_871X("assoc reject, status code: %d\n", status); 1674554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 1675554c0a3aSHans de Goede res = -4; 1676554c0a3aSHans de Goede goto report_assoc_result; 1677554c0a3aSHans de Goede } 1678554c0a3aSHans de Goede 1679554c0a3aSHans de Goede /* get capabilities */ 1680554c0a3aSHans de Goede pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1681554c0a3aSHans de Goede 1682554c0a3aSHans de Goede /* set slot time */ 1683554c0a3aSHans de Goede pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20; 1684554c0a3aSHans de Goede 1685554c0a3aSHans de Goede /* AID */ 1686554c0a3aSHans de Goede res = pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff); 1687554c0a3aSHans de Goede 1688554c0a3aSHans de Goede /* following are moved to join event callback function */ 1689554c0a3aSHans de Goede /* to handle HT, WMM, rate adaptive, update MAC reg */ 1690554c0a3aSHans de Goede /* for not to handle the synchronous IO in the tasklet */ 1691554c0a3aSHans de Goede for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) { 1692554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pframe + i); 1693554c0a3aSHans de Goede 1694554c0a3aSHans de Goede switch (pIE->ElementID) { 1695b05cc3a9SRoss Schmidt case WLAN_EID_VENDOR_SPECIFIC: 1696554c0a3aSHans de Goede if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */ 1697554c0a3aSHans de Goede WMM_param_handler(padapter, pIE); 1698554c0a3aSHans de Goede break; 1699554c0a3aSHans de Goede 1700fc6a6528SRoss Schmidt case WLAN_EID_HT_CAPABILITY: /* HT caps */ 1701554c0a3aSHans de Goede HT_caps_handler(padapter, pIE); 1702554c0a3aSHans de Goede break; 1703554c0a3aSHans de Goede 1704332ec9dbSRoss Schmidt case WLAN_EID_HT_OPERATION: /* HT info */ 1705554c0a3aSHans de Goede HT_info_handler(padapter, pIE); 1706554c0a3aSHans de Goede break; 1707554c0a3aSHans de Goede 1708554c0a3aSHans de Goede case _ERPINFO_IE_: 1709554c0a3aSHans de Goede ERP_IE_handler(padapter, pIE); 17102811861bSGustavo A. R. Silva break; 1711554c0a3aSHans de Goede 1712554c0a3aSHans de Goede default: 1713554c0a3aSHans de Goede break; 1714554c0a3aSHans de Goede } 1715554c0a3aSHans de Goede 1716554c0a3aSHans de Goede i += (pIE->Length + 2); 1717554c0a3aSHans de Goede } 1718554c0a3aSHans de Goede 1719554c0a3aSHans de Goede pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE); 1720554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 1721554c0a3aSHans de Goede 1722554c0a3aSHans de Goede /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ 1723554c0a3aSHans de Goede UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates); 1724554c0a3aSHans de Goede 1725554c0a3aSHans de Goede report_assoc_result: 1726554c0a3aSHans de Goede if (res > 0) { 1727554c0a3aSHans de Goede rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len); 1728554c0a3aSHans de Goede } else { 1729554c0a3aSHans de Goede rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len); 1730554c0a3aSHans de Goede } 1731554c0a3aSHans de Goede 1732554c0a3aSHans de Goede report_join_res(padapter, res); 1733554c0a3aSHans de Goede 1734554c0a3aSHans de Goede return _SUCCESS; 1735554c0a3aSHans de Goede } 1736554c0a3aSHans de Goede 1737554c0a3aSHans de Goede unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame) 1738554c0a3aSHans de Goede { 1739554c0a3aSHans de Goede unsigned short reason; 1740554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1741554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1742554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1743554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1744554c0a3aSHans de Goede 1745554c0a3aSHans de Goede /* check A3 */ 1746554c0a3aSHans de Goede if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) 1747554c0a3aSHans de Goede return _SUCCESS; 1748554c0a3aSHans de Goede 1749554c0a3aSHans de Goede reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1750554c0a3aSHans de Goede 1751554c0a3aSHans de Goede DBG_871X("%s Reason code(%d)\n", __func__, reason); 1752554c0a3aSHans de Goede 17530ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 1754554c0a3aSHans de Goede struct sta_info *psta; 1755554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1756554c0a3aSHans de Goede 1757554c0a3aSHans de Goede /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ 1758554c0a3aSHans de Goede /* rtw_free_stainfo(padapter, psta); */ 1759554c0a3aSHans de Goede /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ 1760554c0a3aSHans de Goede 1761554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n", 1762554c0a3aSHans de Goede reason, GetAddr2Ptr(pframe)); 1763554c0a3aSHans de Goede 1764554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1765554c0a3aSHans de Goede if (psta) { 1766554c0a3aSHans de Goede u8 updated = false; 1767554c0a3aSHans de Goede 1768554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1769554c0a3aSHans de Goede if (list_empty(&psta->asoc_list) == false) { 1770554c0a3aSHans de Goede list_del_init(&psta->asoc_list); 1771554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 1772554c0a3aSHans de Goede updated = ap_free_sta(padapter, psta, false, reason); 1773554c0a3aSHans de Goede 1774554c0a3aSHans de Goede } 1775554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1776554c0a3aSHans de Goede 1777554c0a3aSHans de Goede associated_clients_update(padapter, updated); 1778554c0a3aSHans de Goede } 1779554c0a3aSHans de Goede 1780554c0a3aSHans de Goede 1781554c0a3aSHans de Goede return _SUCCESS; 1782554c0a3aSHans de Goede } else { 1783554c0a3aSHans de Goede int ignore_received_deauth = 0; 1784554c0a3aSHans de Goede 1785554c0a3aSHans de Goede /* Commented by Albert 20130604 */ 1786554c0a3aSHans de Goede /* Before sending the auth frame to start the STA/GC mode connection with AP/GO, */ 1787554c0a3aSHans de Goede /* we will send the deauth first. */ 1788554c0a3aSHans de Goede /* However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */ 1789554c0a3aSHans de Goede /* Added the following code to avoid this case. */ 1790554c0a3aSHans de Goede if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) || 1791554c0a3aSHans de Goede (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) { 1792554c0a3aSHans de Goede if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) { 1793554c0a3aSHans de Goede ignore_received_deauth = 1; 1794554c0a3aSHans de Goede } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) { 1795554c0a3aSHans de Goede /* TODO: 802.11r */ 1796554c0a3aSHans de Goede ignore_received_deauth = 1; 1797554c0a3aSHans de Goede } 1798554c0a3aSHans de Goede } 1799554c0a3aSHans de Goede 1800554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n", 1801554c0a3aSHans de Goede reason, GetAddr3Ptr(pframe), ignore_received_deauth); 1802554c0a3aSHans de Goede 1803554c0a3aSHans de Goede if (0 == ignore_received_deauth) { 1804554c0a3aSHans de Goede receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); 1805554c0a3aSHans de Goede } 1806554c0a3aSHans de Goede } 1807554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bBusyTraffic = false; 1808554c0a3aSHans de Goede return _SUCCESS; 1809554c0a3aSHans de Goede 1810554c0a3aSHans de Goede } 1811554c0a3aSHans de Goede 1812554c0a3aSHans de Goede unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame) 1813554c0a3aSHans de Goede { 1814554c0a3aSHans de Goede unsigned short reason; 1815554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1816554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1817554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1818554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1819554c0a3aSHans de Goede 1820554c0a3aSHans de Goede /* check A3 */ 1821554c0a3aSHans de Goede if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) 1822554c0a3aSHans de Goede return _SUCCESS; 1823554c0a3aSHans de Goede 1824554c0a3aSHans de Goede reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1825554c0a3aSHans de Goede 1826554c0a3aSHans de Goede DBG_871X("%s Reason code(%d)\n", __func__, reason); 1827554c0a3aSHans de Goede 18280ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 1829554c0a3aSHans de Goede struct sta_info *psta; 1830554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1831554c0a3aSHans de Goede 1832554c0a3aSHans de Goede /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ 1833554c0a3aSHans de Goede /* rtw_free_stainfo(padapter, psta); */ 1834554c0a3aSHans de Goede /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ 1835554c0a3aSHans de Goede 1836554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", 1837554c0a3aSHans de Goede reason, GetAddr2Ptr(pframe)); 1838554c0a3aSHans de Goede 1839554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1840554c0a3aSHans de Goede if (psta) { 1841554c0a3aSHans de Goede u8 updated = false; 1842554c0a3aSHans de Goede 1843554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1844554c0a3aSHans de Goede if (list_empty(&psta->asoc_list) == false) { 1845554c0a3aSHans de Goede list_del_init(&psta->asoc_list); 1846554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 1847554c0a3aSHans de Goede updated = ap_free_sta(padapter, psta, false, reason); 1848554c0a3aSHans de Goede 1849554c0a3aSHans de Goede } 1850554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1851554c0a3aSHans de Goede 1852554c0a3aSHans de Goede associated_clients_update(padapter, updated); 1853554c0a3aSHans de Goede } 1854554c0a3aSHans de Goede 1855554c0a3aSHans de Goede return _SUCCESS; 1856554c0a3aSHans de Goede } else { 1857554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "sta recv disassoc reason code(%d) sta:%pM\n", 1858554c0a3aSHans de Goede reason, GetAddr3Ptr(pframe)); 1859554c0a3aSHans de Goede 1860554c0a3aSHans de Goede receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); 1861554c0a3aSHans de Goede } 1862554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bBusyTraffic = false; 1863554c0a3aSHans de Goede return _SUCCESS; 1864554c0a3aSHans de Goede 1865554c0a3aSHans de Goede } 1866554c0a3aSHans de Goede 1867554c0a3aSHans de Goede unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame) 1868554c0a3aSHans de Goede { 1869554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1870554c0a3aSHans de Goede return _SUCCESS; 1871554c0a3aSHans de Goede } 1872554c0a3aSHans de Goede 1873554c0a3aSHans de Goede unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame) 1874554c0a3aSHans de Goede { 1875554c0a3aSHans de Goede struct sta_info *psta = NULL; 1876554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1877554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1878554c0a3aSHans de Goede u8 *frame_body = (u8 *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1879554c0a3aSHans de Goede u8 category; 1880554c0a3aSHans de Goede u8 action; 1881554c0a3aSHans de Goede 1882554c0a3aSHans de Goede DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev)); 1883554c0a3aSHans de Goede 1884554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1885554c0a3aSHans de Goede 1886554c0a3aSHans de Goede if (!psta) 1887554c0a3aSHans de Goede goto exit; 1888554c0a3aSHans de Goede 1889554c0a3aSHans de Goede category = frame_body[0]; 1890554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT) 1891554c0a3aSHans de Goede goto exit; 1892554c0a3aSHans de Goede 1893554c0a3aSHans de Goede action = frame_body[1]; 1894554c0a3aSHans de Goede switch (action) { 189572cac683SRoss Schmidt case WLAN_ACTION_SPCT_MSR_REQ: 189672cac683SRoss Schmidt case WLAN_ACTION_SPCT_MSR_RPRT: 189772cac683SRoss Schmidt case WLAN_ACTION_SPCT_TPC_REQ: 189872cac683SRoss Schmidt case WLAN_ACTION_SPCT_TPC_RPRT: 189972cac683SRoss Schmidt case WLAN_ACTION_SPCT_CHL_SWITCH: 1900554c0a3aSHans de Goede break; 1901554c0a3aSHans de Goede default: 1902554c0a3aSHans de Goede break; 1903554c0a3aSHans de Goede } 1904554c0a3aSHans de Goede 1905554c0a3aSHans de Goede exit: 19061c4bfacfSHariprasad Kelam return _FAIL; 1907554c0a3aSHans de Goede } 1908554c0a3aSHans de Goede 1909554c0a3aSHans de Goede unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame) 1910554c0a3aSHans de Goede { 1911554c0a3aSHans de Goede u8 *addr; 1912554c0a3aSHans de Goede struct sta_info *psta = NULL; 1913554c0a3aSHans de Goede struct recv_reorder_ctrl *preorder_ctrl; 1914554c0a3aSHans de Goede unsigned char *frame_body; 1915554c0a3aSHans de Goede unsigned char category, action; 1916554c0a3aSHans de Goede unsigned short tid, status, reason_code = 0; 1917554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1918554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1919554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1920554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1921554c0a3aSHans de Goede 1922554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 1923554c0a3aSHans de Goede 1924554c0a3aSHans de Goede /* check RA matches or not */ 1925554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */ 1926554c0a3aSHans de Goede return _SUCCESS; 1927554c0a3aSHans de Goede 1928554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 1929554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) 1930554c0a3aSHans de Goede return _SUCCESS; 1931554c0a3aSHans de Goede 1932554c0a3aSHans de Goede addr = GetAddr2Ptr(pframe); 1933554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, addr); 1934554c0a3aSHans de Goede 193541452327SVatsala Narang if (!psta) 1936554c0a3aSHans de Goede return _SUCCESS; 1937554c0a3aSHans de Goede 1938554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1939554c0a3aSHans de Goede 1940554c0a3aSHans de Goede category = frame_body[0]; 1941554c0a3aSHans de Goede if (category == RTW_WLAN_CATEGORY_BACK) {/* representing Block Ack */ 1942a65f0d18SVatsala Narang if (!pmlmeinfo->HT_enable) 1943554c0a3aSHans de Goede return _SUCCESS; 1944554c0a3aSHans de Goede 1945554c0a3aSHans de Goede action = frame_body[1]; 1946554c0a3aSHans de Goede DBG_871X("%s, action =%d\n", __func__, action); 1947554c0a3aSHans de Goede switch (action) { 1948f4acd33cSRoss Schmidt case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ 1949554c0a3aSHans de Goede 1950554c0a3aSHans de Goede memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); 1951554c0a3aSHans de Goede /* process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */ 1952554c0a3aSHans de Goede process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); 1953554c0a3aSHans de Goede 19542646633fSAastha Gupta if (pmlmeinfo->accept_addba_req) { 1955f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 0); 1956554c0a3aSHans de Goede } else { 1957f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */ 1958554c0a3aSHans de Goede } 1959554c0a3aSHans de Goede 1960554c0a3aSHans de Goede break; 1961554c0a3aSHans de Goede 1962f4acd33cSRoss Schmidt case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ 1963d48603afSRoss Schmidt status = get_unaligned_le16(&frame_body[3]); 1964554c0a3aSHans de Goede tid = ((frame_body[5] >> 2) & 0x7); 1965554c0a3aSHans de Goede 1966554c0a3aSHans de Goede if (status == 0) { 1967554c0a3aSHans de Goede /* successful */ 1968554c0a3aSHans de Goede DBG_871X("agg_enable for TID =%d\n", tid); 1969e52d8d0dSVatsala Narang psta->htpriv.agg_enable_bitmap |= BIT(tid); 1970554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); 1971554c0a3aSHans de Goede } else { 1972554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 1973554c0a3aSHans de Goede } 1974554c0a3aSHans de Goede 1975554c0a3aSHans de Goede if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { 1976554c0a3aSHans de Goede DBG_871X("%s alive check - rx ADDBA response\n", __func__); 1977554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 1978554c0a3aSHans de Goede psta->expire_to = pstapriv->expire_to; 1979554c0a3aSHans de Goede psta->state ^= WIFI_STA_ALIVE_CHK_STATE; 1980554c0a3aSHans de Goede } 1981554c0a3aSHans de Goede 1982554c0a3aSHans de Goede /* DBG_871X("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap); */ 1983554c0a3aSHans de Goede break; 1984554c0a3aSHans de Goede 1985f4acd33cSRoss Schmidt case WLAN_ACTION_DELBA: /* DELBA */ 1986554c0a3aSHans de Goede if ((frame_body[3] & BIT(3)) == 0) { 1987e52d8d0dSVatsala Narang psta->htpriv.agg_enable_bitmap &= 1988e52d8d0dSVatsala Narang ~BIT((frame_body[3] >> 4) & 0xf); 1989e52d8d0dSVatsala Narang psta->htpriv.candidate_tid_bitmap &= 1990e52d8d0dSVatsala Narang ~BIT((frame_body[3] >> 4) & 0xf); 1991554c0a3aSHans de Goede 1992554c0a3aSHans de Goede /* reason_code = frame_body[4] | (frame_body[5] << 8); */ 1993d48603afSRoss Schmidt reason_code = get_unaligned_le16(&frame_body[4]); 1994554c0a3aSHans de Goede } else if ((frame_body[3] & BIT(3)) == BIT(3)) { 1995554c0a3aSHans de Goede tid = (frame_body[3] >> 4) & 0x0F; 1996554c0a3aSHans de Goede 1997554c0a3aSHans de Goede preorder_ctrl = &psta->recvreorder_ctrl[tid]; 1998554c0a3aSHans de Goede preorder_ctrl->enable = false; 1999554c0a3aSHans de Goede preorder_ctrl->indicate_seq = 0xffff; 2000554c0a3aSHans de Goede #ifdef DBG_RX_SEQ 2001554c0a3aSHans de Goede DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__, 2002554c0a3aSHans de Goede preorder_ctrl->indicate_seq); 2003554c0a3aSHans de Goede #endif 2004554c0a3aSHans de Goede } 2005554c0a3aSHans de Goede 2006554c0a3aSHans de Goede DBG_871X("%s(): DELBA: %x(%x)\n", __func__, pmlmeinfo->agg_enable_bitmap, reason_code); 2007554c0a3aSHans de Goede /* todo: how to notify the host while receiving DELETE BA */ 2008554c0a3aSHans de Goede break; 2009554c0a3aSHans de Goede 2010554c0a3aSHans de Goede default: 2011554c0a3aSHans de Goede break; 2012554c0a3aSHans de Goede } 2013554c0a3aSHans de Goede } 2014554c0a3aSHans de Goede return _SUCCESS; 2015554c0a3aSHans de Goede } 2016554c0a3aSHans de Goede 2017554c0a3aSHans de Goede static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token) 2018554c0a3aSHans de Goede { 2019554c0a3aSHans de Goede struct adapter *adapter = recv_frame->u.hdr.adapter; 2020554c0a3aSHans de Goede struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv); 2021554c0a3aSHans de Goede u8 *frame = recv_frame->u.hdr.rx_data; 2022554c0a3aSHans de Goede u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) | 2023554c0a3aSHans de Goede (recv_frame->u.hdr.attrib.frag_num & 0xf); 2024554c0a3aSHans de Goede 2025554c0a3aSHans de Goede if (GetRetry(frame)) { 2026554c0a3aSHans de Goede if (token >= 0) { 2027554c0a3aSHans de Goede if ((seq_ctrl == mlmeext->action_public_rxseq) 2028554c0a3aSHans de Goede && (token == mlmeext->action_public_dialog_token)) { 2029554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x, token:%d\n", 2030554c0a3aSHans de Goede FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token); 2031554c0a3aSHans de Goede return _FAIL; 2032554c0a3aSHans de Goede } 2033554c0a3aSHans de Goede } else { 2034554c0a3aSHans de Goede if (seq_ctrl == mlmeext->action_public_rxseq) { 2035554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" seq_ctrl = 0x%x, rxseq = 0x%x\n", 2036554c0a3aSHans de Goede FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq); 2037554c0a3aSHans de Goede return _FAIL; 2038554c0a3aSHans de Goede } 2039554c0a3aSHans de Goede } 2040554c0a3aSHans de Goede } 2041554c0a3aSHans de Goede 2042554c0a3aSHans de Goede mlmeext->action_public_rxseq = seq_ctrl; 2043554c0a3aSHans de Goede 2044554c0a3aSHans de Goede if (token >= 0) 2045554c0a3aSHans de Goede mlmeext->action_public_dialog_token = token; 2046554c0a3aSHans de Goede 2047554c0a3aSHans de Goede return _SUCCESS; 2048554c0a3aSHans de Goede } 2049554c0a3aSHans de Goede 2050554c0a3aSHans de Goede static unsigned int on_action_public_p2p(union recv_frame *precv_frame) 2051554c0a3aSHans de Goede { 2052554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2053554c0a3aSHans de Goede u8 *frame_body; 2054554c0a3aSHans de Goede u8 dialogToken = 0; 2055554c0a3aSHans de Goede 2056554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 2057554c0a3aSHans de Goede 2058554c0a3aSHans de Goede dialogToken = frame_body[7]; 2059554c0a3aSHans de Goede 2060554c0a3aSHans de Goede if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL) 2061554c0a3aSHans de Goede return _FAIL; 2062554c0a3aSHans de Goede 2063554c0a3aSHans de Goede return _SUCCESS; 2064554c0a3aSHans de Goede } 2065554c0a3aSHans de Goede 2066554c0a3aSHans de Goede static unsigned int on_action_public_vendor(union recv_frame *precv_frame) 2067554c0a3aSHans de Goede { 2068554c0a3aSHans de Goede unsigned int ret = _FAIL; 2069554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2070554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 2071554c0a3aSHans de Goede 2072554c0a3aSHans de Goede if (!memcmp(frame_body + 2, P2P_OUI, 4)) { 2073554c0a3aSHans de Goede ret = on_action_public_p2p(precv_frame); 2074554c0a3aSHans de Goede } 2075554c0a3aSHans de Goede 2076554c0a3aSHans de Goede return ret; 2077554c0a3aSHans de Goede } 2078554c0a3aSHans de Goede 2079554c0a3aSHans de Goede static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action) 2080554c0a3aSHans de Goede { 2081554c0a3aSHans de Goede unsigned int ret = _FAIL; 2082554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2083554c0a3aSHans de Goede uint frame_len = precv_frame->u.hdr.len; 2084554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 2085554c0a3aSHans de Goede u8 token; 2086554c0a3aSHans de Goede struct adapter *adapter = precv_frame->u.hdr.adapter; 2087554c0a3aSHans de Goede int cnt = 0; 2088554c0a3aSHans de Goede char msg[64]; 2089554c0a3aSHans de Goede 2090554c0a3aSHans de Goede token = frame_body[2]; 2091554c0a3aSHans de Goede 2092554c0a3aSHans de Goede if (rtw_action_public_decache(precv_frame, token) == _FAIL) 2093554c0a3aSHans de Goede goto exit; 2094554c0a3aSHans de Goede 2095554c0a3aSHans de Goede cnt += sprintf((msg+cnt), "%s(token:%u)", action_public_str(action), token); 2096554c0a3aSHans de Goede rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg); 2097554c0a3aSHans de Goede 2098554c0a3aSHans de Goede ret = _SUCCESS; 2099554c0a3aSHans de Goede 2100554c0a3aSHans de Goede exit: 2101554c0a3aSHans de Goede return ret; 2102554c0a3aSHans de Goede } 2103554c0a3aSHans de Goede 2104554c0a3aSHans de Goede unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame) 2105554c0a3aSHans de Goede { 2106554c0a3aSHans de Goede unsigned int ret = _FAIL; 2107554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2108554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 2109554c0a3aSHans de Goede u8 category, action; 2110554c0a3aSHans de Goede 2111554c0a3aSHans de Goede /* check RA matches or not */ 2112554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN)) 2113554c0a3aSHans de Goede goto exit; 2114554c0a3aSHans de Goede 2115554c0a3aSHans de Goede category = frame_body[0]; 2116554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_PUBLIC) 2117554c0a3aSHans de Goede goto exit; 2118554c0a3aSHans de Goede 2119554c0a3aSHans de Goede action = frame_body[1]; 2120554c0a3aSHans de Goede switch (action) { 2121554c0a3aSHans de Goede case ACT_PUBLIC_VENDOR: 2122554c0a3aSHans de Goede ret = on_action_public_vendor(precv_frame); 2123554c0a3aSHans de Goede break; 2124554c0a3aSHans de Goede default: 2125554c0a3aSHans de Goede ret = on_action_public_default(precv_frame, action); 2126554c0a3aSHans de Goede break; 2127554c0a3aSHans de Goede } 2128554c0a3aSHans de Goede 2129554c0a3aSHans de Goede exit: 2130554c0a3aSHans de Goede return ret; 2131554c0a3aSHans de Goede } 2132554c0a3aSHans de Goede 2133554c0a3aSHans de Goede unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame) 2134554c0a3aSHans de Goede { 2135554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2136554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 2137554c0a3aSHans de Goede u8 category, action; 2138554c0a3aSHans de Goede 2139554c0a3aSHans de Goede /* check RA matches or not */ 2140554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN)) 2141554c0a3aSHans de Goede goto exit; 2142554c0a3aSHans de Goede 2143554c0a3aSHans de Goede category = frame_body[0]; 2144554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_HT) 2145554c0a3aSHans de Goede goto exit; 2146554c0a3aSHans de Goede 2147554c0a3aSHans de Goede action = frame_body[1]; 2148554c0a3aSHans de Goede switch (action) { 2149a9d87638SRoss Schmidt case WLAN_HT_ACTION_COMPRESSED_BF: 2150554c0a3aSHans de Goede break; 2151554c0a3aSHans de Goede default: 2152554c0a3aSHans de Goede break; 2153554c0a3aSHans de Goede } 2154554c0a3aSHans de Goede 2155554c0a3aSHans de Goede exit: 2156554c0a3aSHans de Goede 2157554c0a3aSHans de Goede return _SUCCESS; 2158554c0a3aSHans de Goede } 2159554c0a3aSHans de Goede 2160554c0a3aSHans de Goede unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv_frame) 2161554c0a3aSHans de Goede { 2162554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2163554c0a3aSHans de Goede struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; 2164554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2165554c0a3aSHans de Goede unsigned short tid; 2166554c0a3aSHans de Goede /* Baron */ 2167554c0a3aSHans de Goede 2168554c0a3aSHans de Goede DBG_871X("OnAction_sa_query\n"); 2169554c0a3aSHans de Goede 2170554c0a3aSHans de Goede switch (pframe[WLAN_HDR_A3_LEN+1]) { 2171554c0a3aSHans de Goede case 0: /* SA Query req */ 2172554c0a3aSHans de Goede memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short)); 2173554c0a3aSHans de Goede DBG_871X("OnAction_sa_query request, action =%d, tid =%04x\n", pframe[WLAN_HDR_A3_LEN+1], tid); 2174554c0a3aSHans de Goede issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid); 2175554c0a3aSHans de Goede break; 2176554c0a3aSHans de Goede 2177554c0a3aSHans de Goede case 1: /* SA Query rsp */ 2178554c0a3aSHans de Goede del_timer_sync(&pmlmeext->sa_query_timer); 2179554c0a3aSHans de Goede 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]); 2180554c0a3aSHans de Goede break; 2181554c0a3aSHans de Goede default: 2182554c0a3aSHans de Goede break; 2183554c0a3aSHans de Goede } 2184554c0a3aSHans de Goede if (0) { 2185554c0a3aSHans de Goede int pp; 2186c926f022SSimran Singhal 2187554c0a3aSHans de Goede printk("pattrib->pktlen = %d =>", pattrib->pkt_len); 2188554c0a3aSHans de Goede for (pp = 0; pp < pattrib->pkt_len; pp++) 2189554c0a3aSHans de Goede printk(" %02x ", pframe[pp]); 2190554c0a3aSHans de Goede printk("\n"); 2191554c0a3aSHans de Goede } 2192554c0a3aSHans de Goede 2193554c0a3aSHans de Goede return _SUCCESS; 2194554c0a3aSHans de Goede } 2195554c0a3aSHans de Goede 2196554c0a3aSHans de Goede unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame) 2197554c0a3aSHans de Goede { 2198554c0a3aSHans de Goede int i; 2199554c0a3aSHans de Goede unsigned char category; 2200554c0a3aSHans de Goede struct action_handler *ptable; 2201554c0a3aSHans de Goede unsigned char *frame_body; 2202554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 2203554c0a3aSHans de Goede 2204554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 2205554c0a3aSHans de Goede 2206554c0a3aSHans de Goede category = frame_body[0]; 2207554c0a3aSHans de Goede 220860db8d10SJérémy Lefaure for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) { 2209554c0a3aSHans de Goede ptable = &OnAction_tbl[i]; 2210554c0a3aSHans de Goede 2211554c0a3aSHans de Goede if (category == ptable->num) 2212554c0a3aSHans de Goede ptable->func(padapter, precv_frame); 2213554c0a3aSHans de Goede 2214554c0a3aSHans de Goede } 2215554c0a3aSHans de Goede 2216554c0a3aSHans de Goede return _SUCCESS; 2217554c0a3aSHans de Goede 2218554c0a3aSHans de Goede } 2219554c0a3aSHans de Goede 2220554c0a3aSHans de Goede unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame) 2221554c0a3aSHans de Goede { 2222554c0a3aSHans de Goede 2223554c0a3aSHans de Goede /* DBG_871X("rcvd mgt frame(%x, %x)\n", (GetFrameSubType(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe)); */ 2224554c0a3aSHans de Goede return _SUCCESS; 2225554c0a3aSHans de Goede } 2226554c0a3aSHans de Goede 2227554c0a3aSHans de Goede static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once) 2228554c0a3aSHans de Goede { 2229554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2230554c0a3aSHans de Goede struct xmit_buf *pxmitbuf; 2231554c0a3aSHans de Goede 2232554c0a3aSHans de Goede if (once) 2233554c0a3aSHans de Goede pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv); 2234554c0a3aSHans de Goede else 2235554c0a3aSHans de Goede pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv); 2236554c0a3aSHans de Goede 2237554c0a3aSHans de Goede if (pmgntframe == NULL) { 2238554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once); 2239554c0a3aSHans de Goede goto exit; 2240554c0a3aSHans de Goede } 2241554c0a3aSHans de Goede 2242554c0a3aSHans de Goede pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv); 2243554c0a3aSHans de Goede if (pxmitbuf == NULL) { 2244554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter)); 2245554c0a3aSHans de Goede rtw_free_xmitframe(pxmitpriv, pmgntframe); 2246554c0a3aSHans de Goede pmgntframe = NULL; 2247554c0a3aSHans de Goede goto exit; 2248554c0a3aSHans de Goede } 2249554c0a3aSHans de Goede 2250554c0a3aSHans de Goede pmgntframe->frame_tag = MGNT_FRAMETAG; 2251554c0a3aSHans de Goede pmgntframe->pxmitbuf = pxmitbuf; 2252554c0a3aSHans de Goede pmgntframe->buf_addr = pxmitbuf->pbuf; 2253554c0a3aSHans de Goede pxmitbuf->priv_data = pmgntframe; 2254554c0a3aSHans de Goede 2255554c0a3aSHans de Goede exit: 2256554c0a3aSHans de Goede return pmgntframe; 2257554c0a3aSHans de Goede 2258554c0a3aSHans de Goede } 2259554c0a3aSHans de Goede 2260554c0a3aSHans de Goede inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv) 2261554c0a3aSHans de Goede { 2262554c0a3aSHans de Goede return _alloc_mgtxmitframe(pxmitpriv, false); 2263554c0a3aSHans de Goede } 2264554c0a3aSHans de Goede 2265554c0a3aSHans de Goede /**************************************************************************** 2266554c0a3aSHans de Goede 226768468503SAndreas Hellmich Following are some TX functions for WiFi MLME 2268554c0a3aSHans de Goede 2269554c0a3aSHans de Goede *****************************************************************************/ 2270554c0a3aSHans de Goede 2271554c0a3aSHans de Goede void update_mgnt_tx_rate(struct adapter *padapter, u8 rate) 2272554c0a3aSHans de Goede { 2273554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2274554c0a3aSHans de Goede 2275554c0a3aSHans de Goede pmlmeext->tx_rate = rate; 2276554c0a3aSHans de Goede /* DBG_871X("%s(): rate = %x\n", __func__, rate); */ 2277554c0a3aSHans de Goede } 2278554c0a3aSHans de Goede 2279554c0a3aSHans de Goede void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib) 2280554c0a3aSHans de Goede { 2281554c0a3aSHans de Goede u8 wireless_mode; 2282554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2283554c0a3aSHans de Goede 2284554c0a3aSHans de Goede /* memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */ 2285554c0a3aSHans de Goede 2286554c0a3aSHans de Goede pattrib->hdrlen = 24; 2287554c0a3aSHans de Goede pattrib->nr_frags = 1; 2288554c0a3aSHans de Goede pattrib->priority = 7; 2289554c0a3aSHans de Goede pattrib->mac_id = 0; 2290554c0a3aSHans de Goede pattrib->qsel = 0x12; 2291554c0a3aSHans de Goede 2292554c0a3aSHans de Goede pattrib->pktlen = 0; 2293554c0a3aSHans de Goede 2294554c0a3aSHans de Goede if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB) 2295554c0a3aSHans de Goede wireless_mode = WIRELESS_11B; 2296554c0a3aSHans de Goede else 2297554c0a3aSHans de Goede wireless_mode = WIRELESS_11G; 2298554c0a3aSHans de Goede pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode); 2299554c0a3aSHans de Goede pattrib->rate = pmlmeext->tx_rate; 2300554c0a3aSHans de Goede 2301554c0a3aSHans de Goede pattrib->encrypt = _NO_PRIVACY_; 2302554c0a3aSHans de Goede pattrib->bswenc = false; 2303554c0a3aSHans de Goede 2304554c0a3aSHans de Goede pattrib->qos_en = false; 2305554c0a3aSHans de Goede pattrib->ht_en = false; 2306554c0a3aSHans de Goede pattrib->bwmode = CHANNEL_WIDTH_20; 2307554c0a3aSHans de Goede pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 2308554c0a3aSHans de Goede pattrib->sgi = false; 2309554c0a3aSHans de Goede 2310554c0a3aSHans de Goede pattrib->seqnum = pmlmeext->mgnt_seq; 2311554c0a3aSHans de Goede 2312554c0a3aSHans de Goede pattrib->retry_ctrl = true; 2313554c0a3aSHans de Goede 2314554c0a3aSHans de Goede pattrib->mbssid = 0; 2315554c0a3aSHans de Goede 2316554c0a3aSHans de Goede } 2317554c0a3aSHans de Goede 2318554c0a3aSHans de Goede void update_mgntframe_attrib_addr(struct adapter *padapter, struct xmit_frame *pmgntframe) 2319554c0a3aSHans de Goede { 2320554c0a3aSHans de Goede u8 *pframe; 2321554c0a3aSHans de Goede struct pkt_attrib *pattrib = &pmgntframe->attrib; 2322554c0a3aSHans de Goede 2323554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2324554c0a3aSHans de Goede 2325554c0a3aSHans de Goede memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN); 2326554c0a3aSHans de Goede memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN); 2327554c0a3aSHans de Goede } 2328554c0a3aSHans de Goede 2329554c0a3aSHans de Goede void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe) 2330554c0a3aSHans de Goede { 23310ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 23320ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2333554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2334554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2335554c0a3aSHans de Goede return; 2336554c0a3aSHans de Goede } 2337554c0a3aSHans de Goede 2338554c0a3aSHans de Goede rtw_hal_mgnt_xmit(padapter, pmgntframe); 2339554c0a3aSHans de Goede } 2340554c0a3aSHans de Goede 2341554c0a3aSHans de Goede s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms) 2342554c0a3aSHans de Goede { 2343554c0a3aSHans de Goede s32 ret = _FAIL; 2344554c0a3aSHans de Goede _irqL irqL; 2345554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 2346554c0a3aSHans de Goede struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf; 2347554c0a3aSHans de Goede struct submit_ctx sctx; 2348554c0a3aSHans de Goede 23490ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 23500ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2351554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2352554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2353554c0a3aSHans de Goede return ret; 2354554c0a3aSHans de Goede } 2355554c0a3aSHans de Goede 2356554c0a3aSHans de Goede rtw_sctx_init(&sctx, timeout_ms); 2357554c0a3aSHans de Goede pxmitbuf->sctx = &sctx; 2358554c0a3aSHans de Goede 2359554c0a3aSHans de Goede ret = rtw_hal_mgnt_xmit(padapter, pmgntframe); 2360554c0a3aSHans de Goede 2361554c0a3aSHans de Goede if (ret == _SUCCESS) 2362554c0a3aSHans de Goede ret = rtw_sctx_wait(&sctx, __func__); 2363554c0a3aSHans de Goede 2364554c0a3aSHans de Goede spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); 2365554c0a3aSHans de Goede pxmitbuf->sctx = NULL; 2366554c0a3aSHans de Goede spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL); 2367554c0a3aSHans de Goede 2368554c0a3aSHans de Goede return ret; 2369554c0a3aSHans de Goede } 2370554c0a3aSHans de Goede 2371554c0a3aSHans de Goede s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe) 2372554c0a3aSHans de Goede { 237340d4aa0fSShreeya Patel static u8 seq_no; 2374554c0a3aSHans de Goede s32 ret = _FAIL; 2375554c0a3aSHans de Goede u32 timeout_ms = 500;/* 500ms */ 2376554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 2377554c0a3aSHans de Goede 23780ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 23790ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2380554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2381554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2382554c0a3aSHans de Goede return -1; 2383554c0a3aSHans de Goede } 2384554c0a3aSHans de Goede 2385554c0a3aSHans de Goede if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex) == 0) { 2386554c0a3aSHans de Goede pxmitpriv->ack_tx = true; 2387554c0a3aSHans de Goede pxmitpriv->seq_no = seq_no++; 2388554c0a3aSHans de Goede pmgntframe->ack_report = 1; 2389a65f0d18SVatsala Narang if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) 2390554c0a3aSHans de Goede ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms); 2391554c0a3aSHans de Goede 2392554c0a3aSHans de Goede pxmitpriv->ack_tx = false; 2393554c0a3aSHans de Goede mutex_unlock(&pxmitpriv->ack_tx_mutex); 2394554c0a3aSHans de Goede } 2395554c0a3aSHans de Goede 2396554c0a3aSHans de Goede return ret; 2397554c0a3aSHans de Goede } 2398554c0a3aSHans de Goede 2399554c0a3aSHans de Goede static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) 2400554c0a3aSHans de Goede { 2401554c0a3aSHans de Goede u8 *ssid_ie; 2402554c0a3aSHans de Goede sint ssid_len_ori; 2403554c0a3aSHans de Goede int len_diff = 0; 2404554c0a3aSHans de Goede 2405554c0a3aSHans de Goede ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len); 2406554c0a3aSHans de Goede 2407554c0a3aSHans de Goede /* DBG_871X("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __func__, hidden_ssid_mode, ssid_ie, ssid_len_ori); */ 2408554c0a3aSHans de Goede 2409554c0a3aSHans de Goede if (ssid_ie && ssid_len_ori > 0) { 2410554c0a3aSHans de Goede switch (hidden_ssid_mode) { 2411554c0a3aSHans de Goede case 1: 2412554c0a3aSHans de Goede { 2413554c0a3aSHans de Goede u8 *next_ie = ssid_ie + 2 + ssid_len_ori; 2414554c0a3aSHans de Goede u32 remain_len = 0; 2415554c0a3aSHans de Goede 2416554c0a3aSHans de Goede remain_len = ies_len - (next_ie-ies); 2417554c0a3aSHans de Goede 2418554c0a3aSHans de Goede ssid_ie[1] = 0; 2419554c0a3aSHans de Goede memcpy(ssid_ie+2, next_ie, remain_len); 2420554c0a3aSHans de Goede len_diff -= ssid_len_ori; 2421554c0a3aSHans de Goede 2422554c0a3aSHans de Goede break; 2423554c0a3aSHans de Goede } 2424554c0a3aSHans de Goede case 2: 2425554c0a3aSHans de Goede memset(&ssid_ie[2], 0, ssid_len_ori); 2426554c0a3aSHans de Goede break; 2427554c0a3aSHans de Goede default: 2428554c0a3aSHans de Goede break; 2429554c0a3aSHans de Goede } 2430554c0a3aSHans de Goede } 2431554c0a3aSHans de Goede 2432554c0a3aSHans de Goede return len_diff; 2433554c0a3aSHans de Goede } 2434554c0a3aSHans de Goede 2435554c0a3aSHans de Goede void issue_beacon(struct adapter *padapter, int timeout_ms) 2436554c0a3aSHans de Goede { 2437554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2438554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2439554c0a3aSHans de Goede unsigned char *pframe; 2440554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2441554c0a3aSHans de Goede __le16 *fctrl; 2442554c0a3aSHans de Goede unsigned int rate_len; 2443554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2444554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2445554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2446554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2447554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 2448554c0a3aSHans de Goede u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 2449554c0a3aSHans de Goede 2450554c0a3aSHans de Goede /* DBG_871X("%s\n", __func__); */ 2451554c0a3aSHans de Goede 2452554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 245341452327SVatsala Narang if (!pmgntframe) { 2454554c0a3aSHans de Goede DBG_871X("%s, alloc mgnt frame fail\n", __func__); 2455554c0a3aSHans de Goede return; 2456554c0a3aSHans de Goede } 2457554c0a3aSHans de Goede 2458554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->bcn_update_lock); 2459554c0a3aSHans de Goede 2460554c0a3aSHans de Goede /* update attribute */ 2461554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2462554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2463554c0a3aSHans de Goede pattrib->qsel = 0x10; 2464554c0a3aSHans de Goede 2465554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2466554c0a3aSHans de Goede 2467554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2468554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2469554c0a3aSHans de Goede 2470554c0a3aSHans de Goede 2471554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2472554c0a3aSHans de Goede *(fctrl) = 0; 2473554c0a3aSHans de Goede 2474554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); 2475554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 2476554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); 2477554c0a3aSHans de Goede 2478554c0a3aSHans de Goede SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); 2479554c0a3aSHans de Goede /* pmlmeext->mgnt_seq++; */ 2480554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_BEACON); 2481554c0a3aSHans de Goede 2482554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2483554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2484554c0a3aSHans de Goede 2485554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { 2486554c0a3aSHans de Goede /* DBG_871X("ie len =%d\n", cur_network->IELength); */ 2487554c0a3aSHans de Goede { 2488554c0a3aSHans de Goede int len_diff; 2489c926f022SSimran Singhal 2490554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, cur_network->IELength); 24915641eeecSRoss Schmidt len_diff = update_hidden_ssid(pframe+_BEACON_IE_OFFSET_, 24925641eeecSRoss Schmidt cur_network->IELength-_BEACON_IE_OFFSET_, 24935641eeecSRoss Schmidt pmlmeinfo->hidden_ssid_mode); 2494554c0a3aSHans de Goede pframe += (cur_network->IELength+len_diff); 2495554c0a3aSHans de Goede pattrib->pktlen += (cur_network->IELength+len_diff); 2496554c0a3aSHans de Goede } 2497554c0a3aSHans de Goede 2498554c0a3aSHans de Goede { 2499554c0a3aSHans de Goede u8 *wps_ie; 2500554c0a3aSHans de Goede uint wps_ielen; 2501554c0a3aSHans de Goede u8 sr = 0; 2502c926f022SSimran Singhal 2503554c0a3aSHans de Goede wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_, 2504554c0a3aSHans de Goede pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen); 2505554c0a3aSHans de Goede if (wps_ie && wps_ielen > 0) { 2506554c0a3aSHans de Goede rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); 2507554c0a3aSHans de Goede } 2508554c0a3aSHans de Goede if (sr != 0) 2509554c0a3aSHans de Goede set_fwstate(pmlmepriv, WIFI_UNDER_WPS); 2510554c0a3aSHans de Goede else 2511554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS); 2512554c0a3aSHans de Goede } 2513554c0a3aSHans de Goede 2514554c0a3aSHans de Goede goto _issue_bcn; 2515554c0a3aSHans de Goede 2516554c0a3aSHans de Goede } 2517554c0a3aSHans de Goede 2518554c0a3aSHans de Goede /* below for ad-hoc mode */ 2519554c0a3aSHans de Goede 2520554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 2521554c0a3aSHans de Goede pframe += 8; 2522554c0a3aSHans de Goede pattrib->pktlen += 8; 2523554c0a3aSHans de Goede 2524554c0a3aSHans de Goede /* beacon interval: 2 bytes */ 2525554c0a3aSHans de Goede 2526554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 2527554c0a3aSHans de Goede 2528554c0a3aSHans de Goede pframe += 2; 2529554c0a3aSHans de Goede pattrib->pktlen += 2; 2530554c0a3aSHans de Goede 2531554c0a3aSHans de Goede /* capability info: 2 bytes */ 2532554c0a3aSHans de Goede 2533554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); 2534554c0a3aSHans de Goede 2535554c0a3aSHans de Goede pframe += 2; 2536554c0a3aSHans de Goede pattrib->pktlen += 2; 2537554c0a3aSHans de Goede 2538554c0a3aSHans de Goede /* SSID */ 25393f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); 2540554c0a3aSHans de Goede 2541554c0a3aSHans de Goede /* supported rates... */ 2542554c0a3aSHans de Goede rate_len = rtw_get_rateset_len(cur_network->SupportedRates); 2543c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); 2544554c0a3aSHans de Goede 2545554c0a3aSHans de Goede /* DS parameter set */ 25468f6a9446SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen); 2547554c0a3aSHans de Goede 2548554c0a3aSHans de Goede /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */ 2549554c0a3aSHans de Goede { 2550554c0a3aSHans de Goede u8 erpinfo = 0; 2551554c0a3aSHans de Goede u32 ATIMWindow; 2552554c0a3aSHans de Goede /* IBSS Parameter Set... */ 2553554c0a3aSHans de Goede /* ATIMWindow = cur->Configuration.ATIMWindow; */ 2554554c0a3aSHans de Goede ATIMWindow = 0; 2555e6038a48SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); 2556554c0a3aSHans de Goede 2557554c0a3aSHans de Goede /* ERP IE */ 2558554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen); 2559554c0a3aSHans de Goede } 2560554c0a3aSHans de Goede 2561554c0a3aSHans de Goede 2562554c0a3aSHans de Goede /* EXTERNDED SUPPORTED RATE */ 2563554c0a3aSHans de Goede if (rate_len > 8) { 2564554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); 2565554c0a3aSHans de Goede } 2566554c0a3aSHans de Goede 2567554c0a3aSHans de Goede 2568554c0a3aSHans de Goede /* todo:HT for adhoc */ 2569554c0a3aSHans de Goede 2570554c0a3aSHans de Goede _issue_bcn: 2571554c0a3aSHans de Goede 2572554c0a3aSHans de Goede pmlmepriv->update_bcn = false; 2573554c0a3aSHans de Goede 2574554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->bcn_update_lock); 2575554c0a3aSHans de Goede 2576554c0a3aSHans de Goede if ((pattrib->pktlen + TXDESC_SIZE) > 512) { 2577554c0a3aSHans de Goede DBG_871X("beacon frame too large\n"); 2578554c0a3aSHans de Goede return; 2579554c0a3aSHans de Goede } 2580554c0a3aSHans de Goede 2581554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2582554c0a3aSHans de Goede 2583554c0a3aSHans de Goede /* DBG_871X("issue bcn_sz =%d\n", pattrib->last_txcmdsz); */ 2584554c0a3aSHans de Goede if (timeout_ms > 0) 2585554c0a3aSHans de Goede dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms); 2586554c0a3aSHans de Goede else 2587554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2588554c0a3aSHans de Goede 2589554c0a3aSHans de Goede } 2590554c0a3aSHans de Goede 2591554c0a3aSHans de Goede void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq) 2592554c0a3aSHans de Goede { 2593554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2594554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2595554c0a3aSHans de Goede unsigned char *pframe; 2596554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2597554c0a3aSHans de Goede __le16 *fctrl; 2598554c0a3aSHans de Goede unsigned char *mac, *bssid; 2599554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2600554c0a3aSHans de Goede 2601554c0a3aSHans de Goede u8 *pwps_ie; 2602554c0a3aSHans de Goede uint wps_ielen; 2603554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2604554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2605554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2606554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 2607554c0a3aSHans de Goede unsigned int rate_len; 2608554c0a3aSHans de Goede 2609554c0a3aSHans de Goede /* DBG_871X("%s\n", __func__); */ 2610554c0a3aSHans de Goede 2611554c0a3aSHans de Goede if (da == NULL) 2612554c0a3aSHans de Goede return; 2613554c0a3aSHans de Goede 2614554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2615554c0a3aSHans de Goede if (pmgntframe == NULL) { 2616554c0a3aSHans de Goede DBG_871X("%s, alloc mgnt frame fail\n", __func__); 2617554c0a3aSHans de Goede return; 2618554c0a3aSHans de Goede } 2619554c0a3aSHans de Goede 2620554c0a3aSHans de Goede 2621554c0a3aSHans de Goede /* update attribute */ 2622554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2623554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2624554c0a3aSHans de Goede 2625554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2626554c0a3aSHans de Goede 2627554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2628554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2629554c0a3aSHans de Goede 2630554c0a3aSHans de Goede mac = myid(&(padapter->eeprompriv)); 2631554c0a3aSHans de Goede bssid = cur_network->MacAddress; 2632554c0a3aSHans de Goede 2633554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2634554c0a3aSHans de Goede *(fctrl) = 0; 2635554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 2636554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, mac, ETH_ALEN); 2637554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); 2638554c0a3aSHans de Goede 2639554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2640554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2641554c0a3aSHans de Goede SetFrameSubType(fctrl, WIFI_PROBERSP); 2642554c0a3aSHans de Goede 2643554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 2644554c0a3aSHans de Goede pattrib->pktlen = pattrib->hdrlen; 2645554c0a3aSHans de Goede pframe += pattrib->hdrlen; 2646554c0a3aSHans de Goede 2647554c0a3aSHans de Goede 2648554c0a3aSHans de Goede if (cur_network->IELength > MAX_IE_SZ) 2649554c0a3aSHans de Goede return; 2650554c0a3aSHans de Goede 2651554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { 2652554c0a3aSHans de Goede pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen); 2653554c0a3aSHans de Goede 2654554c0a3aSHans de Goede /* inerset & update wps_probe_resp_ie */ 265534557e23SIzabela Bakollari if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) { 2656554c0a3aSHans de Goede uint wps_offset, remainder_ielen; 2657554c0a3aSHans de Goede u8 *premainder_ie; 2658554c0a3aSHans de Goede 2659554c0a3aSHans de Goede wps_offset = (uint)(pwps_ie - cur_network->IEs); 2660554c0a3aSHans de Goede 2661554c0a3aSHans de Goede premainder_ie = pwps_ie + wps_ielen; 2662554c0a3aSHans de Goede 2663554c0a3aSHans de Goede remainder_ielen = cur_network->IELength - wps_offset - wps_ielen; 2664554c0a3aSHans de Goede 2665554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, wps_offset); 2666554c0a3aSHans de Goede pframe += wps_offset; 2667554c0a3aSHans de Goede pattrib->pktlen += wps_offset; 2668554c0a3aSHans de Goede 2669554c0a3aSHans de Goede wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */ 2670554c0a3aSHans de Goede if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) { 2671554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2); 2672554c0a3aSHans de Goede pframe += wps_ielen+2; 2673554c0a3aSHans de Goede pattrib->pktlen += wps_ielen+2; 2674554c0a3aSHans de Goede } 2675554c0a3aSHans de Goede 2676554c0a3aSHans de Goede if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) { 2677554c0a3aSHans de Goede memcpy(pframe, premainder_ie, remainder_ielen); 2678554c0a3aSHans de Goede pframe += remainder_ielen; 2679554c0a3aSHans de Goede pattrib->pktlen += remainder_ielen; 2680554c0a3aSHans de Goede } 2681554c0a3aSHans de Goede } else { 2682554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, cur_network->IELength); 2683554c0a3aSHans de Goede pframe += cur_network->IELength; 2684554c0a3aSHans de Goede pattrib->pktlen += cur_network->IELength; 2685554c0a3aSHans de Goede } 2686554c0a3aSHans de Goede 2687554c0a3aSHans de Goede /* retrieve SSID IE from cur_network->Ssid */ 2688554c0a3aSHans de Goede { 2689554c0a3aSHans de Goede u8 *ssid_ie; 2690554c0a3aSHans de Goede sint ssid_ielen; 2691554c0a3aSHans de Goede sint ssid_ielen_diff; 2692554c0a3aSHans de Goede u8 buf[MAX_IE_SZ]; 2693554c0a3aSHans de Goede u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr); 2694554c0a3aSHans de Goede 26953f15277bSRoss Schmidt ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, WLAN_EID_SSID, &ssid_ielen, 2696554c0a3aSHans de Goede (pframe-ies)-_FIXED_IE_LENGTH_); 2697554c0a3aSHans de Goede 2698554c0a3aSHans de Goede ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen; 2699554c0a3aSHans de Goede 2700554c0a3aSHans de Goede if (ssid_ie && cur_network->Ssid.SsidLength) { 2701554c0a3aSHans de Goede uint remainder_ielen; 2702554c0a3aSHans de Goede u8 *remainder_ie; 2703c926f022SSimran Singhal 2704554c0a3aSHans de Goede remainder_ie = ssid_ie+2; 2705554c0a3aSHans de Goede remainder_ielen = (pframe-remainder_ie); 2706554c0a3aSHans de Goede 2707554c0a3aSHans de Goede if (remainder_ielen > MAX_IE_SZ) { 2708554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter)); 2709554c0a3aSHans de Goede remainder_ielen = MAX_IE_SZ; 2710554c0a3aSHans de Goede } 2711554c0a3aSHans de Goede 2712554c0a3aSHans de Goede memcpy(buf, remainder_ie, remainder_ielen); 2713554c0a3aSHans de Goede memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen); 2714554c0a3aSHans de Goede *(ssid_ie+1) = cur_network->Ssid.SsidLength; 2715554c0a3aSHans de Goede memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength); 2716554c0a3aSHans de Goede 2717554c0a3aSHans de Goede pframe += ssid_ielen_diff; 2718554c0a3aSHans de Goede pattrib->pktlen += ssid_ielen_diff; 2719554c0a3aSHans de Goede } 2720554c0a3aSHans de Goede } 2721554c0a3aSHans de Goede } else { 2722554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 2723554c0a3aSHans de Goede pframe += 8; 2724554c0a3aSHans de Goede pattrib->pktlen += 8; 2725554c0a3aSHans de Goede 2726554c0a3aSHans de Goede /* beacon interval: 2 bytes */ 2727554c0a3aSHans de Goede 2728554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 2729554c0a3aSHans de Goede 2730554c0a3aSHans de Goede pframe += 2; 2731554c0a3aSHans de Goede pattrib->pktlen += 2; 2732554c0a3aSHans de Goede 2733554c0a3aSHans de Goede /* capability info: 2 bytes */ 2734554c0a3aSHans de Goede 2735554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); 2736554c0a3aSHans de Goede 2737554c0a3aSHans de Goede pframe += 2; 2738554c0a3aSHans de Goede pattrib->pktlen += 2; 2739554c0a3aSHans de Goede 2740554c0a3aSHans de Goede /* below for ad-hoc mode */ 2741554c0a3aSHans de Goede 2742554c0a3aSHans de Goede /* SSID */ 27433f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); 2744554c0a3aSHans de Goede 2745554c0a3aSHans de Goede /* supported rates... */ 2746554c0a3aSHans de Goede rate_len = rtw_get_rateset_len(cur_network->SupportedRates); 2747c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); 2748554c0a3aSHans de Goede 2749554c0a3aSHans de Goede /* DS parameter set */ 27508f6a9446SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen); 2751554c0a3aSHans de Goede 2752554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 2753554c0a3aSHans de Goede u8 erpinfo = 0; 2754554c0a3aSHans de Goede u32 ATIMWindow; 2755554c0a3aSHans de Goede /* IBSS Parameter Set... */ 2756554c0a3aSHans de Goede /* ATIMWindow = cur->Configuration.ATIMWindow; */ 2757554c0a3aSHans de Goede ATIMWindow = 0; 2758e6038a48SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); 2759554c0a3aSHans de Goede 2760554c0a3aSHans de Goede /* ERP IE */ 2761554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen); 2762554c0a3aSHans de Goede } 2763554c0a3aSHans de Goede 2764554c0a3aSHans de Goede 2765554c0a3aSHans de Goede /* EXTERNDED SUPPORTED RATE */ 2766554c0a3aSHans de Goede if (rate_len > 8) { 2767554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); 2768554c0a3aSHans de Goede } 2769554c0a3aSHans de Goede 2770554c0a3aSHans de Goede 2771554c0a3aSHans de Goede /* todo:HT for adhoc */ 2772554c0a3aSHans de Goede 2773554c0a3aSHans de Goede } 2774554c0a3aSHans de Goede 2775554c0a3aSHans de Goede #ifdef CONFIG_AUTO_AP_MODE 2776554c0a3aSHans de Goede { 2777554c0a3aSHans de Goede struct sta_info *psta; 2778554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 2779554c0a3aSHans de Goede 2780554c0a3aSHans de Goede DBG_871X("(%s)\n", __func__); 2781554c0a3aSHans de Goede 2782554c0a3aSHans de Goede /* check rc station */ 2783554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, da); 2784554c0a3aSHans de Goede if (psta && psta->isrc && psta->pid > 0) { 2785554c0a3aSHans de Goede u8 RC_OUI[4] = {0x00, 0xE0, 0x4C, 0x0A}; 2786554c0a3aSHans de Goede u8 RC_INFO[14] = {0}; 2787554c0a3aSHans de Goede /* EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2] */ 2788554c0a3aSHans de Goede u16 cu_ch = (u16)cur_network->Configuration.DSConfig; 2789554c0a3aSHans de Goede 2790bbda3ac4SRoss Schmidt DBG_871X("%s, reply rc(pid = 0x%x) device %pM in ch =%d\n", __func__, 2791554c0a3aSHans de Goede psta->pid, MAC_ARG(psta->hwaddr), cu_ch); 2792554c0a3aSHans de Goede 2793554c0a3aSHans de Goede /* append vendor specific ie */ 2794554c0a3aSHans de Goede memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI)); 2795554c0a3aSHans de Goede memcpy(&RC_INFO[4], mac, ETH_ALEN); 2796554c0a3aSHans de Goede memcpy(&RC_INFO[10], (u8 *)&psta->pid, 2); 2797554c0a3aSHans de Goede memcpy(&RC_INFO[12], (u8 *)&cu_ch, 2); 2798554c0a3aSHans de Goede 2799b05cc3a9SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen); 2800554c0a3aSHans de Goede } 2801554c0a3aSHans de Goede } 2802554c0a3aSHans de Goede #endif /* CONFIG_AUTO_AP_MODE */ 2803554c0a3aSHans de Goede 2804554c0a3aSHans de Goede 2805554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2806554c0a3aSHans de Goede 2807554c0a3aSHans de Goede 2808554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2809554c0a3aSHans de Goede 2810554c0a3aSHans de Goede return; 2811554c0a3aSHans de Goede 2812554c0a3aSHans de Goede } 2813554c0a3aSHans de Goede 281442b3b621SAishwarya Pant static int _issue_probereq(struct adapter *padapter, 281542b3b621SAishwarya Pant struct ndis_802_11_ssid *pssid, 281642b3b621SAishwarya Pant u8 *da, u8 ch, bool append_wps, bool wait_ack) 2817554c0a3aSHans de Goede { 2818554c0a3aSHans de Goede int ret = _FAIL; 2819554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2820554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2821554c0a3aSHans de Goede unsigned char *pframe; 2822554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2823554c0a3aSHans de Goede __le16 *fctrl; 2824554c0a3aSHans de Goede unsigned char *mac; 2825554c0a3aSHans de Goede unsigned char bssrate[NumRates]; 2826554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2827554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2828554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2829554c0a3aSHans de Goede int bssrate_len = 0; 2830554c0a3aSHans de Goede u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 2831554c0a3aSHans de Goede 2832554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+issue_probereq\n")); 2833554c0a3aSHans de Goede 2834554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 283541452327SVatsala Narang if (!pmgntframe) 2836554c0a3aSHans de Goede goto exit; 2837554c0a3aSHans de Goede 2838554c0a3aSHans de Goede /* update attribute */ 2839554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2840554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2841554c0a3aSHans de Goede 2842554c0a3aSHans de Goede 2843554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2844554c0a3aSHans de Goede 2845554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2846554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2847554c0a3aSHans de Goede 2848554c0a3aSHans de Goede mac = myid(&(padapter->eeprompriv)); 2849554c0a3aSHans de Goede 2850554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2851554c0a3aSHans de Goede *(fctrl) = 0; 2852554c0a3aSHans de Goede 2853554c0a3aSHans de Goede if (da) { 2854554c0a3aSHans de Goede /* unicast probe request frame */ 2855554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 2856554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, da, ETH_ALEN); 2857554c0a3aSHans de Goede } else { 2858554c0a3aSHans de Goede /* broadcast probe request frame */ 2859554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); 2860554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN); 2861554c0a3aSHans de Goede } 2862554c0a3aSHans de Goede 2863554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, mac, ETH_ALEN); 2864554c0a3aSHans de Goede 2865554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2866554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2867554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_PROBEREQ); 2868554c0a3aSHans de Goede 2869554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2870554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2871554c0a3aSHans de Goede 2872554c0a3aSHans de Goede if (pssid) 28733f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen)); 2874554c0a3aSHans de Goede else 28753f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, 0, NULL, &(pattrib->pktlen)); 2876554c0a3aSHans de Goede 2877554c0a3aSHans de Goede get_rate_set(padapter, bssrate, &bssrate_len); 2878554c0a3aSHans de Goede 2879554c0a3aSHans de Goede if (bssrate_len > 8) { 2880c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen)); 2881554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); 2882554c0a3aSHans de Goede } else { 2883c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen)); 2884554c0a3aSHans de Goede } 2885554c0a3aSHans de Goede 2886554c0a3aSHans de Goede if (ch) 28878f6a9446SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, &ch, &pattrib->pktlen); 2888554c0a3aSHans de Goede 2889554c0a3aSHans de Goede if (append_wps) { 2890554c0a3aSHans de Goede /* add wps_ie for wps2.0 */ 2891554c0a3aSHans de Goede if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) { 2892554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len); 2893554c0a3aSHans de Goede pframe += pmlmepriv->wps_probe_req_ie_len; 2894554c0a3aSHans de Goede pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; 2895554c0a3aSHans de Goede } 2896554c0a3aSHans de Goede } 2897554c0a3aSHans de Goede 2898554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2899554c0a3aSHans de Goede 2900554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("issuing probe_req, tx_len =%d\n", pattrib->last_txcmdsz)); 2901554c0a3aSHans de Goede 2902554c0a3aSHans de Goede if (wait_ack) { 2903554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 2904554c0a3aSHans de Goede } else { 2905554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2906554c0a3aSHans de Goede ret = _SUCCESS; 2907554c0a3aSHans de Goede } 2908554c0a3aSHans de Goede 2909554c0a3aSHans de Goede exit: 2910554c0a3aSHans de Goede return ret; 2911554c0a3aSHans de Goede } 2912554c0a3aSHans de Goede 2913554c0a3aSHans de Goede inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da) 2914554c0a3aSHans de Goede { 2915554c0a3aSHans de Goede _issue_probereq(padapter, pssid, da, 0, 1, false); 2916554c0a3aSHans de Goede } 2917554c0a3aSHans de Goede 2918554c0a3aSHans de Goede int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps, 2919554c0a3aSHans de Goede int try_cnt, int wait_ms) 2920554c0a3aSHans de Goede { 2921554c0a3aSHans de Goede int ret; 2922554c0a3aSHans de Goede int i = 0; 2923554c0a3aSHans de Goede 2924554c0a3aSHans de Goede do { 29259cdb1928SSaiyam Doshi ret = _issue_probereq(padapter, pssid, da, ch, append_wps, 29269cdb1928SSaiyam Doshi wait_ms > 0); 2927554c0a3aSHans de Goede 2928554c0a3aSHans de Goede i++; 2929554c0a3aSHans de Goede 2930554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 2931554c0a3aSHans de Goede break; 2932554c0a3aSHans de Goede 2933554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 2934554c0a3aSHans de Goede msleep(wait_ms); 2935554c0a3aSHans de Goede 2936554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 2937554c0a3aSHans de Goede 2938554c0a3aSHans de Goede if (ret != _FAIL) { 2939554c0a3aSHans de Goede ret = _SUCCESS; 2940554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 2941554c0a3aSHans de Goede goto exit; 2942554c0a3aSHans de Goede #endif 2943554c0a3aSHans de Goede } 2944554c0a3aSHans de Goede 2945554c0a3aSHans de Goede if (try_cnt && wait_ms) { 2946554c0a3aSHans de Goede if (da) 2947bbda3ac4SRoss Schmidt DBG_871X(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", 2948554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), 2949554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 2950554c0a3aSHans de Goede else 2951554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", 2952554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), 2953554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 2954554c0a3aSHans de Goede } 2955554c0a3aSHans de Goede exit: 2956554c0a3aSHans de Goede return ret; 2957554c0a3aSHans de Goede } 2958554c0a3aSHans de Goede 295968468503SAndreas Hellmich /* if psta == NULL, indicate we are station(client) now... */ 2960554c0a3aSHans de Goede void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status) 2961554c0a3aSHans de Goede { 2962554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2963554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2964554c0a3aSHans de Goede unsigned char *pframe; 2965554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2966554c0a3aSHans de Goede __le16 *fctrl; 2967554c0a3aSHans de Goede unsigned int val32; 2968554c0a3aSHans de Goede unsigned short val16; 2969554c0a3aSHans de Goede int use_shared_key = 0; 2970554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2971554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2972554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2973554c0a3aSHans de Goede __le16 le_tmp; 2974554c0a3aSHans de Goede 2975554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2976554c0a3aSHans de Goede if (pmgntframe == NULL) 2977554c0a3aSHans de Goede return; 2978554c0a3aSHans de Goede 2979554c0a3aSHans de Goede /* update attribute */ 2980554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2981554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2982554c0a3aSHans de Goede 2983554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2984554c0a3aSHans de Goede 2985554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2986554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2987554c0a3aSHans de Goede 2988554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2989554c0a3aSHans de Goede *(fctrl) = 0; 2990554c0a3aSHans de Goede 2991554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2992554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2993554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_AUTH); 2994554c0a3aSHans de Goede 2995554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2996554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2997554c0a3aSHans de Goede 2998554c0a3aSHans de Goede 2999554c0a3aSHans de Goede if (psta) { /* for AP mode */ 3000554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN); 3001554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3002554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN); 3003554c0a3aSHans de Goede 3004554c0a3aSHans de Goede /* setting auth algo number */ 3005554c0a3aSHans de Goede val16 = (u16)psta->authalg; 3006554c0a3aSHans de Goede 30076d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 3008554c0a3aSHans de Goede val16 = 0; 3009554c0a3aSHans de Goede 3010554c0a3aSHans de Goede if (val16) 3011554c0a3aSHans de Goede use_shared_key = 1; 3012554c0a3aSHans de Goede 3013554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 3014554c0a3aSHans de Goede 3015554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3016554c0a3aSHans de Goede 3017554c0a3aSHans de Goede /* setting auth seq number */ 3018554c0a3aSHans de Goede val16 = (u16)psta->auth_seq; 3019554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 3020554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3021554c0a3aSHans de Goede 3022554c0a3aSHans de Goede /* setting status code... */ 3023554c0a3aSHans de Goede val16 = status; 3024554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 3025554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3026554c0a3aSHans de Goede 3027554c0a3aSHans de Goede /* added challenging text... */ 3028554c0a3aSHans de Goede if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) 3029554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen)); 3030554c0a3aSHans de Goede 3031554c0a3aSHans de Goede } else { 3032554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); 3033554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); 3034554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); 3035554c0a3aSHans de Goede 3036554c0a3aSHans de Goede /* setting auth algo number */ 3037554c0a3aSHans de Goede val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */ 3038554c0a3aSHans de Goede if (val16) { 3039554c0a3aSHans de Goede use_shared_key = 1; 3040554c0a3aSHans de Goede } 3041554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 3042554c0a3aSHans de Goede /* DBG_871X("%s auth_algo = %s auth_seq =%d\n", __func__, (pmlmeinfo->auth_algo == 0)?"OPEN":"SHARED", pmlmeinfo->auth_seq); */ 3043554c0a3aSHans de Goede 3044554c0a3aSHans de Goede /* setting IV for auth seq #3 */ 3045554c0a3aSHans de Goede if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { 3046554c0a3aSHans de Goede __le32 le_tmp32; 3047554c0a3aSHans de Goede 3048554c0a3aSHans de Goede /* DBG_871X("==> iv(%d), key_index(%d)\n", pmlmeinfo->iv, pmlmeinfo->key_index); */ 3049554c0a3aSHans de Goede val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30)); 3050554c0a3aSHans de Goede le_tmp32 = cpu_to_le32(val32); 3051554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen)); 3052554c0a3aSHans de Goede 3053554c0a3aSHans de Goede pattrib->iv_len = 4; 3054554c0a3aSHans de Goede } 3055554c0a3aSHans de Goede 3056554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3057554c0a3aSHans de Goede 3058554c0a3aSHans de Goede /* setting auth seq number */ 3059554c0a3aSHans de Goede le_tmp = cpu_to_le16(pmlmeinfo->auth_seq); 3060554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3061554c0a3aSHans de Goede 3062554c0a3aSHans de Goede 3063554c0a3aSHans de Goede /* setting status code... */ 3064554c0a3aSHans de Goede le_tmp = cpu_to_le16(status); 3065554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3066554c0a3aSHans de Goede 3067554c0a3aSHans de Goede /* then checking to see if sending challenging text... */ 3068554c0a3aSHans de Goede if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { 3069554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen)); 3070554c0a3aSHans de Goede 3071554c0a3aSHans de Goede SetPrivacy(fctrl); 3072554c0a3aSHans de Goede 3073554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 3074554c0a3aSHans de Goede 3075554c0a3aSHans de Goede pattrib->encrypt = _WEP40_; 3076554c0a3aSHans de Goede 3077554c0a3aSHans de Goede pattrib->icv_len = 4; 3078554c0a3aSHans de Goede 3079554c0a3aSHans de Goede pattrib->pktlen += pattrib->icv_len; 3080554c0a3aSHans de Goede 3081554c0a3aSHans de Goede } 3082554c0a3aSHans de Goede 3083554c0a3aSHans de Goede } 3084554c0a3aSHans de Goede 3085554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3086554c0a3aSHans de Goede 3087554c0a3aSHans de Goede rtw_wep_encrypt(padapter, (u8 *)pmgntframe); 3088554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 3089554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3090554c0a3aSHans de Goede } 3091554c0a3aSHans de Goede 3092554c0a3aSHans de Goede 3093554c0a3aSHans de Goede void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type) 3094554c0a3aSHans de Goede { 3095554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3096554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3097554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3098554c0a3aSHans de Goede unsigned char *pbuf, *pframe; 3099554c0a3aSHans de Goede unsigned short val; 3100554c0a3aSHans de Goede __le16 *fctrl; 3101554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3102554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 3103554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 3104554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3105554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); 3106554c0a3aSHans de Goede u8 *ie = pnetwork->IEs; 3107554c0a3aSHans de Goede __le16 lestatus, le_tmp; 3108554c0a3aSHans de Goede 3109554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 3110554c0a3aSHans de Goede 3111554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3112554c0a3aSHans de Goede if (pmgntframe == NULL) 3113554c0a3aSHans de Goede return; 3114554c0a3aSHans de Goede 3115554c0a3aSHans de Goede /* update attribute */ 3116554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3117554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3118554c0a3aSHans de Goede 3119554c0a3aSHans de Goede 3120554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3121554c0a3aSHans de Goede 3122554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3123554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3124554c0a3aSHans de Goede 3125554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3126554c0a3aSHans de Goede *(fctrl) = 0; 3127554c0a3aSHans de Goede 3128554c0a3aSHans de Goede memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN); 3129554c0a3aSHans de Goede memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN); 3130554c0a3aSHans de Goede memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3131554c0a3aSHans de Goede 3132554c0a3aSHans de Goede 3133554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3134554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3135554c0a3aSHans de Goede if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP)) 3136554c0a3aSHans de Goede SetFrameSubType(pwlanhdr, pkt_type); 3137554c0a3aSHans de Goede else 3138554c0a3aSHans de Goede return; 3139554c0a3aSHans de Goede 3140554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 3141554c0a3aSHans de Goede pattrib->pktlen += pattrib->hdrlen; 3142554c0a3aSHans de Goede pframe += pattrib->hdrlen; 3143554c0a3aSHans de Goede 3144554c0a3aSHans de Goede /* capability */ 3145554c0a3aSHans de Goede val = *(unsigned short *)rtw_get_capability_from_ie(ie); 3146554c0a3aSHans de Goede 3147554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &(pattrib->pktlen)); 3148554c0a3aSHans de Goede 3149554c0a3aSHans de Goede lestatus = cpu_to_le16(status); 3150554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &(pattrib->pktlen)); 3151554c0a3aSHans de Goede 3152554c0a3aSHans de Goede le_tmp = cpu_to_le16(pstat->aid | BIT(14) | BIT(15)); 3153554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3154554c0a3aSHans de Goede 3155554c0a3aSHans de Goede if (pstat->bssratelen <= 8) { 3156c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen)); 3157554c0a3aSHans de Goede } else { 3158c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, pstat->bssrateset, &(pattrib->pktlen)); 3159554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen)); 3160554c0a3aSHans de Goede } 3161554c0a3aSHans de Goede 3162554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) { 3163554c0a3aSHans de Goede uint ie_len = 0; 3164554c0a3aSHans de Goede 3165554c0a3aSHans de Goede /* FILL HT CAP INFO IE */ 3166554c0a3aSHans de Goede /* p = hostapd_eid_ht_capabilities_info(hapd, p); */ 3167fc6a6528SRoss Schmidt pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); 3168554c0a3aSHans de Goede if (pbuf && ie_len > 0) { 3169554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 3170554c0a3aSHans de Goede pframe += (ie_len+2); 3171554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 3172554c0a3aSHans de Goede } 3173554c0a3aSHans de Goede 3174554c0a3aSHans de Goede /* FILL HT ADD INFO IE */ 3175554c0a3aSHans de Goede /* p = hostapd_eid_ht_operation(hapd, p); */ 3176332ec9dbSRoss Schmidt pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); 3177554c0a3aSHans de Goede if (pbuf && ie_len > 0) { 3178554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 3179554c0a3aSHans de Goede pframe += (ie_len+2); 3180554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 3181554c0a3aSHans de Goede } 3182554c0a3aSHans de Goede 3183554c0a3aSHans de Goede } 3184554c0a3aSHans de Goede 3185554c0a3aSHans de Goede /* FILL WMM IE */ 3186554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) { 3187554c0a3aSHans de Goede uint ie_len = 0; 3188554c0a3aSHans de Goede unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; 3189554c0a3aSHans de Goede 3190554c0a3aSHans de Goede for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) { 3191b05cc3a9SRoss Schmidt pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); 3192554c0a3aSHans de Goede if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) { 3193554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 3194554c0a3aSHans de Goede pframe += (ie_len+2); 3195554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 3196554c0a3aSHans de Goede 3197554c0a3aSHans de Goede break; 3198554c0a3aSHans de Goede } 3199554c0a3aSHans de Goede 3200554c0a3aSHans de Goede if ((pbuf == NULL) || (ie_len == 0)) { 3201554c0a3aSHans de Goede break; 3202554c0a3aSHans de Goede } 3203554c0a3aSHans de Goede } 3204554c0a3aSHans de Goede 3205554c0a3aSHans de Goede } 3206554c0a3aSHans de Goede 3207554c0a3aSHans de Goede if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) { 3208b05cc3a9SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen)); 3209554c0a3aSHans de Goede } 3210554c0a3aSHans de Goede 3211554c0a3aSHans de Goede /* add WPS IE ie for wps 2.0 */ 3212554c0a3aSHans de Goede if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) { 3213554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len); 3214554c0a3aSHans de Goede 3215554c0a3aSHans de Goede pframe += pmlmepriv->wps_assoc_resp_ie_len; 3216554c0a3aSHans de Goede pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len; 3217554c0a3aSHans de Goede } 3218554c0a3aSHans de Goede 3219554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3220554c0a3aSHans de Goede 3221554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3222554c0a3aSHans de Goede } 3223554c0a3aSHans de Goede 3224554c0a3aSHans de Goede void issue_assocreq(struct adapter *padapter) 3225554c0a3aSHans de Goede { 3226554c0a3aSHans de Goede int ret = _FAIL; 3227554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3228554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3229554c0a3aSHans de Goede unsigned char *pframe; 3230554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3231554c0a3aSHans de Goede __le16 *fctrl; 3232554c0a3aSHans de Goede __le16 val16; 3233554c0a3aSHans de Goede unsigned int i, j, index = 0; 3234554c0a3aSHans de Goede unsigned char bssrate[NumRates], sta_bssrate[NumRates]; 3235554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 3236554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3237554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 3238554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3239554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3240554c0a3aSHans de Goede int bssrate_len = 0, sta_bssrate_len = 0; 3241554c0a3aSHans de Goede u8 vs_ie_length = 0; 3242554c0a3aSHans de Goede 3243554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3244554c0a3aSHans de Goede if (pmgntframe == NULL) 3245554c0a3aSHans de Goede goto exit; 3246554c0a3aSHans de Goede 3247554c0a3aSHans de Goede /* update attribute */ 3248554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3249554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3250554c0a3aSHans de Goede 3251554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3252554c0a3aSHans de Goede 3253554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3254554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3255554c0a3aSHans de Goede 3256554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3257554c0a3aSHans de Goede *(fctrl) = 0; 3258554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3259554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3260554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3261554c0a3aSHans de Goede 3262554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3263554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3264554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ASSOCREQ); 3265554c0a3aSHans de Goede 3266554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3267554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3268554c0a3aSHans de Goede 3269554c0a3aSHans de Goede /* caps */ 3270554c0a3aSHans de Goede memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2); 3271554c0a3aSHans de Goede 3272554c0a3aSHans de Goede pframe += 2; 3273554c0a3aSHans de Goede pattrib->pktlen += 2; 3274554c0a3aSHans de Goede 3275554c0a3aSHans de Goede /* listen interval */ 3276554c0a3aSHans de Goede /* todo: listen interval for power saving */ 3277554c0a3aSHans de Goede val16 = cpu_to_le16(3); 3278554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)&val16, 2); 3279554c0a3aSHans de Goede pframe += 2; 3280554c0a3aSHans de Goede pattrib->pktlen += 2; 3281554c0a3aSHans de Goede 3282554c0a3aSHans de Goede /* SSID */ 32833f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen)); 3284554c0a3aSHans de Goede 3285554c0a3aSHans de Goede /* supported rate & extended supported rate */ 3286554c0a3aSHans de Goede 3287554c0a3aSHans de Goede /* Check if the AP's supported rates are also supported by STA. */ 3288554c0a3aSHans de Goede get_rate_set(padapter, sta_bssrate, &sta_bssrate_len); 3289554c0a3aSHans de Goede /* DBG_871X("sta_bssrate_len =%d\n", sta_bssrate_len); */ 3290554c0a3aSHans de Goede 3291554c0a3aSHans de Goede if (pmlmeext->cur_channel == 14) /* for JAPAN, channel 14 can only uses B Mode(CCK) */ 3292554c0a3aSHans de Goede sta_bssrate_len = 4; 3293554c0a3aSHans de Goede 3294554c0a3aSHans de Goede 3295554c0a3aSHans de Goede /* for (i = 0; i < sta_bssrate_len; i++) { */ 3296554c0a3aSHans de Goede /* DBG_871X("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]); */ 3297554c0a3aSHans de Goede /* */ 3298554c0a3aSHans de Goede 3299554c0a3aSHans de Goede for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { 3300554c0a3aSHans de Goede if (pmlmeinfo->network.SupportedRates[i] == 0) 3301554c0a3aSHans de Goede break; 3302554c0a3aSHans de Goede DBG_871X("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]); 3303554c0a3aSHans de Goede } 3304554c0a3aSHans de Goede 3305554c0a3aSHans de Goede 3306554c0a3aSHans de Goede for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { 3307554c0a3aSHans de Goede if (pmlmeinfo->network.SupportedRates[i] == 0) 3308554c0a3aSHans de Goede break; 3309554c0a3aSHans de Goede 3310554c0a3aSHans de Goede 3311554c0a3aSHans de Goede /* Check if the AP's supported rates are also supported by STA. */ 3312554c0a3aSHans de Goede for (j = 0; j < sta_bssrate_len; j++) { 3313554c0a3aSHans de Goede /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */ 3314554c0a3aSHans de Goede if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK) 3315554c0a3aSHans de Goede == (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) { 3316554c0a3aSHans de Goede /* DBG_871X("match i = %d, j =%d\n", i, j); */ 3317554c0a3aSHans de Goede break; 3318554c0a3aSHans de Goede } else { 3319554c0a3aSHans de Goede /* DBG_871X("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)); */ 3320554c0a3aSHans de Goede } 3321554c0a3aSHans de Goede } 3322554c0a3aSHans de Goede 3323554c0a3aSHans de Goede if (j == sta_bssrate_len) { 3324554c0a3aSHans de Goede /* the rate is not supported by STA */ 3325554c0a3aSHans de Goede DBG_871X("%s(): the rate[%d]=%02X is not supported by STA!\n", __func__, i, pmlmeinfo->network.SupportedRates[i]); 3326554c0a3aSHans de Goede } else { 3327554c0a3aSHans de Goede /* the rate is supported by STA */ 3328554c0a3aSHans de Goede bssrate[index++] = pmlmeinfo->network.SupportedRates[i]; 3329554c0a3aSHans de Goede } 3330554c0a3aSHans de Goede } 3331554c0a3aSHans de Goede 3332554c0a3aSHans de Goede bssrate_len = index; 3333554c0a3aSHans de Goede DBG_871X("bssrate_len = %d\n", bssrate_len); 3334554c0a3aSHans de Goede 3335554c0a3aSHans de Goede if (bssrate_len == 0) { 3336554c0a3aSHans de Goede rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); 3337554c0a3aSHans de Goede rtw_free_xmitframe(pxmitpriv, pmgntframe); 3338554c0a3aSHans de Goede goto exit; /* don't connect to AP if no joint supported rate */ 3339554c0a3aSHans de Goede } 3340554c0a3aSHans de Goede 3341554c0a3aSHans de Goede 3342554c0a3aSHans de Goede if (bssrate_len > 8) { 3343c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen)); 3344554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); 3345554c0a3aSHans de Goede } else 3346c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen)); 3347554c0a3aSHans de Goede 3348554c0a3aSHans de Goede /* vendor specific IE, such as WPA, WMM, WPS */ 3349554c0a3aSHans de Goede for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) { 3350554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i); 3351554c0a3aSHans de Goede 3352554c0a3aSHans de Goede switch (pIE->ElementID) { 3353b05cc3a9SRoss Schmidt case WLAN_EID_VENDOR_SPECIFIC: 3354554c0a3aSHans de Goede if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) || 3355554c0a3aSHans de Goede (!memcmp(pIE->data, WMM_OUI, 4)) || 3356554c0a3aSHans de Goede (!memcmp(pIE->data, WPS_OUI, 4))) { 3357554c0a3aSHans de Goede vs_ie_length = pIE->Length; 3358554c0a3aSHans de Goede if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) { 33594d17363dSAndreas Hellmich /* Commented by Kurt 20110629 33604d17363dSAndreas Hellmich * In some older APs, WPS handshake 33614d17363dSAndreas Hellmich * would be fail if we append vendor 33624d17363dSAndreas Hellmich * extensions information to AP 33634d17363dSAndreas Hellmich */ 3364554c0a3aSHans de Goede 3365554c0a3aSHans de Goede vs_ie_length = 14; 3366554c0a3aSHans de Goede } 3367554c0a3aSHans de Goede 3368b05cc3a9SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, vs_ie_length, pIE->data, &(pattrib->pktlen)); 3369554c0a3aSHans de Goede } 3370554c0a3aSHans de Goede break; 3371554c0a3aSHans de Goede 33723359e292SRoss Schmidt case WLAN_EID_RSN: 33733359e292SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_RSN, pIE->Length, pIE->data, &(pattrib->pktlen)); 3374554c0a3aSHans de Goede break; 3375fc6a6528SRoss Schmidt case WLAN_EID_HT_CAPABILITY: 33760ad02fa8SGeorgiana Chelu if (padapter->mlmepriv.htpriv.ht_option) { 3377554c0a3aSHans de Goede if (!(is_ap_in_tkip(padapter))) { 3378554c0a3aSHans de Goede memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element)); 3379fc6a6528SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_HT_CAPABILITY, pIE->Length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen)); 3380554c0a3aSHans de Goede } 3381554c0a3aSHans de Goede } 3382554c0a3aSHans de Goede break; 3383554c0a3aSHans de Goede 3384554c0a3aSHans de Goede case EID_EXTCapability: 33850ad02fa8SGeorgiana Chelu if (padapter->mlmepriv.htpriv.ht_option) 3386554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen)); 3387554c0a3aSHans de Goede break; 3388554c0a3aSHans de Goede default: 3389554c0a3aSHans de Goede break; 3390554c0a3aSHans de Goede } 3391554c0a3aSHans de Goede 3392554c0a3aSHans de Goede i += (pIE->Length + 2); 3393554c0a3aSHans de Goede } 3394554c0a3aSHans de Goede 3395554c0a3aSHans de Goede if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) 3396b05cc3a9SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen)); 3397554c0a3aSHans de Goede 3398554c0a3aSHans de Goede 3399554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3400554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3401554c0a3aSHans de Goede 3402554c0a3aSHans de Goede ret = _SUCCESS; 3403554c0a3aSHans de Goede 3404554c0a3aSHans de Goede exit: 3405554c0a3aSHans de Goede if (ret == _SUCCESS) 3406554c0a3aSHans de Goede rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen); 3407554c0a3aSHans de Goede else 3408554c0a3aSHans de Goede rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len); 3409554c0a3aSHans de Goede } 3410554c0a3aSHans de Goede 341168468503SAndreas Hellmich /* when wait_ack is true, this function should be called at process context */ 341242b3b621SAishwarya Pant static int _issue_nulldata(struct adapter *padapter, unsigned char *da, 341342b3b621SAishwarya Pant unsigned int power_mode, bool wait_ack) 3414554c0a3aSHans de Goede { 3415554c0a3aSHans de Goede int ret = _FAIL; 3416554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3417554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3418554c0a3aSHans de Goede unsigned char *pframe; 3419554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3420554c0a3aSHans de Goede __le16 *fctrl; 3421554c0a3aSHans de Goede struct xmit_priv *pxmitpriv; 3422554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 3423554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo; 3424554c0a3aSHans de Goede 3425554c0a3aSHans de Goede /* DBG_871X("%s:%d\n", __func__, power_mode); */ 3426554c0a3aSHans de Goede 3427554c0a3aSHans de Goede if (!padapter) 3428554c0a3aSHans de Goede goto exit; 3429554c0a3aSHans de Goede 3430554c0a3aSHans de Goede pxmitpriv = &(padapter->xmitpriv); 3431554c0a3aSHans de Goede pmlmeext = &(padapter->mlmeextpriv); 3432554c0a3aSHans de Goede pmlmeinfo = &(pmlmeext->mlmext_info); 3433554c0a3aSHans de Goede 3434554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3435554c0a3aSHans de Goede if (pmgntframe == NULL) 3436554c0a3aSHans de Goede goto exit; 3437554c0a3aSHans de Goede 3438554c0a3aSHans de Goede /* update attribute */ 3439554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3440554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3441554c0a3aSHans de Goede pattrib->retry_ctrl = false; 3442554c0a3aSHans de Goede 3443554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3444554c0a3aSHans de Goede 3445554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3446554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3447554c0a3aSHans de Goede 3448554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3449554c0a3aSHans de Goede *(fctrl) = 0; 3450554c0a3aSHans de Goede 3451554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) 3452554c0a3aSHans de Goede SetFrDs(fctrl); 3453554c0a3aSHans de Goede else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) 3454554c0a3aSHans de Goede SetToDs(fctrl); 3455554c0a3aSHans de Goede 3456554c0a3aSHans de Goede if (power_mode) 3457554c0a3aSHans de Goede SetPwrMgt(fctrl); 3458554c0a3aSHans de Goede 3459554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3460554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3461554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3462554c0a3aSHans de Goede 3463554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3464554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3465554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_DATA_NULL); 3466554c0a3aSHans de Goede 3467554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3468554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3469554c0a3aSHans de Goede 3470554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3471554c0a3aSHans de Goede 3472554c0a3aSHans de Goede if (wait_ack) { 3473554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3474554c0a3aSHans de Goede } else { 3475554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3476554c0a3aSHans de Goede ret = _SUCCESS; 3477554c0a3aSHans de Goede } 3478554c0a3aSHans de Goede 3479554c0a3aSHans de Goede exit: 3480554c0a3aSHans de Goede return ret; 3481554c0a3aSHans de Goede } 3482554c0a3aSHans de Goede 3483554c0a3aSHans de Goede /* 3484554c0a3aSHans de Goede * [IMPORTANT] Don't call this function in interrupt context 3485554c0a3aSHans de Goede * 348668468503SAndreas Hellmich * When wait_ms > 0, this function should be called at process context 3487554c0a3aSHans de Goede * da == NULL for station mode 3488554c0a3aSHans de Goede */ 3489554c0a3aSHans de Goede int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms) 3490554c0a3aSHans de Goede { 3491554c0a3aSHans de Goede int ret; 3492554c0a3aSHans de Goede int i = 0; 3493554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3494554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3495554c0a3aSHans de Goede struct sta_info *psta; 3496554c0a3aSHans de Goede 3497554c0a3aSHans de Goede 349868468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 34995947e900SNishka Dasgupta if (!da) 3500554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3501554c0a3aSHans de Goede 3502554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, da); 3503554c0a3aSHans de Goede if (psta) { 3504554c0a3aSHans de Goede if (power_mode) 3505554c0a3aSHans de Goede rtw_hal_macid_sleep(padapter, psta->mac_id); 3506554c0a3aSHans de Goede else 3507554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 3508554c0a3aSHans de Goede } else { 3509bbda3ac4SRoss Schmidt DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for %pM, skip macid %s!!\n", 3510554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup"); 3511554c0a3aSHans de Goede rtw_warn_on(1); 3512554c0a3aSHans de Goede } 3513554c0a3aSHans de Goede 3514554c0a3aSHans de Goede do { 35159cdb1928SSaiyam Doshi ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0); 3516554c0a3aSHans de Goede 3517554c0a3aSHans de Goede i++; 3518554c0a3aSHans de Goede 3519554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3520554c0a3aSHans de Goede break; 3521554c0a3aSHans de Goede 3522554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 3523554c0a3aSHans de Goede msleep(wait_ms); 3524554c0a3aSHans de Goede 3525554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3526554c0a3aSHans de Goede 3527554c0a3aSHans de Goede if (ret != _FAIL) { 3528554c0a3aSHans de Goede ret = _SUCCESS; 3529554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3530554c0a3aSHans de Goede goto exit; 3531554c0a3aSHans de Goede #endif 3532554c0a3aSHans de Goede } 3533554c0a3aSHans de Goede 3534554c0a3aSHans de Goede if (try_cnt && wait_ms) { 3535554c0a3aSHans de Goede if (da) 3536bbda3ac4SRoss Schmidt DBG_871X(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", 3537554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), 3538554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3539554c0a3aSHans de Goede else 3540554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", 3541554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), 3542554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3543554c0a3aSHans de Goede } 3544554c0a3aSHans de Goede exit: 3545554c0a3aSHans de Goede return ret; 3546554c0a3aSHans de Goede } 3547554c0a3aSHans de Goede 3548554c0a3aSHans de Goede /* 3549554c0a3aSHans de Goede * [IMPORTANT] This function run in interrupt context 3550554c0a3aSHans de Goede * 3551554c0a3aSHans de Goede * The null data packet would be sent without power bit, 3552554c0a3aSHans de Goede * and not guarantee success. 3553554c0a3aSHans de Goede */ 3554554c0a3aSHans de Goede s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da) 3555554c0a3aSHans de Goede { 3556554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 3557554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo; 3558554c0a3aSHans de Goede 3559554c0a3aSHans de Goede 3560554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 3561554c0a3aSHans de Goede pmlmeinfo = &pmlmeext->mlmext_info; 3562554c0a3aSHans de Goede 356368468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 35645947e900SNishka Dasgupta if (!da) 3565554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3566554c0a3aSHans de Goede 356763ff599aSNishka Dasgupta return _issue_nulldata(padapter, da, 0, false); 3568554c0a3aSHans de Goede } 3569554c0a3aSHans de Goede 357068468503SAndreas Hellmich /* when wait_ack is true, this function should be called at process context */ 357142b3b621SAishwarya Pant static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, 357242b3b621SAishwarya Pant u16 tid, bool wait_ack) 3573554c0a3aSHans de Goede { 3574554c0a3aSHans de Goede int ret = _FAIL; 3575554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3576554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3577554c0a3aSHans de Goede unsigned char *pframe; 3578554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3579554c0a3aSHans de Goede __le16 *fctrl; 3580554c0a3aSHans de Goede u16 *qc; 3581554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3582554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3583554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3584554c0a3aSHans de Goede 3585554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 3586554c0a3aSHans de Goede 3587554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3588554c0a3aSHans de Goede if (pmgntframe == NULL) 3589554c0a3aSHans de Goede goto exit; 3590554c0a3aSHans de Goede 3591554c0a3aSHans de Goede /* update attribute */ 3592554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3593554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3594554c0a3aSHans de Goede 3595554c0a3aSHans de Goede pattrib->hdrlen += 2; 3596554c0a3aSHans de Goede pattrib->qos_en = true; 3597554c0a3aSHans de Goede pattrib->eosp = 1; 3598554c0a3aSHans de Goede pattrib->ack_policy = 0; 3599554c0a3aSHans de Goede pattrib->mdata = 0; 3600554c0a3aSHans de Goede 3601554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3602554c0a3aSHans de Goede 3603554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3604554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3605554c0a3aSHans de Goede 3606554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3607554c0a3aSHans de Goede *(fctrl) = 0; 3608554c0a3aSHans de Goede 3609554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) 3610554c0a3aSHans de Goede SetFrDs(fctrl); 3611554c0a3aSHans de Goede else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) 3612554c0a3aSHans de Goede SetToDs(fctrl); 3613554c0a3aSHans de Goede 3614554c0a3aSHans de Goede if (pattrib->mdata) 3615554c0a3aSHans de Goede SetMData(fctrl); 3616554c0a3aSHans de Goede 3617554c0a3aSHans de Goede qc = (unsigned short *)(pframe + pattrib->hdrlen - 2); 3618554c0a3aSHans de Goede 3619554c0a3aSHans de Goede SetPriority(qc, tid); 3620554c0a3aSHans de Goede 3621554c0a3aSHans de Goede SetEOSP(qc, pattrib->eosp); 3622554c0a3aSHans de Goede 3623554c0a3aSHans de Goede SetAckpolicy(qc, pattrib->ack_policy); 3624554c0a3aSHans de Goede 3625554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3626554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3627554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3628554c0a3aSHans de Goede 3629554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3630554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3631554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); 3632554c0a3aSHans de Goede 3633554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_qos_hdr); 3634554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); 3635554c0a3aSHans de Goede 3636554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3637554c0a3aSHans de Goede 3638554c0a3aSHans de Goede if (wait_ack) { 3639554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3640554c0a3aSHans de Goede } else { 3641554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3642554c0a3aSHans de Goede ret = _SUCCESS; 3643554c0a3aSHans de Goede } 3644554c0a3aSHans de Goede 3645554c0a3aSHans de Goede exit: 3646554c0a3aSHans de Goede return ret; 3647554c0a3aSHans de Goede } 3648554c0a3aSHans de Goede 364968468503SAndreas Hellmich /* when wait_ms >0 , this function should be called at process context */ 3650554c0a3aSHans de Goede /* da == NULL for station mode */ 3651554c0a3aSHans de Goede int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms) 3652554c0a3aSHans de Goede { 3653554c0a3aSHans de Goede int ret; 3654554c0a3aSHans de Goede int i = 0; 3655554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3656554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3657554c0a3aSHans de Goede 365868468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 36595947e900SNishka Dasgupta if (!da) 3660554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3661554c0a3aSHans de Goede 3662554c0a3aSHans de Goede do { 36639cdb1928SSaiyam Doshi ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0); 3664554c0a3aSHans de Goede 3665554c0a3aSHans de Goede i++; 3666554c0a3aSHans de Goede 3667554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3668554c0a3aSHans de Goede break; 3669554c0a3aSHans de Goede 3670554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 3671554c0a3aSHans de Goede msleep(wait_ms); 3672554c0a3aSHans de Goede 3673554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3674554c0a3aSHans de Goede 3675554c0a3aSHans de Goede if (ret != _FAIL) { 3676554c0a3aSHans de Goede ret = _SUCCESS; 3677554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3678554c0a3aSHans de Goede goto exit; 3679554c0a3aSHans de Goede #endif 3680554c0a3aSHans de Goede } 3681554c0a3aSHans de Goede 3682554c0a3aSHans de Goede if (try_cnt && wait_ms) { 3683554c0a3aSHans de Goede if (da) 3684bbda3ac4SRoss Schmidt DBG_871X(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", 3685554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), 3686554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3687554c0a3aSHans de Goede else 3688554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", 3689554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), 3690554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3691554c0a3aSHans de Goede } 3692554c0a3aSHans de Goede exit: 3693554c0a3aSHans de Goede return ret; 3694554c0a3aSHans de Goede } 3695554c0a3aSHans de Goede 369642b3b621SAishwarya Pant static int _issue_deauth(struct adapter *padapter, unsigned char *da, 369742b3b621SAishwarya Pant unsigned short reason, bool wait_ack) 3698554c0a3aSHans de Goede { 3699554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3700554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3701554c0a3aSHans de Goede unsigned char *pframe; 3702554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3703554c0a3aSHans de Goede __le16 *fctrl; 3704554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3705554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3706554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3707554c0a3aSHans de Goede int ret = _FAIL; 3708554c0a3aSHans de Goede __le16 le_tmp; 3709554c0a3aSHans de Goede 3710bbda3ac4SRoss Schmidt /* DBG_871X("%s to %pM\n", __func__, MAC_ARG(da)); */ 3711554c0a3aSHans de Goede 3712554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3713554c0a3aSHans de Goede if (pmgntframe == NULL) { 3714554c0a3aSHans de Goede goto exit; 3715554c0a3aSHans de Goede } 3716554c0a3aSHans de Goede 3717554c0a3aSHans de Goede /* update attribute */ 3718554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3719554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3720554c0a3aSHans de Goede pattrib->retry_ctrl = false; 3721554c0a3aSHans de Goede 3722554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3723554c0a3aSHans de Goede 3724554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3725554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3726554c0a3aSHans de Goede 3727554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3728554c0a3aSHans de Goede *(fctrl) = 0; 3729554c0a3aSHans de Goede 3730554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3731554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3732554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3733554c0a3aSHans de Goede 3734554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3735554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3736554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_DEAUTH); 3737554c0a3aSHans de Goede 3738554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3739554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3740554c0a3aSHans de Goede 3741554c0a3aSHans de Goede le_tmp = cpu_to_le16(reason); 3742554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3743554c0a3aSHans de Goede 3744554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3745554c0a3aSHans de Goede 3746554c0a3aSHans de Goede 3747554c0a3aSHans de Goede if (wait_ack) { 3748554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3749554c0a3aSHans de Goede } else { 3750554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3751554c0a3aSHans de Goede ret = _SUCCESS; 3752554c0a3aSHans de Goede } 3753554c0a3aSHans de Goede 3754554c0a3aSHans de Goede exit: 3755554c0a3aSHans de Goede return ret; 3756554c0a3aSHans de Goede } 3757554c0a3aSHans de Goede 3758554c0a3aSHans de Goede int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason) 3759554c0a3aSHans de Goede { 3760bbda3ac4SRoss Schmidt DBG_871X("%s to %pM\n", __func__, MAC_ARG(da)); 3761554c0a3aSHans de Goede return _issue_deauth(padapter, da, reason, false); 3762554c0a3aSHans de Goede } 3763554c0a3aSHans de Goede 3764554c0a3aSHans de Goede int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt, 3765554c0a3aSHans de Goede int wait_ms) 3766554c0a3aSHans de Goede { 3767554c0a3aSHans de Goede int ret; 3768554c0a3aSHans de Goede int i = 0; 3769554c0a3aSHans de Goede 3770554c0a3aSHans de Goede do { 37719cdb1928SSaiyam Doshi ret = _issue_deauth(padapter, da, reason, wait_ms > 0); 3772554c0a3aSHans de Goede 3773554c0a3aSHans de Goede i++; 3774554c0a3aSHans de Goede 3775554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3776554c0a3aSHans de Goede break; 3777554c0a3aSHans de Goede 3778554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 37791c8cb89eSJia-Ju Bai mdelay(wait_ms); 3780554c0a3aSHans de Goede 3781554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3782554c0a3aSHans de Goede 3783554c0a3aSHans de Goede if (ret != _FAIL) { 3784554c0a3aSHans de Goede ret = _SUCCESS; 3785554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3786554c0a3aSHans de Goede goto exit; 3787554c0a3aSHans de Goede #endif 3788554c0a3aSHans de Goede } 3789554c0a3aSHans de Goede 3790554c0a3aSHans de Goede if (try_cnt && wait_ms) { 3791554c0a3aSHans de Goede if (da) 3792bbda3ac4SRoss Schmidt DBG_871X(FUNC_ADPT_FMT" to %pM, ch:%u%s, %d/%d in %u ms\n", 3793554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter), 3794554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3795554c0a3aSHans de Goede else 3796554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n", 3797554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter), 3798554c0a3aSHans de Goede ret == _SUCCESS?", acked":"", i, try_cnt, (i + 1) * wait_ms); 3799554c0a3aSHans de Goede } 3800554c0a3aSHans de Goede exit: 3801554c0a3aSHans de Goede return ret; 3802554c0a3aSHans de Goede } 3803554c0a3aSHans de Goede 3804554c0a3aSHans de Goede void issue_action_SA_Query(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid) 3805554c0a3aSHans de Goede { 3806554c0a3aSHans de Goede u8 category = RTW_WLAN_CATEGORY_SA_QUERY; 3807554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3808554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3809554c0a3aSHans de Goede u8 *pframe; 3810554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3811554c0a3aSHans de Goede __le16 *fctrl; 3812554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3813554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3814554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3815554c0a3aSHans de Goede __le16 le_tmp; 3816554c0a3aSHans de Goede 3817554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 3818554c0a3aSHans de Goede 3819554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3820554c0a3aSHans de Goede if (pmgntframe == NULL) { 3821554c0a3aSHans de Goede DBG_871X("%s: alloc_mgtxmitframe fail\n", __func__); 3822554c0a3aSHans de Goede return; 3823554c0a3aSHans de Goede } 3824554c0a3aSHans de Goede 3825554c0a3aSHans de Goede /* update attribute */ 3826554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3827554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3828554c0a3aSHans de Goede 3829554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3830554c0a3aSHans de Goede 3831554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3832554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3833554c0a3aSHans de Goede 3834554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3835554c0a3aSHans de Goede *(fctrl) = 0; 3836554c0a3aSHans de Goede 3837554c0a3aSHans de Goede if (raddr) 3838554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); 3839554c0a3aSHans de Goede else 3840554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3841554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3842554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3843554c0a3aSHans de Goede 3844554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3845554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3846554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 3847554c0a3aSHans de Goede 3848554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3849554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3850554c0a3aSHans de Goede 3851554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); 3852554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); 3853554c0a3aSHans de Goede 3854554c0a3aSHans de Goede switch (action) { 3855554c0a3aSHans de Goede case 0: /* SA Query req */ 3856554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen); 3857554c0a3aSHans de Goede pmlmeext->sa_query_seq++; 3858554c0a3aSHans de Goede /* send sa query request to AP, AP should reply sa query response in 1 second */ 3859554c0a3aSHans de Goede set_sa_query_timer(pmlmeext, 1000); 3860554c0a3aSHans de Goede break; 3861554c0a3aSHans de Goede 3862554c0a3aSHans de Goede case 1: /* SA Query rsp */ 3863554c0a3aSHans de Goede le_tmp = cpu_to_le16(tid); 3864554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen); 3865554c0a3aSHans de Goede break; 3866554c0a3aSHans de Goede default: 3867554c0a3aSHans de Goede break; 3868554c0a3aSHans de Goede } 3869554c0a3aSHans de Goede 3870554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3871554c0a3aSHans de Goede 3872554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3873554c0a3aSHans de Goede } 3874554c0a3aSHans de Goede 3875554c0a3aSHans de Goede void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status) 3876554c0a3aSHans de Goede { 3877554c0a3aSHans de Goede u8 category = RTW_WLAN_CATEGORY_BACK; 3878554c0a3aSHans de Goede u16 start_seq; 3879554c0a3aSHans de Goede u16 BA_para_set; 3880554c0a3aSHans de Goede u16 reason_code; 3881554c0a3aSHans de Goede u16 BA_timeout_value; 3882554c0a3aSHans de Goede u16 BA_starting_seqctrl = 0; 388398b32c71SRoss Schmidt enum ieee80211_max_ampdu_length_exp max_rx_ampdu_factor; 3884554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3885554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3886554c0a3aSHans de Goede u8 *pframe; 3887554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3888554c0a3aSHans de Goede __le16 *fctrl; 3889554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3890554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3891554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3892554c0a3aSHans de Goede struct sta_info *psta; 3893554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 3894554c0a3aSHans de Goede struct registry_priv *pregpriv = &padapter->registrypriv; 3895554c0a3aSHans de Goede __le16 le_tmp; 3896554c0a3aSHans de Goede 3897554c0a3aSHans de Goede DBG_871X("%s, category =%d, action =%d, status =%d\n", __func__, category, action, status); 3898554c0a3aSHans de Goede 3899554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 390041452327SVatsala Narang if (!pmgntframe) 3901554c0a3aSHans de Goede return; 3902554c0a3aSHans de Goede 3903554c0a3aSHans de Goede /* update attribute */ 3904554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3905554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3906554c0a3aSHans de Goede 3907554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3908554c0a3aSHans de Goede 3909554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3910554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3911554c0a3aSHans de Goede 3912554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3913554c0a3aSHans de Goede *(fctrl) = 0; 3914554c0a3aSHans de Goede 3915554c0a3aSHans de Goede /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */ 3916554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); 3917554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3918554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3919554c0a3aSHans de Goede 3920554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3921554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3922554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 3923554c0a3aSHans de Goede 3924554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3925554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3926554c0a3aSHans de Goede 3927554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); 3928554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); 3929554c0a3aSHans de Goede 3930554c0a3aSHans de Goede if (category == 3) { 3931554c0a3aSHans de Goede switch (action) { 3932554c0a3aSHans de Goede case 0: /* ADDBA req */ 3933554c0a3aSHans de Goede do { 3934554c0a3aSHans de Goede pmlmeinfo->dialogToken++; 3935554c0a3aSHans de Goede } while (pmlmeinfo->dialogToken == 0); 3936554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen)); 3937554c0a3aSHans de Goede 3938d312a47fSNishka Dasgupta if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter)) { 3939554c0a3aSHans de Goede /* A-MSDU NOT Supported */ 3940554c0a3aSHans de Goede BA_para_set = 0; 3941554c0a3aSHans de Goede /* immediate Block Ack */ 3942f36fa2d9SPayal Kshirsagar BA_para_set |= BIT(1) & IEEE80211_ADDBA_PARAM_POLICY_MASK; 3943554c0a3aSHans de Goede /* TID */ 3944554c0a3aSHans de Goede BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK; 3945554c0a3aSHans de Goede /* max buffer size is 8 MSDU */ 3946b3ae8af6SRoss Schmidt BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3947554c0a3aSHans de Goede } else { 3948554c0a3aSHans de Goede BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */ 3949554c0a3aSHans de Goede } 3950554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 3951554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3952554c0a3aSHans de Goede 3953554c0a3aSHans de Goede BA_timeout_value = 5000;/* 5ms */ 3954554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_timeout_value); 3955554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3956554c0a3aSHans de Goede 3957554c0a3aSHans de Goede /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */ 3958554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, raddr); 395934557e23SIzabela Bakollari if (psta) { 3960554c0a3aSHans de Goede start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1; 3961554c0a3aSHans de Goede 3962554c0a3aSHans de Goede DBG_871X("BA_starting_seqctrl = %d for TID =%d\n", start_seq, status & 0x07); 3963554c0a3aSHans de Goede 3964554c0a3aSHans de Goede psta->BA_starting_seqctrl[status & 0x07] = start_seq; 3965554c0a3aSHans de Goede 3966554c0a3aSHans de Goede BA_starting_seqctrl = start_seq << 4; 3967554c0a3aSHans de Goede } 3968554c0a3aSHans de Goede 3969554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_starting_seqctrl); 3970554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3971554c0a3aSHans de Goede break; 3972554c0a3aSHans de Goede 3973554c0a3aSHans de Goede case 1: /* ADDBA rsp */ 3974554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen)); 3975554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen)); 3976554c0a3aSHans de Goede if (padapter->driver_rx_ampdu_factor != 0xFF) 3977554c0a3aSHans de Goede max_rx_ampdu_factor = 397898b32c71SRoss Schmidt (enum ieee80211_max_ampdu_length_exp)padapter->driver_rx_ampdu_factor; 3979554c0a3aSHans de Goede else 3980554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, 3981554c0a3aSHans de Goede HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); 3982554c0a3aSHans de Goede 398398b32c71SRoss Schmidt if (IEEE80211_HT_MAX_AMPDU_64K == max_rx_ampdu_factor) 3984554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */ 398598b32c71SRoss Schmidt else if (IEEE80211_HT_MAX_AMPDU_32K == max_rx_ampdu_factor) 3986554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */ 398798b32c71SRoss Schmidt else if (IEEE80211_HT_MAX_AMPDU_16K == max_rx_ampdu_factor) 3988554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */ 398998b32c71SRoss Schmidt else if (IEEE80211_HT_MAX_AMPDU_8K == max_rx_ampdu_factor) 3990554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */ 3991554c0a3aSHans de Goede else 3992554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */ 3993554c0a3aSHans de Goede 3994d312a47fSNishka Dasgupta if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter) && 3995554c0a3aSHans de Goede padapter->driver_rx_ampdu_factor == 0xFF) { 3996554c0a3aSHans de Goede /* max buffer size is 8 MSDU */ 3997b3ae8af6SRoss Schmidt BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3998b3ae8af6SRoss Schmidt BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3999554c0a3aSHans de Goede } 4000554c0a3aSHans de Goede 4001554c0a3aSHans de Goede if (pregpriv->ampdu_amsdu == 0)/* disabled */ 4002554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set & ~BIT(0)); 4003554c0a3aSHans de Goede else if (pregpriv->ampdu_amsdu == 1)/* enabled */ 4004554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set | BIT(0)); 4005554c0a3aSHans de Goede else /* auto */ 4006554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 4007554c0a3aSHans de Goede 4008554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 4009554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen)); 4010554c0a3aSHans de Goede break; 4011554c0a3aSHans de Goede case 2:/* DELBA */ 4012554c0a3aSHans de Goede BA_para_set = (status & 0x1F) << 3; 4013554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 4014554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 4015554c0a3aSHans de Goede 4016554c0a3aSHans de Goede reason_code = 37; 4017554c0a3aSHans de Goede le_tmp = cpu_to_le16(reason_code); 4018554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 4019554c0a3aSHans de Goede break; 4020554c0a3aSHans de Goede default: 4021554c0a3aSHans de Goede break; 4022554c0a3aSHans de Goede } 4023554c0a3aSHans de Goede } 4024554c0a3aSHans de Goede 4025554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 4026554c0a3aSHans de Goede 4027554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 4028554c0a3aSHans de Goede } 4029554c0a3aSHans de Goede 4030554c0a3aSHans de Goede static void issue_action_BSSCoexistPacket(struct adapter *padapter) 4031554c0a3aSHans de Goede { 4032554c0a3aSHans de Goede struct list_head *plist, *phead; 4033554c0a3aSHans de Goede unsigned char category, action; 4034554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 4035554c0a3aSHans de Goede struct pkt_attrib *pattrib; 4036554c0a3aSHans de Goede unsigned char *pframe; 4037554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 4038554c0a3aSHans de Goede __le16 *fctrl; 4039554c0a3aSHans de Goede struct wlan_network *pnetwork = NULL; 4040554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 4041554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 4042554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 4043554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4044554c0a3aSHans de Goede struct __queue *queue = &(pmlmepriv->scanned_queue); 4045554c0a3aSHans de Goede u8 InfoContent[16] = {0}; 4046554c0a3aSHans de Goede u8 ICS[8][15]; 4047554c0a3aSHans de Goede 4048554c0a3aSHans de Goede if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0)) 4049554c0a3aSHans de Goede return; 4050554c0a3aSHans de Goede 4051554c0a3aSHans de Goede if (true == pmlmeinfo->bwmode_updated) 4052554c0a3aSHans de Goede return; 4053554c0a3aSHans de Goede 4054554c0a3aSHans de Goede 4055554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 4056554c0a3aSHans de Goede 4057554c0a3aSHans de Goede 4058554c0a3aSHans de Goede category = RTW_WLAN_CATEGORY_PUBLIC; 4059554c0a3aSHans de Goede action = ACT_PUBLIC_BSSCOEXIST; 4060554c0a3aSHans de Goede 4061554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 4062554c0a3aSHans de Goede if (pmgntframe == NULL) { 4063554c0a3aSHans de Goede return; 4064554c0a3aSHans de Goede } 4065554c0a3aSHans de Goede 4066554c0a3aSHans de Goede /* update attribute */ 4067554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 4068554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 4069554c0a3aSHans de Goede 4070554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 4071554c0a3aSHans de Goede 4072554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 4073554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 4074554c0a3aSHans de Goede 4075554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 4076554c0a3aSHans de Goede *(fctrl) = 0; 4077554c0a3aSHans de Goede 4078554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 4079554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 4080554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 4081554c0a3aSHans de Goede 4082554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 4083554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 4084554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 4085554c0a3aSHans de Goede 4086554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 4087554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 4088554c0a3aSHans de Goede 4089554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); 4090554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); 4091554c0a3aSHans de Goede 4092554c0a3aSHans de Goede 4093554c0a3aSHans de Goede /* */ 4094554c0a3aSHans de Goede if (pmlmepriv->num_FortyMHzIntolerant > 0) { 4095554c0a3aSHans de Goede u8 iedata = 0; 4096554c0a3aSHans de Goede 4097554c0a3aSHans de Goede iedata |= BIT(2);/* 20 MHz BSS Width Request */ 4098554c0a3aSHans de Goede 4099554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen)); 4100554c0a3aSHans de Goede 4101554c0a3aSHans de Goede } 4102554c0a3aSHans de Goede 4103554c0a3aSHans de Goede 4104554c0a3aSHans de Goede /* */ 4105554c0a3aSHans de Goede memset(ICS, 0, sizeof(ICS)); 4106554c0a3aSHans de Goede if (pmlmepriv->num_sta_no_ht > 0) { 4107554c0a3aSHans de Goede int i; 4108554c0a3aSHans de Goede 4109554c0a3aSHans de Goede spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 4110554c0a3aSHans de Goede 4111554c0a3aSHans de Goede phead = get_list_head(queue); 4112554c0a3aSHans de Goede plist = get_next(phead); 4113554c0a3aSHans de Goede 4114554c0a3aSHans de Goede while (1) { 4115554c0a3aSHans de Goede int len; 4116554c0a3aSHans de Goede u8 *p; 4117554c0a3aSHans de Goede struct wlan_bssid_ex *pbss_network; 4118554c0a3aSHans de Goede 4119554c0a3aSHans de Goede if (phead == plist) 4120554c0a3aSHans de Goede break; 4121554c0a3aSHans de Goede 412219cf9d7aSRoss Schmidt pnetwork = container_of(plist, struct wlan_network, list); 4123554c0a3aSHans de Goede 4124554c0a3aSHans de Goede plist = get_next(plist); 4125554c0a3aSHans de Goede 4126554c0a3aSHans de Goede pbss_network = (struct wlan_bssid_ex *)&pnetwork->network; 4127554c0a3aSHans de Goede 4128fc6a6528SRoss Schmidt p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pbss_network->IELength - _FIXED_IE_LENGTH_); 4129554c0a3aSHans de Goede if ((p == NULL) || (len == 0)) {/* non-HT */ 4130554c0a3aSHans de Goede 4131554c0a3aSHans de Goede if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14)) 4132554c0a3aSHans de Goede continue; 4133554c0a3aSHans de Goede 4134554c0a3aSHans de Goede ICS[0][pbss_network->Configuration.DSConfig] = 1; 4135554c0a3aSHans de Goede 4136554c0a3aSHans de Goede if (ICS[0][0] == 0) 4137554c0a3aSHans de Goede ICS[0][0] = 1; 4138554c0a3aSHans de Goede } 4139554c0a3aSHans de Goede 4140554c0a3aSHans de Goede } 4141554c0a3aSHans de Goede 4142554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 4143554c0a3aSHans de Goede 4144554c0a3aSHans de Goede 4145554c0a3aSHans de Goede for (i = 0; i < 8; i++) { 4146554c0a3aSHans de Goede if (ICS[i][0] == 1) { 4147554c0a3aSHans de Goede int j, k = 0; 4148554c0a3aSHans de Goede 4149554c0a3aSHans de Goede InfoContent[k] = i; 4150554c0a3aSHans de Goede /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */ 4151554c0a3aSHans de Goede k++; 4152554c0a3aSHans de Goede 4153554c0a3aSHans de Goede for (j = 1; j <= 14; j++) { 4154554c0a3aSHans de Goede if (ICS[i][j] == 1) { 4155554c0a3aSHans de Goede if (k < 16) { 4156554c0a3aSHans de Goede InfoContent[k] = j; /* channel number */ 4157554c0a3aSHans de Goede /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */ 4158554c0a3aSHans de Goede k++; 4159554c0a3aSHans de Goede } 4160554c0a3aSHans de Goede } 4161554c0a3aSHans de Goede } 4162554c0a3aSHans de Goede 4163554c0a3aSHans de Goede pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen)); 4164554c0a3aSHans de Goede 4165554c0a3aSHans de Goede } 4166554c0a3aSHans de Goede 4167554c0a3aSHans de Goede } 4168554c0a3aSHans de Goede 4169554c0a3aSHans de Goede 4170554c0a3aSHans de Goede } 4171554c0a3aSHans de Goede 4172554c0a3aSHans de Goede 4173554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 4174554c0a3aSHans de Goede 4175554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 4176554c0a3aSHans de Goede } 4177554c0a3aSHans de Goede 4178554c0a3aSHans de Goede unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr) 4179554c0a3aSHans de Goede { 4180554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 4181554c0a3aSHans de Goede struct sta_info *psta = NULL; 4182554c0a3aSHans de Goede /* struct recv_reorder_ctrl *preorder_ctrl; */ 4183554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4184554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4185554c0a3aSHans de Goede u16 tid; 4186554c0a3aSHans de Goede 4187554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 4188554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) 4189554c0a3aSHans de Goede return _SUCCESS; 4190554c0a3aSHans de Goede 4191554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, addr); 4192554c0a3aSHans de Goede if (psta == NULL) 4193554c0a3aSHans de Goede return _SUCCESS; 4194554c0a3aSHans de Goede 4195554c0a3aSHans de Goede /* DBG_871X("%s:%s\n", __func__, (initiator == 0)?"RX_DIR":"TX_DIR"); */ 4196554c0a3aSHans de Goede 4197554c0a3aSHans de Goede if (initiator == 0) {/* recipient */ 4198554c0a3aSHans de Goede for (tid = 0; tid < MAXTID; tid++) { 41990ad02fa8SGeorgiana Chelu if (psta->recvreorder_ctrl[tid].enable) { 4200554c0a3aSHans de Goede DBG_871X("rx agg disable tid(%d)\n", tid); 4201f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F)); 4202554c0a3aSHans de Goede psta->recvreorder_ctrl[tid].enable = false; 4203554c0a3aSHans de Goede psta->recvreorder_ctrl[tid].indicate_seq = 0xffff; 4204554c0a3aSHans de Goede #ifdef DBG_RX_SEQ 4205554c0a3aSHans de Goede DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__, 4206554c0a3aSHans de Goede psta->recvreorder_ctrl[tid].indicate_seq); 4207554c0a3aSHans de Goede #endif 4208554c0a3aSHans de Goede } 4209554c0a3aSHans de Goede } 4210554c0a3aSHans de Goede } else if (initiator == 1) {/* originator */ 4211554c0a3aSHans de Goede /* DBG_871X("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap); */ 4212554c0a3aSHans de Goede for (tid = 0; tid < MAXTID; tid++) { 4213554c0a3aSHans de Goede if (psta->htpriv.agg_enable_bitmap & BIT(tid)) { 4214554c0a3aSHans de Goede DBG_871X("tx agg disable tid(%d)\n", tid); 4215f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F)); 4216554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 4217554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); 4218554c0a3aSHans de Goede 4219554c0a3aSHans de Goede } 4220554c0a3aSHans de Goede } 4221554c0a3aSHans de Goede } 4222554c0a3aSHans de Goede 4223554c0a3aSHans de Goede return _SUCCESS; 4224554c0a3aSHans de Goede 4225554c0a3aSHans de Goede } 4226554c0a3aSHans de Goede 4227554c0a3aSHans de Goede unsigned int send_beacon(struct adapter *padapter) 4228554c0a3aSHans de Goede { 4229554c0a3aSHans de Goede u8 bxmitok = false; 4230554c0a3aSHans de Goede int issue = 0; 4231554c0a3aSHans de Goede int poll = 0; 4232554c0a3aSHans de Goede unsigned long start = jiffies; 4233554c0a3aSHans de Goede 4234554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); 4235554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL); 4236554c0a3aSHans de Goede do { 4237554c0a3aSHans de Goede issue_beacon(padapter, 100); 4238554c0a3aSHans de Goede issue++; 4239554c0a3aSHans de Goede do { 4240c22da34aSThomas Avery cond_resched(); 4241554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok)); 4242554c0a3aSHans de Goede poll++; 4243554c0a3aSHans de Goede } while ((poll%10) != 0 && false == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 4244554c0a3aSHans de Goede 4245554c0a3aSHans de Goede } while (false == bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 4246554c0a3aSHans de Goede 4247554c0a3aSHans de Goede if (padapter->bSurpriseRemoved || padapter->bDriverStopped) { 4248554c0a3aSHans de Goede return _FAIL; 4249554c0a3aSHans de Goede } 4250554c0a3aSHans de Goede 4251554c0a3aSHans de Goede 4252554c0a3aSHans de Goede if (false == bxmitok) { 4253554c0a3aSHans de Goede DBG_871X("%s fail! %u ms\n", __func__, jiffies_to_msecs(jiffies - start)); 4254554c0a3aSHans de Goede return _FAIL; 4255554c0a3aSHans de Goede } else { 4256554c0a3aSHans de Goede unsigned long passing_time = jiffies_to_msecs(jiffies - start); 4257554c0a3aSHans de Goede 4258554c0a3aSHans de Goede if (passing_time > 100 || issue > 3) 4259554c0a3aSHans de Goede DBG_871X("%s success, issue:%d, poll:%d, %lu ms\n", __func__, issue, poll, passing_time); 4260554c0a3aSHans de Goede /* else */ 4261554c0a3aSHans de Goede /* DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __func__, issue, poll, passing_time); */ 4262554c0a3aSHans de Goede 4263554c0a3aSHans de Goede return _SUCCESS; 4264554c0a3aSHans de Goede } 4265554c0a3aSHans de Goede } 4266554c0a3aSHans de Goede 4267554c0a3aSHans de Goede /**************************************************************************** 4268554c0a3aSHans de Goede 426968468503SAndreas Hellmich Following are some utility functions for WiFi MLME 4270554c0a3aSHans de Goede 4271554c0a3aSHans de Goede *****************************************************************************/ 4272554c0a3aSHans de Goede 4273554c0a3aSHans de Goede void site_survey(struct adapter *padapter) 4274554c0a3aSHans de Goede { 4275554c0a3aSHans de Goede unsigned char survey_channel = 0, val8; 4276554c0a3aSHans de Goede RT_SCAN_TYPE ScanType = SCAN_PASSIVE; 4277554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4278554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4279554c0a3aSHans de Goede u32 initialgain = 0; 4280554c0a3aSHans de Goede u32 channel_scan_time_ms = 0; 4281554c0a3aSHans de Goede 4282554c0a3aSHans de Goede { 4283554c0a3aSHans de Goede struct rtw_ieee80211_channel *ch; 4284c926f022SSimran Singhal 4285554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) { 4286554c0a3aSHans de Goede ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx]; 4287554c0a3aSHans de Goede survey_channel = ch->hw_value; 4288554c0a3aSHans de Goede ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE; 4289554c0a3aSHans de Goede } 4290554c0a3aSHans de Goede } 4291554c0a3aSHans de Goede 4292554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ch:%u (cnt:%u) at %dms, %c%c%c\n" 4293554c0a3aSHans de Goede , FUNC_ADPT_ARG(padapter) 4294554c0a3aSHans de Goede , survey_channel 4295554c0a3aSHans de Goede , pmlmeext->sitesurvey_res.channel_idx 4296554c0a3aSHans de Goede , jiffies_to_msecs(jiffies - padapter->mlmepriv.scan_start_time) 4297554c0a3aSHans de Goede , ScanType?'A':'P', pmlmeext->sitesurvey_res.scan_mode?'A':'P' 4298554c0a3aSHans de Goede , pmlmeext->sitesurvey_res.ssid[0].SsidLength?'S':' ' 4299554c0a3aSHans de Goede ); 4300554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 4301554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan); 4302554c0a3aSHans de Goede #endif 4303554c0a3aSHans de Goede 4304554c0a3aSHans de Goede if (survey_channel != 0) { 4305554c0a3aSHans de Goede /* PAUSE 4-AC Queue when site_survey */ 4306554c0a3aSHans de Goede /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 4307554c0a3aSHans de Goede /* val8 |= 0x0f; */ 4308554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 4309554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.channel_idx == 0) { 4310554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 4311554c0a3aSHans de Goede if (pmlmeext->fixed_chan != 0xff) 4312554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 4313554c0a3aSHans de Goede else 4314554c0a3aSHans de Goede #endif 4315554c0a3aSHans de Goede set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 4316554c0a3aSHans de Goede } else { 4317554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 4318554c0a3aSHans de Goede if (pmlmeext->fixed_chan != 0xff) 4319554c0a3aSHans de Goede SelectChannel(padapter, pmlmeext->fixed_chan); 4320554c0a3aSHans de Goede else 4321554c0a3aSHans de Goede #endif 4322554c0a3aSHans de Goede SelectChannel(padapter, survey_channel); 4323554c0a3aSHans de Goede } 4324554c0a3aSHans de Goede 4325554c0a3aSHans de Goede if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */ 4326554c0a3aSHans de Goede { 4327554c0a3aSHans de Goede int i; 4328c926f022SSimran Singhal 4329554c0a3aSHans de Goede for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { 4330554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) { 4331554c0a3aSHans de Goede /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */ 4332554c0a3aSHans de Goede if (padapter->registrypriv.wifi_spec) 4333554c0a3aSHans de Goede issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL); 4334554c0a3aSHans de Goede else 4335554c0a3aSHans de Goede issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0); 4336554c0a3aSHans de Goede issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL); 4337554c0a3aSHans de Goede } 4338554c0a3aSHans de Goede } 4339554c0a3aSHans de Goede 4340554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) { 4341554c0a3aSHans de Goede /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */ 4342554c0a3aSHans de Goede if (padapter->registrypriv.wifi_spec) 4343554c0a3aSHans de Goede issue_probereq(padapter, NULL, NULL); 4344554c0a3aSHans de Goede else 4345554c0a3aSHans de Goede issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0); 4346554c0a3aSHans de Goede issue_probereq(padapter, NULL, NULL); 4347554c0a3aSHans de Goede } 4348554c0a3aSHans de Goede } 4349554c0a3aSHans de Goede } 4350554c0a3aSHans de Goede 4351554c0a3aSHans de Goede channel_scan_time_ms = pmlmeext->chan_scan_time; 4352554c0a3aSHans de Goede 4353554c0a3aSHans de Goede set_survey_timer(pmlmeext, channel_scan_time_ms); 4354554c0a3aSHans de Goede #if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR) 4355554c0a3aSHans de Goede { 4356554c0a3aSHans de Goede struct noise_info info; 4357c926f022SSimran Singhal 4358554c0a3aSHans de Goede info.bPauseDIG = false; 4359554c0a3aSHans de Goede info.IGIValue = 0; 4360554c0a3aSHans de Goede info.max_time = channel_scan_time_ms/2;/* ms */ 4361554c0a3aSHans de Goede info.chan = survey_channel; 4362554c0a3aSHans de Goede rtw_hal_set_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &info, false); 4363554c0a3aSHans de Goede } 4364554c0a3aSHans de Goede #endif 4365554c0a3aSHans de Goede 4366554c0a3aSHans de Goede } else { 4367554c0a3aSHans de Goede 4368554c0a3aSHans de Goede /* channel number is 0 or this channel is not valid. */ 4369554c0a3aSHans de Goede 4370554c0a3aSHans de Goede { 4371554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_COMPLETE; 4372554c0a3aSHans de Goede 4373554c0a3aSHans de Goede /* switch back to the original channel */ 4374554c0a3aSHans de Goede /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */ 4375554c0a3aSHans de Goede 4376554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 4377554c0a3aSHans de Goede 4378554c0a3aSHans de Goede /* flush 4-AC Queue after site_survey */ 4379554c0a3aSHans de Goede /* val8 = 0; */ 4380554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 4381554c0a3aSHans de Goede 4382554c0a3aSHans de Goede /* config MSR */ 4383554c0a3aSHans de Goede Set_MSR(padapter, (pmlmeinfo->state & 0x3)); 4384554c0a3aSHans de Goede 4385554c0a3aSHans de Goede initialgain = 0xff; /* restore RX GAIN */ 4386554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 4387554c0a3aSHans de Goede /* turn on dynamic functions */ 4388554c0a3aSHans de Goede Restore_DM_Func_Flag(padapter); 4389554c0a3aSHans de Goede /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */ 4390554c0a3aSHans de Goede 43910ad02fa8SGeorgiana Chelu if (is_client_associated_to_ap(padapter)) 4392554c0a3aSHans de Goede issue_nulldata(padapter, NULL, 0, 3, 500); 4393554c0a3aSHans de Goede 4394554c0a3aSHans de Goede val8 = 0; /* survey done */ 4395554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); 4396554c0a3aSHans de Goede 4397554c0a3aSHans de Goede report_surveydone_event(padapter); 4398554c0a3aSHans de Goede 4399554c0a3aSHans de Goede pmlmeext->chan_scan_time = SURVEY_TO; 4400554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_DISABLE; 4401554c0a3aSHans de Goede 4402554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4403554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4404554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4405554c0a3aSHans de Goede } 4406554c0a3aSHans de Goede } 4407554c0a3aSHans de Goede 4408554c0a3aSHans de Goede return; 4409554c0a3aSHans de Goede 4410554c0a3aSHans de Goede } 4411554c0a3aSHans de Goede 4412554c0a3aSHans de Goede /* collect bss info from Beacon and Probe request/response frames. */ 4413554c0a3aSHans de Goede u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid) 4414554c0a3aSHans de Goede { 4415554c0a3aSHans de Goede int i; 4416554c0a3aSHans de Goede u32 len; 4417554c0a3aSHans de Goede u8 *p; 4418554c0a3aSHans de Goede u16 val16, subtype; 4419554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 4420554c0a3aSHans de Goede u32 packet_len = precv_frame->u.hdr.len; 4421554c0a3aSHans de Goede u8 ie_offset; 4422554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 4423554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4424554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4425554c0a3aSHans de Goede __le32 le32_tmp; 4426554c0a3aSHans de Goede 4427554c0a3aSHans de Goede len = packet_len - sizeof(struct ieee80211_hdr_3addr); 4428554c0a3aSHans de Goede 4429554c0a3aSHans de Goede if (len > MAX_IE_SZ) { 4430554c0a3aSHans de Goede /* DBG_871X("IE too long for survey event\n"); */ 4431554c0a3aSHans de Goede return _FAIL; 4432554c0a3aSHans de Goede } 4433554c0a3aSHans de Goede 4434554c0a3aSHans de Goede memset(bssid, 0, sizeof(struct wlan_bssid_ex)); 4435554c0a3aSHans de Goede 4436554c0a3aSHans de Goede subtype = GetFrameSubType(pframe); 4437554c0a3aSHans de Goede 4438554c0a3aSHans de Goede if (subtype == WIFI_BEACON) { 4439554c0a3aSHans de Goede bssid->Reserved[0] = 1; 4440554c0a3aSHans de Goede ie_offset = _BEACON_IE_OFFSET_; 4441554c0a3aSHans de Goede } else { 4442554c0a3aSHans de Goede /* FIXME : more type */ 4443554c0a3aSHans de Goede if (subtype == WIFI_PROBERSP) { 4444554c0a3aSHans de Goede ie_offset = _PROBERSP_IE_OFFSET_; 4445554c0a3aSHans de Goede bssid->Reserved[0] = 3; 4446554c0a3aSHans de Goede } else if (subtype == WIFI_PROBEREQ) { 4447554c0a3aSHans de Goede ie_offset = _PROBEREQ_IE_OFFSET_; 4448554c0a3aSHans de Goede bssid->Reserved[0] = 2; 4449554c0a3aSHans de Goede } else { 4450554c0a3aSHans de Goede bssid->Reserved[0] = 0; 4451554c0a3aSHans de Goede ie_offset = _FIXED_IE_LENGTH_; 4452554c0a3aSHans de Goede } 4453554c0a3aSHans de Goede } 4454554c0a3aSHans de Goede 4455554c0a3aSHans de Goede bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len; 4456554c0a3aSHans de Goede 4457554c0a3aSHans de Goede /* below is to copy the information element */ 4458554c0a3aSHans de Goede bssid->IELength = len; 4459554c0a3aSHans de Goede memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength); 4460554c0a3aSHans de Goede 4461554c0a3aSHans de Goede /* get the signal strength */ 4462554c0a3aSHans de Goede bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /* in dBM.raw data */ 4463554c0a3aSHans de Goede bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */ 4464554c0a3aSHans de Goede bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */ 4465554c0a3aSHans de Goede 4466554c0a3aSHans de Goede /* checking SSID */ 44673f15277bSRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_SSID, &len, bssid->IELength - ie_offset); 4468554c0a3aSHans de Goede if (p == NULL) { 4469554c0a3aSHans de Goede DBG_871X("marc: cannot find SSID for survey event\n"); 4470554c0a3aSHans de Goede return _FAIL; 4471554c0a3aSHans de Goede } 4472554c0a3aSHans de Goede 4473554c0a3aSHans de Goede if (*(p + 1)) { 4474554c0a3aSHans de Goede if (len > NDIS_802_11_LENGTH_SSID) { 4475554c0a3aSHans de Goede DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); 4476554c0a3aSHans de Goede return _FAIL; 4477554c0a3aSHans de Goede } 4478554c0a3aSHans de Goede memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1)); 4479554c0a3aSHans de Goede bssid->Ssid.SsidLength = *(p + 1); 4480554c0a3aSHans de Goede } else 4481554c0a3aSHans de Goede bssid->Ssid.SsidLength = 0; 4482554c0a3aSHans de Goede 4483554c0a3aSHans de Goede memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); 4484554c0a3aSHans de Goede 4485554c0a3aSHans de Goede /* checking rate info... */ 4486554c0a3aSHans de Goede i = 0; 4487c34c45edSRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_SUPP_RATES, &len, bssid->IELength - ie_offset); 448834557e23SIzabela Bakollari if (p) { 4489554c0a3aSHans de Goede if (len > NDIS_802_11_LENGTH_RATES_EX) { 4490554c0a3aSHans de Goede DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); 4491554c0a3aSHans de Goede return _FAIL; 4492554c0a3aSHans de Goede } 4493554c0a3aSHans de Goede memcpy(bssid->SupportedRates, (p + 2), len); 4494554c0a3aSHans de Goede i = len; 4495554c0a3aSHans de Goede } 4496554c0a3aSHans de Goede 4497554c0a3aSHans de Goede p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset); 449834557e23SIzabela Bakollari if (p) { 4499554c0a3aSHans de Goede if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) { 4500554c0a3aSHans de Goede DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __func__, __LINE__, len); 4501554c0a3aSHans de Goede return _FAIL; 4502554c0a3aSHans de Goede } 4503554c0a3aSHans de Goede memcpy(bssid->SupportedRates + i, (p + 2), len); 4504554c0a3aSHans de Goede } 4505554c0a3aSHans de Goede 4506554c0a3aSHans de Goede bssid->NetworkTypeInUse = Ndis802_11OFDM24; 4507554c0a3aSHans de Goede 4508554c0a3aSHans de Goede if (bssid->IELength < 12) 4509554c0a3aSHans de Goede return _FAIL; 4510554c0a3aSHans de Goede 4511554c0a3aSHans de Goede /* Checking for DSConfig */ 45128f6a9446SRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_DS_PARAMS, &len, bssid->IELength - ie_offset); 4513554c0a3aSHans de Goede 4514554c0a3aSHans de Goede bssid->Configuration.DSConfig = 0; 4515554c0a3aSHans de Goede bssid->Configuration.Length = 0; 4516554c0a3aSHans de Goede 4517554c0a3aSHans de Goede if (p) { 4518554c0a3aSHans de Goede bssid->Configuration.DSConfig = *(p + 2); 4519554c0a3aSHans de Goede } else { 4520554c0a3aSHans de Goede /* In 5G, some ap do not have DSSET IE */ 4521554c0a3aSHans de Goede /* checking HT info for channel */ 4522332ec9dbSRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_HT_OPERATION, &len, bssid->IELength - ie_offset); 4523554c0a3aSHans de Goede if (p) { 4524554c0a3aSHans de Goede struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2); 4525c926f022SSimran Singhal 4526554c0a3aSHans de Goede bssid->Configuration.DSConfig = HT_info->primary_channel; 4527554c0a3aSHans de Goede } else { /* use current channel */ 4528554c0a3aSHans de Goede bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter); 4529554c0a3aSHans de Goede } 4530554c0a3aSHans de Goede } 4531554c0a3aSHans de Goede 4532554c0a3aSHans de Goede memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2); 4533554c0a3aSHans de Goede bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp); 4534554c0a3aSHans de Goede 4535554c0a3aSHans de Goede val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid); 4536554c0a3aSHans de Goede 4537554c0a3aSHans de Goede if (val16 & BIT(0)) { 4538554c0a3aSHans de Goede bssid->InfrastructureMode = Ndis802_11Infrastructure; 4539554c0a3aSHans de Goede memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); 4540554c0a3aSHans de Goede } else { 4541554c0a3aSHans de Goede bssid->InfrastructureMode = Ndis802_11IBSS; 4542554c0a3aSHans de Goede memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN); 4543554c0a3aSHans de Goede } 4544554c0a3aSHans de Goede 4545554c0a3aSHans de Goede if (val16 & BIT(4)) 4546554c0a3aSHans de Goede bssid->Privacy = 1; 4547554c0a3aSHans de Goede else 4548554c0a3aSHans de Goede bssid->Privacy = 0; 4549554c0a3aSHans de Goede 4550554c0a3aSHans de Goede bssid->Configuration.ATIMWindow = 0; 4551554c0a3aSHans de Goede 4552554c0a3aSHans de Goede /* 20/40 BSS Coexistence check */ 4553554c0a3aSHans de Goede if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) { 4554554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 4555554c0a3aSHans de Goede 4556fc6a6528SRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_HT_CAPABILITY, &len, bssid->IELength - ie_offset); 4557554c0a3aSHans de Goede if (p && len > 0) { 4558554c0a3aSHans de Goede struct HT_caps_element *pHT_caps; 4559c926f022SSimran Singhal 4560554c0a3aSHans de Goede pHT_caps = (struct HT_caps_element *)(p + 2); 4561554c0a3aSHans de Goede 4562554c0a3aSHans de Goede if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14)) 4563554c0a3aSHans de Goede pmlmepriv->num_FortyMHzIntolerant++; 4564554c0a3aSHans de Goede } else 4565554c0a3aSHans de Goede pmlmepriv->num_sta_no_ht++; 4566554c0a3aSHans de Goede } 4567554c0a3aSHans de Goede 4568554c0a3aSHans de Goede #if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1 4569554c0a3aSHans de Goede if (strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) { 4570bbda3ac4SRoss Schmidt DBG_871X("Receiving %s(%pM, DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n" 4571554c0a3aSHans de Goede , bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig 4572554c0a3aSHans de Goede , rtw_get_oper_ch(padapter) 4573554c0a3aSHans de Goede , bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi 4574554c0a3aSHans de Goede ); 4575554c0a3aSHans de Goede } 4576554c0a3aSHans de Goede #endif 4577554c0a3aSHans de Goede 457868468503SAndreas Hellmich /* mark bss info receiving from nearby channel as SignalQuality 101 */ 4579554c0a3aSHans de Goede if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter)) 4580554c0a3aSHans de Goede bssid->PhyInfo.SignalQuality = 101; 4581554c0a3aSHans de Goede 4582554c0a3aSHans de Goede return _SUCCESS; 4583554c0a3aSHans de Goede } 4584554c0a3aSHans de Goede 4585554c0a3aSHans de Goede void start_create_ibss(struct adapter *padapter) 4586554c0a3aSHans de Goede { 4587554c0a3aSHans de Goede unsigned short caps; 4588554c0a3aSHans de Goede u8 val8; 4589554c0a3aSHans de Goede u8 join_type; 4590554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4591554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4592554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 4593c926f022SSimran Singhal 4594554c0a3aSHans de Goede pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; 4595554c0a3aSHans de Goede pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); 4596554c0a3aSHans de Goede 4597554c0a3aSHans de Goede /* update wireless mode */ 4598554c0a3aSHans de Goede update_wireless_mode(padapter); 4599554c0a3aSHans de Goede 460068468503SAndreas Hellmich /* update capability */ 4601554c0a3aSHans de Goede caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); 4602554c0a3aSHans de Goede update_capinfo(padapter, caps); 46032415ae7fSRoss Schmidt if (caps&WLAN_CAPABILITY_IBSS) {/* adhoc master */ 4604554c0a3aSHans de Goede val8 = 0xcf; 4605554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4606554c0a3aSHans de Goede 4607554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL); 4608554c0a3aSHans de Goede 4609554c0a3aSHans de Goede /* switch channel */ 4610554c0a3aSHans de Goede /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */ 4611554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 4612554c0a3aSHans de Goede 4613554c0a3aSHans de Goede beacon_timing_control(padapter); 4614554c0a3aSHans de Goede 4615554c0a3aSHans de Goede /* set msr to WIFI_FW_ADHOC_STATE */ 4616554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_ADHOC_STATE; 4617554c0a3aSHans de Goede Set_MSR(padapter, (pmlmeinfo->state & 0x3)); 4618554c0a3aSHans de Goede 4619554c0a3aSHans de Goede /* issue beacon */ 4620554c0a3aSHans de Goede if (send_beacon(padapter) == _FAIL) { 4621554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("issuing beacon frame fail....\n")); 4622554c0a3aSHans de Goede 4623554c0a3aSHans de Goede report_join_res(padapter, -1); 4624554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4625554c0a3aSHans de Goede } else { 4626554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress); 4627554c0a3aSHans de Goede join_type = 0; 4628554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 4629554c0a3aSHans de Goede 4630554c0a3aSHans de Goede report_join_res(padapter, 1); 4631554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 4632554c0a3aSHans de Goede rtw_indicate_connect(padapter); 4633554c0a3aSHans de Goede } 4634554c0a3aSHans de Goede } else { 4635554c0a3aSHans de Goede DBG_871X("start_create_ibss, invalid cap:%x\n", caps); 4636554c0a3aSHans de Goede return; 4637554c0a3aSHans de Goede } 4638554c0a3aSHans de Goede /* update bc/mc sta_info */ 4639554c0a3aSHans de Goede update_bmc_sta(padapter); 4640554c0a3aSHans de Goede 4641554c0a3aSHans de Goede } 4642554c0a3aSHans de Goede 4643554c0a3aSHans de Goede void start_clnt_join(struct adapter *padapter) 4644554c0a3aSHans de Goede { 4645554c0a3aSHans de Goede unsigned short caps; 4646554c0a3aSHans de Goede u8 val8; 4647554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4648554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4649554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 4650554c0a3aSHans de Goede int beacon_timeout; 4651554c0a3aSHans de Goede 4652554c0a3aSHans de Goede /* update wireless mode */ 4653554c0a3aSHans de Goede update_wireless_mode(padapter); 4654554c0a3aSHans de Goede 465568468503SAndreas Hellmich /* update capability */ 4656554c0a3aSHans de Goede caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); 4657554c0a3aSHans de Goede update_capinfo(padapter, caps); 46582415ae7fSRoss Schmidt if (caps&WLAN_CAPABILITY_ESS) { 4659554c0a3aSHans de Goede Set_MSR(padapter, WIFI_FW_STATION_STATE); 4660554c0a3aSHans de Goede 4661554c0a3aSHans de Goede val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf; 4662554c0a3aSHans de Goede 4663554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4664554c0a3aSHans de Goede 4665554c0a3aSHans de Goede /* Because of AP's not receiving deauth before */ 4666554c0a3aSHans de Goede /* AP may: 1)not response auth or 2)deauth us after link is complete */ 4667554c0a3aSHans de Goede /* issue deauth before issuing auth to deal with the situation */ 4668554c0a3aSHans de Goede 4669554c0a3aSHans de Goede /* Commented by Albert 2012/07/21 */ 4670554c0a3aSHans de Goede /* For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it. */ 4671554c0a3aSHans de Goede { 4672554c0a3aSHans de Goede /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */ 4673554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); 4674554c0a3aSHans de Goede } 4675554c0a3aSHans de Goede 4676554c0a3aSHans de Goede /* here wait for receiving the beacon to start auth */ 4677554c0a3aSHans de Goede /* and enable a timer */ 4678554c0a3aSHans de Goede beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval); 4679554c0a3aSHans de Goede set_link_timer(pmlmeext, beacon_timeout); 4680554c0a3aSHans de Goede _set_timer(&padapter->mlmepriv.assoc_timer, 4681554c0a3aSHans de Goede (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout); 4682554c0a3aSHans de Goede 4683554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE; 46842415ae7fSRoss Schmidt } else if (caps&WLAN_CAPABILITY_IBSS) { /* adhoc client */ 4685554c0a3aSHans de Goede Set_MSR(padapter, WIFI_FW_ADHOC_STATE); 4686554c0a3aSHans de Goede 4687554c0a3aSHans de Goede val8 = 0xcf; 4688554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4689554c0a3aSHans de Goede 4690554c0a3aSHans de Goede beacon_timing_control(padapter); 4691554c0a3aSHans de Goede 4692554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_ADHOC_STATE; 4693554c0a3aSHans de Goede 4694554c0a3aSHans de Goede report_join_res(padapter, 1); 4695554c0a3aSHans de Goede } else { 4696554c0a3aSHans de Goede /* DBG_871X("marc: invalid cap:%x\n", caps); */ 4697554c0a3aSHans de Goede return; 4698554c0a3aSHans de Goede } 4699554c0a3aSHans de Goede 4700554c0a3aSHans de Goede } 4701554c0a3aSHans de Goede 4702554c0a3aSHans de Goede void start_clnt_auth(struct adapter *padapter) 4703554c0a3aSHans de Goede { 4704554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4705554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4706554c0a3aSHans de Goede 4707554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 4708554c0a3aSHans de Goede 4709554c0a3aSHans de Goede pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL); 4710554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_AUTH_STATE; 4711554c0a3aSHans de Goede 4712554c0a3aSHans de Goede pmlmeinfo->auth_seq = 1; 4713554c0a3aSHans de Goede pmlmeinfo->reauth_count = 0; 4714554c0a3aSHans de Goede pmlmeinfo->reassoc_count = 0; 4715554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 4716554c0a3aSHans de Goede pmlmeext->retry = 0; 4717554c0a3aSHans de Goede 4718554c0a3aSHans de Goede 4719554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "start auth\n"); 4720554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 4721554c0a3aSHans de Goede 4722554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 4723554c0a3aSHans de Goede 4724554c0a3aSHans de Goede } 4725554c0a3aSHans de Goede 4726554c0a3aSHans de Goede 4727554c0a3aSHans de Goede void start_clnt_assoc(struct adapter *padapter) 4728554c0a3aSHans de Goede { 4729554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4730554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4731554c0a3aSHans de Goede 4732554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 4733554c0a3aSHans de Goede 4734554c0a3aSHans de Goede pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE)); 4735554c0a3aSHans de Goede pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE); 4736554c0a3aSHans de Goede 4737554c0a3aSHans de Goede issue_assocreq(padapter); 4738554c0a3aSHans de Goede 4739554c0a3aSHans de Goede set_link_timer(pmlmeext, REASSOC_TO); 4740554c0a3aSHans de Goede } 4741554c0a3aSHans de Goede 4742554c0a3aSHans de Goede unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) 4743554c0a3aSHans de Goede { 4744554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4745554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4746554c0a3aSHans de Goede 4747554c0a3aSHans de Goede /* check A3 */ 4748554c0a3aSHans de Goede if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN))) 4749554c0a3aSHans de Goede return _SUCCESS; 4750554c0a3aSHans de Goede 4751554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 4752554c0a3aSHans de Goede 4753554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 4754554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { 4755554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4756554c0a3aSHans de Goede report_del_sta_event(padapter, MacAddr, reason); 4757554c0a3aSHans de Goede 4758554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) { 4759554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4760554c0a3aSHans de Goede report_join_res(padapter, -2); 4761554c0a3aSHans de Goede } 4762554c0a3aSHans de Goede } 4763554c0a3aSHans de Goede 4764554c0a3aSHans de Goede return _SUCCESS; 4765554c0a3aSHans de Goede } 4766554c0a3aSHans de Goede 4767554c0a3aSHans de Goede static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid) 4768554c0a3aSHans de Goede { 4769554c0a3aSHans de Goede struct registry_priv *pregistrypriv; 4770554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 4771554c0a3aSHans de Goede RT_CHANNEL_INFO *chplan_new; 4772554c0a3aSHans de Goede u8 channel; 4773554c0a3aSHans de Goede u8 i; 4774554c0a3aSHans de Goede 4775554c0a3aSHans de Goede 4776554c0a3aSHans de Goede pregistrypriv = &padapter->registrypriv; 4777554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 4778554c0a3aSHans de Goede 4779554c0a3aSHans de Goede /* Adjust channel plan by AP Country IE */ 4780554c0a3aSHans de Goede if (pregistrypriv->enable80211d && 4781554c0a3aSHans de Goede (!pmlmeext->update_channel_plan_by_ap_done)) { 4782554c0a3aSHans de Goede u8 *ie, *p; 4783554c0a3aSHans de Goede u32 len; 4784554c0a3aSHans de Goede RT_CHANNEL_PLAN chplan_ap; 4785554c0a3aSHans de Goede RT_CHANNEL_INFO chplan_sta[MAX_CHANNEL_NUM]; 4786554c0a3aSHans de Goede u8 country[4]; 4787554c0a3aSHans de Goede u8 fcn; /* first channel number */ 4788554c0a3aSHans de Goede u8 noc; /* number of channel */ 4789554c0a3aSHans de Goede u8 j, k; 4790554c0a3aSHans de Goede 4791*0b44fca9SRoss Schmidt ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_COUNTRY, &len, bssid->IELength - _FIXED_IE_LENGTH_); 4792554c0a3aSHans de Goede if (!ie) 4793554c0a3aSHans de Goede return; 4794554c0a3aSHans de Goede if (len < 6) 4795554c0a3aSHans de Goede return; 4796554c0a3aSHans de Goede 4797554c0a3aSHans de Goede ie += 2; 4798554c0a3aSHans de Goede p = ie; 4799554c0a3aSHans de Goede ie += len; 4800554c0a3aSHans de Goede 4801554c0a3aSHans de Goede memset(country, 0, 4); 4802554c0a3aSHans de Goede memcpy(country, p, 3); 4803554c0a3aSHans de Goede p += 3; 4804554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, 4805554c0a3aSHans de Goede ("%s: 802.11d country =%s\n", __func__, country)); 4806554c0a3aSHans de Goede 4807554c0a3aSHans de Goede i = 0; 4808554c0a3aSHans de Goede while ((ie - p) >= 3) { 4809554c0a3aSHans de Goede fcn = *(p++); 4810554c0a3aSHans de Goede noc = *(p++); 4811554c0a3aSHans de Goede p++; 4812554c0a3aSHans de Goede 4813554c0a3aSHans de Goede for (j = 0; j < noc; j++) { 4814554c0a3aSHans de Goede if (fcn <= 14) 4815554c0a3aSHans de Goede channel = fcn + j; /* 2.4 GHz */ 4816554c0a3aSHans de Goede else 4817554c0a3aSHans de Goede channel = fcn + j*4; /* 5 GHz */ 4818554c0a3aSHans de Goede 4819554c0a3aSHans de Goede chplan_ap.Channel[i++] = channel; 4820554c0a3aSHans de Goede } 4821554c0a3aSHans de Goede } 4822554c0a3aSHans de Goede chplan_ap.Len = i; 4823554c0a3aSHans de Goede 4824f55a6d45SArnd Bergmann #ifdef DEBUG_RTL871X 4825554c0a3aSHans de Goede i = 0; 4826554c0a3aSHans de Goede DBG_871X("%s: AP[%s] channel plan {", __func__, bssid->Ssid.Ssid); 4827554c0a3aSHans de Goede while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0)) { 4828554c0a3aSHans de Goede DBG_8192C("%02d,", chplan_ap.Channel[i]); 4829554c0a3aSHans de Goede i++; 4830554c0a3aSHans de Goede } 4831554c0a3aSHans de Goede DBG_871X("}\n"); 4832554c0a3aSHans de Goede #endif 4833554c0a3aSHans de Goede 4834554c0a3aSHans de Goede memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta)); 4835f55a6d45SArnd Bergmann #ifdef DEBUG_RTL871X 4836554c0a3aSHans de Goede i = 0; 4837554c0a3aSHans de Goede DBG_871X("%s: STA channel plan {", __func__); 4838554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4839554c0a3aSHans de Goede DBG_871X("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType == SCAN_PASSIVE?'p':'a'); 4840554c0a3aSHans de Goede i++; 4841554c0a3aSHans de Goede } 4842554c0a3aSHans de Goede DBG_871X("}\n"); 4843554c0a3aSHans de Goede #endif 4844554c0a3aSHans de Goede 4845554c0a3aSHans de Goede memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set)); 4846554c0a3aSHans de Goede chplan_new = pmlmeext->channel_set; 4847554c0a3aSHans de Goede 4848554c0a3aSHans de Goede i = j = k = 0; 4849554c0a3aSHans de Goede if (pregistrypriv->wireless_mode & WIRELESS_11G) { 4850554c0a3aSHans de Goede do { 4851554c0a3aSHans de Goede if ((i == MAX_CHANNEL_NUM) || 4852554c0a3aSHans de Goede (chplan_sta[i].ChannelNum == 0) || 4853554c0a3aSHans de Goede (chplan_sta[i].ChannelNum > 14)) 4854554c0a3aSHans de Goede break; 4855554c0a3aSHans de Goede 4856554c0a3aSHans de Goede if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14)) 4857554c0a3aSHans de Goede break; 4858554c0a3aSHans de Goede 4859554c0a3aSHans de Goede if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { 4860554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4861554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4862554c0a3aSHans de Goede i++; 4863554c0a3aSHans de Goede j++; 4864554c0a3aSHans de Goede k++; 4865554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { 4866554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4867554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4868554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4869554c0a3aSHans de Goede i++; 4870554c0a3aSHans de Goede k++; 4871554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { 4872554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4873554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4874554c0a3aSHans de Goede j++; 4875554c0a3aSHans de Goede k++; 4876554c0a3aSHans de Goede } 4877554c0a3aSHans de Goede } while (1); 4878554c0a3aSHans de Goede 4879554c0a3aSHans de Goede /* change AP not support channel to Passive scan */ 4880554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && 4881554c0a3aSHans de Goede (chplan_sta[i].ChannelNum != 0) && 4882554c0a3aSHans de Goede (chplan_sta[i].ChannelNum <= 14)) { 4883554c0a3aSHans de Goede 4884554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4885554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4886554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4887554c0a3aSHans de Goede i++; 4888554c0a3aSHans de Goede k++; 4889554c0a3aSHans de Goede } 4890554c0a3aSHans de Goede 4891554c0a3aSHans de Goede /* add channel AP supported */ 4892554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) { 4893554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4894554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4895554c0a3aSHans de Goede j++; 4896554c0a3aSHans de Goede k++; 4897554c0a3aSHans de Goede } 4898554c0a3aSHans de Goede } else { 4899554c0a3aSHans de Goede /* keep original STA 2.4G channel plan */ 4900554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && 4901554c0a3aSHans de Goede (chplan_sta[i].ChannelNum != 0) && 4902554c0a3aSHans de Goede (chplan_sta[i].ChannelNum <= 14)) { 4903554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4904554c0a3aSHans de Goede chplan_new[k].ScanType = chplan_sta[i].ScanType; 4905554c0a3aSHans de Goede i++; 4906554c0a3aSHans de Goede k++; 4907554c0a3aSHans de Goede } 4908554c0a3aSHans de Goede 4909554c0a3aSHans de Goede /* skip AP 2.4G channel plan */ 4910554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) { 4911554c0a3aSHans de Goede j++; 4912554c0a3aSHans de Goede } 4913554c0a3aSHans de Goede } 4914554c0a3aSHans de Goede 4915554c0a3aSHans de Goede if (pregistrypriv->wireless_mode & WIRELESS_11A) { 4916554c0a3aSHans de Goede do { 4917554c0a3aSHans de Goede if ((i == MAX_CHANNEL_NUM) || 4918554c0a3aSHans de Goede (chplan_sta[i].ChannelNum == 0)) 4919554c0a3aSHans de Goede break; 4920554c0a3aSHans de Goede 4921554c0a3aSHans de Goede if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0)) 4922554c0a3aSHans de Goede break; 4923554c0a3aSHans de Goede 4924554c0a3aSHans de Goede if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { 4925554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4926554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4927554c0a3aSHans de Goede i++; 4928554c0a3aSHans de Goede j++; 4929554c0a3aSHans de Goede k++; 4930554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { 4931554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4932554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4933554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4934554c0a3aSHans de Goede i++; 4935554c0a3aSHans de Goede k++; 4936554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { 4937554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4938554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4939554c0a3aSHans de Goede j++; 4940554c0a3aSHans de Goede k++; 4941554c0a3aSHans de Goede } 4942554c0a3aSHans de Goede } while (1); 4943554c0a3aSHans de Goede 4944554c0a3aSHans de Goede /* change AP not support channel to Passive scan */ 4945554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4946554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4947554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4948554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4949554c0a3aSHans de Goede i++; 4950554c0a3aSHans de Goede k++; 4951554c0a3aSHans de Goede } 4952554c0a3aSHans de Goede 4953554c0a3aSHans de Goede /* add channel AP supported */ 4954554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) { 4955554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4956554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4957554c0a3aSHans de Goede j++; 4958554c0a3aSHans de Goede k++; 4959554c0a3aSHans de Goede } 4960554c0a3aSHans de Goede } else { 4961554c0a3aSHans de Goede /* keep original STA 5G channel plan */ 4962554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4963554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4964554c0a3aSHans de Goede chplan_new[k].ScanType = chplan_sta[i].ScanType; 4965554c0a3aSHans de Goede i++; 4966554c0a3aSHans de Goede k++; 4967554c0a3aSHans de Goede } 4968554c0a3aSHans de Goede } 4969554c0a3aSHans de Goede 4970554c0a3aSHans de Goede pmlmeext->update_channel_plan_by_ap_done = 1; 4971554c0a3aSHans de Goede 4972f55a6d45SArnd Bergmann #ifdef DEBUG_RTL871X 4973554c0a3aSHans de Goede k = 0; 4974554c0a3aSHans de Goede DBG_871X("%s: new STA channel plan {", __func__); 4975554c0a3aSHans de Goede while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) { 4976554c0a3aSHans de Goede DBG_871X("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType == SCAN_PASSIVE?'p':'c'); 4977554c0a3aSHans de Goede k++; 4978554c0a3aSHans de Goede } 4979554c0a3aSHans de Goede DBG_871X("}\n"); 4980554c0a3aSHans de Goede #endif 4981554c0a3aSHans de Goede } 4982554c0a3aSHans de Goede 4983554c0a3aSHans de Goede /* If channel is used by AP, set channel scan type to active */ 4984554c0a3aSHans de Goede channel = bssid->Configuration.DSConfig; 4985554c0a3aSHans de Goede chplan_new = pmlmeext->channel_set; 4986554c0a3aSHans de Goede i = 0; 4987554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) { 4988554c0a3aSHans de Goede if (chplan_new[i].ChannelNum == channel) { 4989554c0a3aSHans de Goede if (chplan_new[i].ScanType == SCAN_PASSIVE) { 4990554c0a3aSHans de Goede /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */ 4991554c0a3aSHans de Goede if (channel >= 52 && channel <= 144) 4992554c0a3aSHans de Goede break; 4993554c0a3aSHans de Goede 4994554c0a3aSHans de Goede chplan_new[i].ScanType = SCAN_ACTIVE; 4995554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, 4996554c0a3aSHans de Goede ("%s: change channel %d scan type from passive to active\n", 4997554c0a3aSHans de Goede __func__, channel)); 4998554c0a3aSHans de Goede } 4999554c0a3aSHans de Goede break; 5000554c0a3aSHans de Goede } 5001554c0a3aSHans de Goede i++; 5002554c0a3aSHans de Goede } 5003554c0a3aSHans de Goede } 5004554c0a3aSHans de Goede 5005554c0a3aSHans de Goede /**************************************************************************** 5006554c0a3aSHans de Goede 5007554c0a3aSHans de Goede Following are the functions to report events 5008554c0a3aSHans de Goede 5009554c0a3aSHans de Goede *****************************************************************************/ 5010554c0a3aSHans de Goede 5011554c0a3aSHans de Goede void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame) 5012554c0a3aSHans de Goede { 5013554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5014554c0a3aSHans de Goede u8 *pevtcmd; 5015554c0a3aSHans de Goede u32 cmdsz; 5016554c0a3aSHans de Goede struct survey_event *psurvey_evt; 5017554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5018554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 5019554c0a3aSHans de Goede struct cmd_priv *pcmdpriv; 5020554c0a3aSHans de Goede /* u8 *pframe = precv_frame->u.hdr.rx_data; */ 5021554c0a3aSHans de Goede /* uint len = precv_frame->u.hdr.len; */ 5022554c0a3aSHans de Goede 5023554c0a3aSHans de Goede if (!padapter) 5024554c0a3aSHans de Goede return; 5025554c0a3aSHans de Goede 5026554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 5027554c0a3aSHans de Goede pcmdpriv = &padapter->cmdpriv; 5028554c0a3aSHans de Goede 50292ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 503041452327SVatsala Narang if (!pcmd_obj) 5031554c0a3aSHans de Goede return; 5032554c0a3aSHans de Goede 5033554c0a3aSHans de Goede cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header)); 50342ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 503541452327SVatsala Narang if (!pevtcmd) { 50368f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5037554c0a3aSHans de Goede return; 5038554c0a3aSHans de Goede } 5039554c0a3aSHans de Goede 5040554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5041554c0a3aSHans de Goede 5042554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5043554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5044554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5045554c0a3aSHans de Goede 5046554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5047554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5048554c0a3aSHans de Goede 5049554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5050554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct survey_event); 5051554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); 5052554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5053554c0a3aSHans de Goede 5054554c0a3aSHans de Goede psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5055554c0a3aSHans de Goede 5056554c0a3aSHans de Goede if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) { 50578f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 50588f24f505SMadhumitha Prabakaran kfree(pevtcmd); 5059554c0a3aSHans de Goede return; 5060554c0a3aSHans de Goede } 5061554c0a3aSHans de Goede 5062554c0a3aSHans de Goede process_80211d(padapter, &psurvey_evt->bss); 5063554c0a3aSHans de Goede 5064554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5065554c0a3aSHans de Goede 5066554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt++; 5067554c0a3aSHans de Goede 5068554c0a3aSHans de Goede return; 5069554c0a3aSHans de Goede 5070554c0a3aSHans de Goede } 5071554c0a3aSHans de Goede 5072554c0a3aSHans de Goede void report_surveydone_event(struct adapter *padapter) 5073554c0a3aSHans de Goede { 5074554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5075554c0a3aSHans de Goede u8 *pevtcmd; 5076554c0a3aSHans de Goede u32 cmdsz; 5077554c0a3aSHans de Goede struct surveydone_event *psurveydone_evt; 5078554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5079554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5080554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5081554c0a3aSHans de Goede 50822ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 508341452327SVatsala Narang if (!pcmd_obj) 5084554c0a3aSHans de Goede return; 5085554c0a3aSHans de Goede 5086554c0a3aSHans de Goede cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header)); 50872ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 508841452327SVatsala Narang if (!pevtcmd) { 50898f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5090554c0a3aSHans de Goede return; 5091554c0a3aSHans de Goede } 5092554c0a3aSHans de Goede 5093554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5094554c0a3aSHans de Goede 5095554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5096554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5097554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5098554c0a3aSHans de Goede 5099554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5100554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5101554c0a3aSHans de Goede 5102554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5103554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct surveydone_event); 5104554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); 5105554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5106554c0a3aSHans de Goede 5107554c0a3aSHans de Goede psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5108554c0a3aSHans de Goede psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt; 5109554c0a3aSHans de Goede 5110d0cc39cdSRoss Schmidt DBG_871X("survey done event(%x) band:%d for %s\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter)); 5111554c0a3aSHans de Goede 5112554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5113554c0a3aSHans de Goede 5114554c0a3aSHans de Goede return; 5115554c0a3aSHans de Goede 5116554c0a3aSHans de Goede } 5117554c0a3aSHans de Goede 5118554c0a3aSHans de Goede void report_join_res(struct adapter *padapter, int res) 5119554c0a3aSHans de Goede { 5120554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5121554c0a3aSHans de Goede u8 *pevtcmd; 5122554c0a3aSHans de Goede u32 cmdsz; 5123554c0a3aSHans de Goede struct joinbss_event *pjoinbss_evt; 5124554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5125554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5126554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5127554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5128554c0a3aSHans de Goede 51292ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 513041452327SVatsala Narang if (!pcmd_obj) 5131554c0a3aSHans de Goede return; 5132554c0a3aSHans de Goede 5133554c0a3aSHans de Goede cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header)); 51342ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 513541452327SVatsala Narang if (!pevtcmd) { 51368f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5137554c0a3aSHans de Goede return; 5138554c0a3aSHans de Goede } 5139554c0a3aSHans de Goede 5140554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5141554c0a3aSHans de Goede 5142554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5143554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5144554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5145554c0a3aSHans de Goede 5146554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5147554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5148554c0a3aSHans de Goede 5149554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5150554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct joinbss_event); 5151554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); 5152554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5153554c0a3aSHans de Goede 5154554c0a3aSHans de Goede pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5155554c0a3aSHans de Goede memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex)); 5156554c0a3aSHans de Goede pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = res; 5157554c0a3aSHans de Goede 5158554c0a3aSHans de Goede DBG_871X("report_join_res(%d)\n", res); 5159554c0a3aSHans de Goede 5160554c0a3aSHans de Goede 5161554c0a3aSHans de Goede rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network); 5162554c0a3aSHans de Goede 5163554c0a3aSHans de Goede 5164554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5165554c0a3aSHans de Goede 5166554c0a3aSHans de Goede return; 5167554c0a3aSHans de Goede 5168554c0a3aSHans de Goede } 5169554c0a3aSHans de Goede 5170554c0a3aSHans de Goede void report_wmm_edca_update(struct adapter *padapter) 5171554c0a3aSHans de Goede { 5172554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5173554c0a3aSHans de Goede u8 *pevtcmd; 5174554c0a3aSHans de Goede u32 cmdsz; 5175554c0a3aSHans de Goede struct wmm_event *pwmm_event; 5176554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5177554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5178554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5179554c0a3aSHans de Goede 51802ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 518141452327SVatsala Narang if (!pcmd_obj) 5182554c0a3aSHans de Goede return; 5183554c0a3aSHans de Goede 5184554c0a3aSHans de Goede cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header)); 51852ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 518641452327SVatsala Narang if (!pevtcmd) { 51878f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5188554c0a3aSHans de Goede return; 5189554c0a3aSHans de Goede } 5190554c0a3aSHans de Goede 5191554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5192554c0a3aSHans de Goede 5193554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5194554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5195554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5196554c0a3aSHans de Goede 5197554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5198554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5199554c0a3aSHans de Goede 5200554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5201554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct wmm_event); 5202554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM); 5203554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5204554c0a3aSHans de Goede 5205554c0a3aSHans de Goede pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5206554c0a3aSHans de Goede pwmm_event->wmm = 0; 5207554c0a3aSHans de Goede 5208554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5209554c0a3aSHans de Goede 5210554c0a3aSHans de Goede return; 5211554c0a3aSHans de Goede 5212554c0a3aSHans de Goede } 5213554c0a3aSHans de Goede 5214554c0a3aSHans de Goede void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) 5215554c0a3aSHans de Goede { 5216554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5217554c0a3aSHans de Goede u8 *pevtcmd; 5218554c0a3aSHans de Goede u32 cmdsz; 5219554c0a3aSHans de Goede struct sta_info *psta; 5220554c0a3aSHans de Goede int mac_id; 5221554c0a3aSHans de Goede struct stadel_event *pdel_sta_evt; 5222554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5223554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5224554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5225554c0a3aSHans de Goede 52262ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 5227554c0a3aSHans de Goede if (pcmd_obj == NULL) { 5228554c0a3aSHans de Goede return; 5229554c0a3aSHans de Goede } 5230554c0a3aSHans de Goede 5231554c0a3aSHans de Goede cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header)); 52322ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 5233554c0a3aSHans de Goede if (pevtcmd == NULL) { 52348f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5235554c0a3aSHans de Goede return; 5236554c0a3aSHans de Goede } 5237554c0a3aSHans de Goede 5238554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5239554c0a3aSHans de Goede 5240554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5241554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5242554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5243554c0a3aSHans de Goede 5244554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5245554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5246554c0a3aSHans de Goede 5247554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5248554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct stadel_event); 5249554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); 5250554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5251554c0a3aSHans de Goede 5252554c0a3aSHans de Goede pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5253554c0a3aSHans de Goede memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN); 5254554c0a3aSHans de Goede memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2); 5255554c0a3aSHans de Goede 5256554c0a3aSHans de Goede 5257554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, MacAddr); 5258554c0a3aSHans de Goede if (psta) 5259554c0a3aSHans de Goede mac_id = (int)psta->mac_id; 5260554c0a3aSHans de Goede else 5261554c0a3aSHans de Goede mac_id = (-1); 5262554c0a3aSHans de Goede 5263554c0a3aSHans de Goede pdel_sta_evt->mac_id = mac_id; 5264554c0a3aSHans de Goede 5265554c0a3aSHans de Goede DBG_871X("report_del_sta_event: delete STA, mac_id =%d\n", mac_id); 5266554c0a3aSHans de Goede 5267554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5268554c0a3aSHans de Goede } 5269554c0a3aSHans de Goede 5270554c0a3aSHans de Goede void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx) 5271554c0a3aSHans de Goede { 5272554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 5273554c0a3aSHans de Goede u8 *pevtcmd; 5274554c0a3aSHans de Goede u32 cmdsz; 5275554c0a3aSHans de Goede struct stassoc_event *padd_sta_evt; 5276554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 5277554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5278554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5279554c0a3aSHans de Goede 52802ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 5281554c0a3aSHans de Goede if (pcmd_obj == NULL) 5282554c0a3aSHans de Goede return; 5283554c0a3aSHans de Goede 5284554c0a3aSHans de Goede cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header)); 52852ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 5286554c0a3aSHans de Goede if (pevtcmd == NULL) { 52878f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 5288554c0a3aSHans de Goede return; 5289554c0a3aSHans de Goede } 5290554c0a3aSHans de Goede 5291554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 5292554c0a3aSHans de Goede 5293554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 5294554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 5295554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 5296554c0a3aSHans de Goede 5297554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 5298554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 5299554c0a3aSHans de Goede 5300554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 5301554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct stassoc_event); 5302554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); 5303554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 5304554c0a3aSHans de Goede 5305554c0a3aSHans de Goede padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 5306554c0a3aSHans de Goede memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN); 5307554c0a3aSHans de Goede padd_sta_evt->cam_id = cam_idx; 5308554c0a3aSHans de Goede 5309554c0a3aSHans de Goede DBG_871X("report_add_sta_event: add STA\n"); 5310554c0a3aSHans de Goede 5311554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 5312554c0a3aSHans de Goede } 5313554c0a3aSHans de Goede 5314554c0a3aSHans de Goede /**************************************************************************** 5315554c0a3aSHans de Goede 5316554c0a3aSHans de Goede Following are the event callback functions 5317554c0a3aSHans de Goede 5318554c0a3aSHans de Goede *****************************************************************************/ 5319554c0a3aSHans de Goede 5320554c0a3aSHans de Goede /* for sta/adhoc mode */ 5321554c0a3aSHans de Goede void update_sta_info(struct adapter *padapter, struct sta_info *psta) 5322554c0a3aSHans de Goede { 5323554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 5324554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5325554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5326554c0a3aSHans de Goede 5327554c0a3aSHans de Goede /* ERP */ 5328554c0a3aSHans de Goede VCS_update(padapter, psta); 5329554c0a3aSHans de Goede 5330554c0a3aSHans de Goede /* HT */ 5331554c0a3aSHans de Goede if (pmlmepriv->htpriv.ht_option) { 5332554c0a3aSHans de Goede psta->htpriv.ht_option = true; 5333554c0a3aSHans de Goede 5334554c0a3aSHans de Goede psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; 5335554c0a3aSHans de Goede 5336554c0a3aSHans de Goede psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2; 5337554c0a3aSHans de Goede 5338554c0a3aSHans de Goede if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20)) 5339554c0a3aSHans de Goede psta->htpriv.sgi_20m = true; 5340554c0a3aSHans de Goede 5341554c0a3aSHans de Goede if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40)) 5342554c0a3aSHans de Goede psta->htpriv.sgi_40m = true; 5343554c0a3aSHans de Goede 5344554c0a3aSHans de Goede psta->qos_option = true; 5345554c0a3aSHans de Goede 5346554c0a3aSHans de Goede psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap; 5347554c0a3aSHans de Goede psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap; 5348554c0a3aSHans de Goede psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap; 5349554c0a3aSHans de Goede 5350c25d8a7dSRoss Schmidt memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct ieee80211_ht_cap)); 5351554c0a3aSHans de Goede } else { 5352554c0a3aSHans de Goede psta->htpriv.ht_option = false; 5353554c0a3aSHans de Goede 5354554c0a3aSHans de Goede psta->htpriv.ampdu_enable = false; 5355554c0a3aSHans de Goede 5356554c0a3aSHans de Goede psta->htpriv.sgi_20m = false; 5357554c0a3aSHans de Goede psta->htpriv.sgi_40m = false; 5358554c0a3aSHans de Goede psta->qos_option = false; 5359554c0a3aSHans de Goede 5360554c0a3aSHans de Goede } 5361554c0a3aSHans de Goede 5362554c0a3aSHans de Goede psta->htpriv.ch_offset = pmlmeext->cur_ch_offset; 5363554c0a3aSHans de Goede 5364554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ 5365554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ 5366554c0a3aSHans de Goede 5367554c0a3aSHans de Goede psta->bw_mode = pmlmeext->cur_bwmode; 5368554c0a3aSHans de Goede 5369554c0a3aSHans de Goede /* QoS */ 5370554c0a3aSHans de Goede if (pmlmepriv->qospriv.qos_option) 5371554c0a3aSHans de Goede psta->qos_option = true; 5372554c0a3aSHans de Goede 5373554c0a3aSHans de Goede update_ldpc_stbc_cap(psta); 5374554c0a3aSHans de Goede 5375554c0a3aSHans de Goede spin_lock_bh(&psta->lock); 5376554c0a3aSHans de Goede psta->state = _FW_LINKED; 5377554c0a3aSHans de Goede spin_unlock_bh(&psta->lock); 5378554c0a3aSHans de Goede 5379554c0a3aSHans de Goede } 5380554c0a3aSHans de Goede 5381554c0a3aSHans de Goede static void rtw_mlmeext_disconnect(struct adapter *padapter) 5382554c0a3aSHans de Goede { 5383554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 5384554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5385554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5386554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 5387554c0a3aSHans de Goede 5388554c0a3aSHans de Goede /* set_opmode_cmd(padapter, infra_client_with_mlme); */ 5389554c0a3aSHans de Goede 53904d17363dSAndreas Hellmich /* For safety, prevent from keeping macid sleep. 5391554c0a3aSHans de Goede * If we can sure all power mode enter/leave are paired, 5392554c0a3aSHans de Goede * this check can be removed. 5393554c0a3aSHans de Goede * Lucas@20131113 5394554c0a3aSHans de Goede */ 5395554c0a3aSHans de Goede /* wakeup macid after disconnect. */ 5396554c0a3aSHans de Goede { 5397554c0a3aSHans de Goede struct sta_info *psta; 5398c926f022SSimran Singhal 5399554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork)); 5400554c0a3aSHans de Goede if (psta) 5401554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 5402554c0a3aSHans de Goede } 5403554c0a3aSHans de Goede 5404554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL); 5405554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); 5406554c0a3aSHans de Goede 5407554c0a3aSHans de Goede /* set MSR to no link state -> infra. mode */ 5408554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_STATION_); 5409554c0a3aSHans de Goede 5410554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5411554c0a3aSHans de Goede 5412554c0a3aSHans de Goede /* switch to the 20M Hz mode after disconnect */ 5413554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 5414554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 5415554c0a3aSHans de Goede 5416554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 5417554c0a3aSHans de Goede 5418554c0a3aSHans de Goede flush_all_cam_entry(padapter); 5419554c0a3aSHans de Goede 5420554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 5421554c0a3aSHans de Goede 5422554c0a3aSHans de Goede /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */ 5423554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0; 5424554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0; 5425554c0a3aSHans de Goede 5426554c0a3aSHans de Goede } 5427554c0a3aSHans de Goede 5428554c0a3aSHans de Goede void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) 5429554c0a3aSHans de Goede { 5430554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5431554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5432554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 5433554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5434554c0a3aSHans de Goede u8 join_type; 5435554c0a3aSHans de Goede struct sta_info *psta; 5436c926f022SSimran Singhal 5437554c0a3aSHans de Goede if (join_res < 0) { 5438554c0a3aSHans de Goede join_type = 1; 5439554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5440554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); 5441554c0a3aSHans de Goede 5442554c0a3aSHans de Goede goto exit_mlmeext_joinbss_event_callback; 5443554c0a3aSHans de Goede } 5444554c0a3aSHans de Goede 5445554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) 5446554c0a3aSHans de Goede /* update bc/mc sta_info */ 5447554c0a3aSHans de Goede update_bmc_sta(padapter); 5448554c0a3aSHans de Goede 5449554c0a3aSHans de Goede 5450554c0a3aSHans de Goede /* turn on dynamic functions */ 5451554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); 5452554c0a3aSHans de Goede 545368468503SAndreas Hellmich /* update IOT-related issue */ 5454554c0a3aSHans de Goede update_IOT_info(padapter); 5455554c0a3aSHans de Goede 5456554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates); 5457554c0a3aSHans de Goede 5458554c0a3aSHans de Goede /* BCN interval */ 5459554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval)); 5460554c0a3aSHans de Goede 546168468503SAndreas Hellmich /* update capability */ 5462554c0a3aSHans de Goede update_capinfo(padapter, pmlmeinfo->capability); 5463554c0a3aSHans de Goede 5464554c0a3aSHans de Goede /* WMM, Update EDCA param */ 5465554c0a3aSHans de Goede WMMOnAssocRsp(padapter); 5466554c0a3aSHans de Goede 5467554c0a3aSHans de Goede /* HT */ 5468554c0a3aSHans de Goede HTOnAssocRsp(padapter); 5469554c0a3aSHans de Goede 5470554c0a3aSHans de Goede /* Set cur_channel&cur_bwmode&cur_ch_offset */ 5471554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 5472554c0a3aSHans de Goede 5473554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress); 5474554c0a3aSHans de Goede if (psta) { /* only for infra. mode */ 5475554c0a3aSHans de Goede 5476554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; 5477554c0a3aSHans de Goede 5478554c0a3aSHans de Goede /* DBG_871X("set_sta_rate\n"); */ 5479554c0a3aSHans de Goede 5480554c0a3aSHans de Goede psta->wireless_mode = pmlmeext->cur_wireless_mode; 5481554c0a3aSHans de Goede 5482554c0a3aSHans de Goede /* set per sta rate after updating HT cap. */ 5483554c0a3aSHans de Goede set_sta_rate(padapter, psta); 5484554c0a3aSHans de Goede 5485554c0a3aSHans de Goede rtw_sta_media_status_rpt(padapter, psta, 1); 5486554c0a3aSHans de Goede 5487554c0a3aSHans de Goede /* wakeup macid after join bss successfully to ensure 5488554c0a3aSHans de Goede the subsequent data frames can be sent out normally */ 5489554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 5490554c0a3aSHans de Goede } 5491554c0a3aSHans de Goede 5492554c0a3aSHans de Goede join_type = 2; 5493554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5494554c0a3aSHans de Goede 5495554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 5496554c0a3aSHans de Goede /* correcting TSF */ 5497554c0a3aSHans de Goede correct_TSF(padapter, pmlmeext); 5498554c0a3aSHans de Goede 5499554c0a3aSHans de Goede /* set_link_timer(pmlmeext, DISCONNECT_TO); */ 5500554c0a3aSHans de Goede } 5501554c0a3aSHans de Goede 5502554c0a3aSHans de Goede if (get_iface_type(padapter) == IFACE_PORT0) 5503554c0a3aSHans de Goede rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0); 5504554c0a3aSHans de Goede 5505554c0a3aSHans de Goede exit_mlmeext_joinbss_event_callback: 5506554c0a3aSHans de Goede 5507554c0a3aSHans de Goede DBG_871X("=>%s\n", __func__); 5508554c0a3aSHans de Goede 5509554c0a3aSHans de Goede } 5510554c0a3aSHans de Goede 5511554c0a3aSHans de Goede /* currently only adhoc mode will go here */ 5512554c0a3aSHans de Goede void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta) 5513554c0a3aSHans de Goede { 5514554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 5515554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5516554c0a3aSHans de Goede u8 join_type; 5517554c0a3aSHans de Goede 5518554c0a3aSHans de Goede DBG_871X("%s\n", __func__); 5519554c0a3aSHans de Goede 5520554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 5521554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */ 5522554c0a3aSHans de Goede 5523554c0a3aSHans de Goede /* nothing to do */ 5524554c0a3aSHans de Goede } else { /* adhoc client */ 5525554c0a3aSHans de Goede /* update TSF Value */ 5526554c0a3aSHans de Goede /* update_TSF(pmlmeext, pframe, len); */ 5527554c0a3aSHans de Goede 5528554c0a3aSHans de Goede /* correcting TSF */ 5529554c0a3aSHans de Goede correct_TSF(padapter, pmlmeext); 5530554c0a3aSHans de Goede 5531554c0a3aSHans de Goede /* start beacon */ 5532554c0a3aSHans de Goede if (send_beacon(padapter) == _FAIL) { 5533554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].status = 0; 5534554c0a3aSHans de Goede 5535554c0a3aSHans de Goede pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE; 5536554c0a3aSHans de Goede 5537554c0a3aSHans de Goede return; 5538554c0a3aSHans de Goede } 5539554c0a3aSHans de Goede 5540554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 5541554c0a3aSHans de Goede 5542554c0a3aSHans de Goede } 5543554c0a3aSHans de Goede 5544554c0a3aSHans de Goede join_type = 2; 5545554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5546554c0a3aSHans de Goede } 5547554c0a3aSHans de Goede 5548554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; 5549554c0a3aSHans de Goede 5550554c0a3aSHans de Goede psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates); 5551554c0a3aSHans de Goede memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen); 5552554c0a3aSHans de Goede 5553554c0a3aSHans de Goede /* update adhoc sta_info */ 5554554c0a3aSHans de Goede update_sta_info(padapter, psta); 5555554c0a3aSHans de Goede 5556554c0a3aSHans de Goede rtw_hal_update_sta_rate_mask(padapter, psta); 5557554c0a3aSHans de Goede 5558554c0a3aSHans de Goede /* ToDo: HT for Ad-hoc */ 5559554c0a3aSHans de Goede psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel); 5560777a4334SNishka Dasgupta psta->raid = networktype_to_raid_ex(padapter, psta); 5561554c0a3aSHans de Goede 5562554c0a3aSHans de Goede /* rate radaptive */ 5563554c0a3aSHans de Goede Update_RA_Entry(padapter, psta); 5564554c0a3aSHans de Goede } 5565554c0a3aSHans de Goede 5566554c0a3aSHans de Goede void mlmeext_sta_del_event_callback(struct adapter *padapter) 5567554c0a3aSHans de Goede { 5568554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) 5569554c0a3aSHans de Goede rtw_mlmeext_disconnect(padapter); 5570554c0a3aSHans de Goede } 5571554c0a3aSHans de Goede 5572554c0a3aSHans de Goede /**************************************************************************** 5573554c0a3aSHans de Goede 5574554c0a3aSHans de Goede Following are the functions for the timer handlers 5575554c0a3aSHans de Goede 5576554c0a3aSHans de Goede *****************************************************************************/ 5577554c0a3aSHans de Goede void _linked_info_dump(struct adapter *padapter) 5578554c0a3aSHans de Goede { 5579554c0a3aSHans de Goede int i; 5580554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5581554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5582554c0a3aSHans de Goede int UndecoratedSmoothedPWDB; 5583554c0a3aSHans de Goede struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); 5584554c0a3aSHans de Goede 5585554c0a3aSHans de Goede if (padapter->bLinkInfoDump) { 5586554c0a3aSHans de Goede 5587d0cc39cdSRoss Schmidt DBG_871X("\n ============[%s] linked status check ===================\n", ADPT_ARG(padapter)); 5588554c0a3aSHans de Goede 5589554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 5590554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB); 5591554c0a3aSHans de Goede 5592bbda3ac4SRoss Schmidt DBG_871X("AP[%pM] - UndecoratedSmoothedPWDB:%d\n", 5593554c0a3aSHans de Goede MAC_ARG(padapter->mlmepriv.cur_network.network.MacAddress), UndecoratedSmoothedPWDB); 5594554c0a3aSHans de Goede } else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_) { 5595554c0a3aSHans de Goede struct list_head *phead, *plist; 5596554c0a3aSHans de Goede 5597554c0a3aSHans de Goede struct sta_info *psta = NULL; 5598554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5599554c0a3aSHans de Goede 5600554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 5601554c0a3aSHans de Goede phead = &pstapriv->asoc_list; 5602554c0a3aSHans de Goede plist = get_next(phead); 5603554c0a3aSHans de Goede while (phead != plist) { 560419cf9d7aSRoss Schmidt psta = container_of(plist, struct sta_info, asoc_list); 5605554c0a3aSHans de Goede plist = get_next(plist); 5606554c0a3aSHans de Goede 5607bbda3ac4SRoss Schmidt DBG_871X("STA[%pM]:UndecoratedSmoothedPWDB:%d\n", 5608554c0a3aSHans de Goede MAC_ARG(psta->hwaddr), psta->rssi_stat.UndecoratedSmoothedPWDB); 5609554c0a3aSHans de Goede } 5610554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 5611554c0a3aSHans de Goede 5612554c0a3aSHans de Goede } 5613554c0a3aSHans de Goede for (i = 0; i < NUM_STA; i++) { 56140ad02fa8SGeorgiana Chelu if (pdvobj->macid[i]) { 5615554c0a3aSHans de Goede if (i != 1) /* skip bc/mc sta */ 5616554c0a3aSHans de Goede /* tx info ============ */ 5617554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i); 5618554c0a3aSHans de Goede } 5619554c0a3aSHans de Goede } 5620554c0a3aSHans de Goede rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL); 5621554c0a3aSHans de Goede 5622554c0a3aSHans de Goede 5623554c0a3aSHans de Goede } 5624554c0a3aSHans de Goede 5625554c0a3aSHans de Goede 5626554c0a3aSHans de Goede } 5627554c0a3aSHans de Goede 5628554c0a3aSHans de Goede static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta) 5629554c0a3aSHans de Goede { 5630554c0a3aSHans de Goede u8 ret = false; 5631554c0a3aSHans de Goede 5632554c0a3aSHans de Goede #ifdef DBG_EXPIRATION_CHK 5633554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu" 5634554c0a3aSHans de Goede /*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/ 5635554c0a3aSHans de Goede ", retry:%u\n" 5636554c0a3aSHans de Goede , FUNC_ADPT_ARG(padapter) 5637554c0a3aSHans de Goede , STA_RX_PKTS_DIFF_ARG(psta) 5638554c0a3aSHans de Goede , psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts 5639554c0a3aSHans de Goede , psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts 5640554c0a3aSHans de Goede /*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts 5641554c0a3aSHans de Goede , psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts 5642554c0a3aSHans de Goede , psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts 5643554c0a3aSHans de Goede , pmlmeinfo->bcn_interval*/ 5644554c0a3aSHans de Goede , pmlmeext->retry 5645554c0a3aSHans de Goede ); 5646554c0a3aSHans de Goede 5647554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter) 5648554c0a3aSHans de Goede , padapter->xmitpriv.tx_pkts 5649554c0a3aSHans de Goede , pmlmeinfo->link_count 5650554c0a3aSHans de Goede ); 5651554c0a3aSHans de Goede #endif 5652554c0a3aSHans de Goede 5653554c0a3aSHans de Goede if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) 5654554c0a3aSHans de Goede && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) 5655554c0a3aSHans de Goede && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta) 5656554c0a3aSHans de Goede ) { 5657554c0a3aSHans de Goede ret = false; 5658554c0a3aSHans de Goede } else { 5659554c0a3aSHans de Goede ret = true; 5660554c0a3aSHans de Goede } 5661554c0a3aSHans de Goede 5662554c0a3aSHans de Goede sta_update_last_rx_pkts(psta); 5663554c0a3aSHans de Goede 5664554c0a3aSHans de Goede return ret; 5665554c0a3aSHans de Goede } 5666554c0a3aSHans de Goede 5667554c0a3aSHans de Goede void linked_status_chk(struct adapter *padapter) 5668554c0a3aSHans de Goede { 5669554c0a3aSHans de Goede u32 i; 5670554c0a3aSHans de Goede struct sta_info *psta; 5671554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 5672554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5673554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5674554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5675554c0a3aSHans de Goede 5676554c0a3aSHans de Goede 5677554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter)) { 5678554c0a3aSHans de Goede /* linked infrastructure client mode */ 5679554c0a3aSHans de Goede 5680554c0a3aSHans de Goede int tx_chk = _SUCCESS, rx_chk = _SUCCESS; 5681554c0a3aSHans de Goede int rx_chk_limit; 5682554c0a3aSHans de Goede int link_count_limit; 5683554c0a3aSHans de Goede 5684554c0a3aSHans de Goede #if defined(DBG_ROAMING_TEST) 5685554c0a3aSHans de Goede rx_chk_limit = 1; 5686554c0a3aSHans de Goede #else 5687554c0a3aSHans de Goede rx_chk_limit = 8; 5688554c0a3aSHans de Goede #endif 5689554c0a3aSHans de Goede link_count_limit = 7; /* 16 sec */ 5690554c0a3aSHans de Goede 5691554c0a3aSHans de Goede /* Marked by Kurt 20130715 */ 5692554c0a3aSHans de Goede /* 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. */ 5693554c0a3aSHans de Goede /* todo: To check why we under miracast session, rx_chk would be false */ 5694554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress); 569534557e23SIzabela Bakollari if (psta) { 5696554c0a3aSHans de Goede if (chk_ap_is_alive(padapter, psta) == false) 5697554c0a3aSHans de Goede rx_chk = _FAIL; 5698554c0a3aSHans de Goede 5699554c0a3aSHans de Goede if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts) 5700554c0a3aSHans de Goede tx_chk = _FAIL; 5701554c0a3aSHans de Goede 5702554c0a3aSHans de Goede { 5703554c0a3aSHans de Goede if (rx_chk != _SUCCESS) { 5704554c0a3aSHans de Goede if (pmlmeext->retry == 0) { 5705554c0a3aSHans de Goede #ifdef DBG_EXPIRATION_CHK 5706554c0a3aSHans de Goede DBG_871X("issue_probereq to trigger probersp, retry =%d\n", pmlmeext->retry); 5707554c0a3aSHans de Goede #endif 5708554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5709554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5710554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5711554c0a3aSHans de Goede } 5712554c0a3aSHans de Goede } 5713554c0a3aSHans de Goede 5714554c0a3aSHans de Goede if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) { 5715554c0a3aSHans de Goede #ifdef DBG_EXPIRATION_CHK 5716554c0a3aSHans de Goede DBG_871X("%s issue_nulldata 0\n", __func__); 5717554c0a3aSHans de Goede #endif 5718554c0a3aSHans de Goede tx_chk = issue_nulldata_in_interrupt(padapter, NULL); 5719554c0a3aSHans de Goede } 5720554c0a3aSHans de Goede } 5721554c0a3aSHans de Goede 5722554c0a3aSHans de Goede if (rx_chk == _FAIL) { 5723554c0a3aSHans de Goede pmlmeext->retry++; 5724554c0a3aSHans de Goede if (pmlmeext->retry > rx_chk_limit) { 5725554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n", 5726554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter)); 5727554c0a3aSHans de Goede receive_disconnect(padapter, pmlmeinfo->network.MacAddress 5728554c0a3aSHans de Goede , WLAN_REASON_EXPIRATION_CHK); 5729554c0a3aSHans de Goede return; 5730554c0a3aSHans de Goede } 5731554c0a3aSHans de Goede } else { 5732554c0a3aSHans de Goede pmlmeext->retry = 0; 5733554c0a3aSHans de Goede } 5734554c0a3aSHans de Goede 5735554c0a3aSHans de Goede if (tx_chk == _FAIL) { 5736554c0a3aSHans de Goede pmlmeinfo->link_count %= (link_count_limit+1); 5737554c0a3aSHans de Goede } else { 5738554c0a3aSHans de Goede pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts; 5739554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 5740554c0a3aSHans de Goede } 5741554c0a3aSHans de Goede 5742554c0a3aSHans de Goede } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */ 5743554c0a3aSHans de Goede } else if (is_client_associated_to_ibss(padapter)) { 5744554c0a3aSHans de Goede /* linked IBSS mode */ 5745554c0a3aSHans de Goede /* for each assoc list entry to check the rx pkt counter */ 5746554c0a3aSHans de Goede for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { 5747554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].status == 1) { 5748554c0a3aSHans de Goede psta = pmlmeinfo->FW_sta_info[i].psta; 5749554c0a3aSHans de Goede 5750554c0a3aSHans de Goede if (NULL == psta) 5751554c0a3aSHans de Goede continue; 5752554c0a3aSHans de Goede 5753554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) { 5754554c0a3aSHans de Goede 5755554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].retry < 3) { 5756554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry++; 5757554c0a3aSHans de Goede } else { 5758554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry = 0; 5759554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].status = 0; 5760554c0a3aSHans de Goede report_del_sta_event(padapter, psta->hwaddr 5761554c0a3aSHans de Goede , 65535/* indicate disconnect caused by no rx */ 5762554c0a3aSHans de Goede ); 5763554c0a3aSHans de Goede } 5764554c0a3aSHans de Goede } else { 5765554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry = 0; 5766554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta); 5767554c0a3aSHans de Goede } 5768554c0a3aSHans de Goede } 5769554c0a3aSHans de Goede } 5770554c0a3aSHans de Goede 5771554c0a3aSHans de Goede /* set_link_timer(pmlmeext, DISCONNECT_TO); */ 5772554c0a3aSHans de Goede 5773554c0a3aSHans de Goede } 5774554c0a3aSHans de Goede 5775554c0a3aSHans de Goede } 5776554c0a3aSHans de Goede 5777e8b1844aSKees Cook void survey_timer_hdl(struct timer_list *t) 5778554c0a3aSHans de Goede { 5779e8b1844aSKees Cook struct adapter *padapter = 5780e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.survey_timer); 5781554c0a3aSHans de Goede struct cmd_obj *ph2c; 5782554c0a3aSHans de Goede struct sitesurvey_parm *psurveyPara; 5783554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5784554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5785554c0a3aSHans de Goede 5786554c0a3aSHans de Goede /* DBG_871X("marc: survey timer\n"); */ 5787554c0a3aSHans de Goede 5788554c0a3aSHans de Goede /* issue rtw_sitesurvey_cmd */ 5789554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state > SCAN_START) { 5790554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 5791554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx++; 5792554c0a3aSHans de Goede } 5793554c0a3aSHans de Goede 57940ad02fa8SGeorgiana Chelu if (pmlmeext->scan_abort) { 5795554c0a3aSHans de Goede { 5796554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num; 5797554c0a3aSHans de Goede DBG_871X("%s idx:%d\n", __func__ 5798554c0a3aSHans de Goede , pmlmeext->sitesurvey_res.channel_idx 5799554c0a3aSHans de Goede ); 5800554c0a3aSHans de Goede } 5801554c0a3aSHans de Goede 5802554c0a3aSHans de Goede pmlmeext->scan_abort = false;/* reset */ 5803554c0a3aSHans de Goede } 5804554c0a3aSHans de Goede 58052ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 5806554c0a3aSHans de Goede if (ph2c == NULL) { 5807554c0a3aSHans de Goede goto exit_survey_timer_hdl; 5808554c0a3aSHans de Goede } 5809554c0a3aSHans de Goede 58102ef2b7c2SJoe Perches psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm)); 5811554c0a3aSHans de Goede if (psurveyPara == NULL) { 58128f24f505SMadhumitha Prabakaran kfree(ph2c); 5813554c0a3aSHans de Goede goto exit_survey_timer_hdl; 5814554c0a3aSHans de Goede } 5815554c0a3aSHans de Goede 5816554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); 5817554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, ph2c); 5818554c0a3aSHans de Goede } 5819554c0a3aSHans de Goede 5820554c0a3aSHans de Goede 5821554c0a3aSHans de Goede exit_survey_timer_hdl: 5822554c0a3aSHans de Goede 5823554c0a3aSHans de Goede return; 5824554c0a3aSHans de Goede } 5825554c0a3aSHans de Goede 5826e8b1844aSKees Cook void link_timer_hdl(struct timer_list *t) 5827554c0a3aSHans de Goede { 5828e8b1844aSKees Cook struct adapter *padapter = 5829e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.link_timer); 5830554c0a3aSHans de Goede /* static unsigned int rx_pkt = 0; */ 5831554c0a3aSHans de Goede /* static u64 tx_cnt = 0; */ 5832554c0a3aSHans de Goede /* struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); */ 5833554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5834554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5835554c0a3aSHans de Goede /* struct sta_priv *pstapriv = &padapter->stapriv; */ 5836554c0a3aSHans de Goede 5837554c0a3aSHans de Goede 5838554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { 5839554c0a3aSHans de Goede DBG_871X("link_timer_hdl:no beacon while connecting\n"); 5840554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5841554c0a3aSHans de Goede report_join_res(padapter, -3); 5842554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) { 5843554c0a3aSHans de Goede /* re-auth timer */ 5844554c0a3aSHans de Goede if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) { 5845554c0a3aSHans de Goede /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */ 5846554c0a3aSHans de Goede /* */ 5847554c0a3aSHans de Goede pmlmeinfo->state = 0; 5848554c0a3aSHans de Goede report_join_res(padapter, -1); 5849554c0a3aSHans de Goede return; 5850554c0a3aSHans de Goede /* */ 5851554c0a3aSHans de Goede /* else */ 5852554c0a3aSHans de Goede /* */ 5853554c0a3aSHans de Goede /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */ 5854554c0a3aSHans de Goede /* pmlmeinfo->reauth_count = 0; */ 5855554c0a3aSHans de Goede /* */ 5856554c0a3aSHans de Goede } 5857554c0a3aSHans de Goede 5858554c0a3aSHans de Goede DBG_871X("link_timer_hdl: auth timeout and try again\n"); 5859554c0a3aSHans de Goede pmlmeinfo->auth_seq = 1; 5860554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 5861554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 5862554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) { 5863554c0a3aSHans de Goede /* re-assoc timer */ 5864554c0a3aSHans de Goede if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) { 5865554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5866554c0a3aSHans de Goede report_join_res(padapter, -2); 5867554c0a3aSHans de Goede return; 5868554c0a3aSHans de Goede } 5869554c0a3aSHans de Goede 5870554c0a3aSHans de Goede DBG_871X("link_timer_hdl: assoc timeout and try again\n"); 5871554c0a3aSHans de Goede issue_assocreq(padapter); 5872554c0a3aSHans de Goede set_link_timer(pmlmeext, REASSOC_TO); 5873554c0a3aSHans de Goede } 5874554c0a3aSHans de Goede } 5875554c0a3aSHans de Goede 5876e8b1844aSKees Cook void addba_timer_hdl(struct timer_list *t) 5877554c0a3aSHans de Goede { 5878e8b1844aSKees Cook struct sta_info *psta = from_timer(psta, t, addba_retry_timer); 5879554c0a3aSHans de Goede struct ht_priv *phtpriv; 5880554c0a3aSHans de Goede 5881554c0a3aSHans de Goede if (!psta) 5882554c0a3aSHans de Goede return; 5883554c0a3aSHans de Goede 5884554c0a3aSHans de Goede phtpriv = &psta->htpriv; 5885554c0a3aSHans de Goede 58860ad02fa8SGeorgiana Chelu if (phtpriv->ht_option && phtpriv->ampdu_enable) { 5887554c0a3aSHans de Goede if (phtpriv->candidate_tid_bitmap) 5888554c0a3aSHans de Goede phtpriv->candidate_tid_bitmap = 0x0; 5889554c0a3aSHans de Goede 5890554c0a3aSHans de Goede } 5891554c0a3aSHans de Goede } 5892554c0a3aSHans de Goede 5893e8b1844aSKees Cook void sa_query_timer_hdl(struct timer_list *t) 5894554c0a3aSHans de Goede { 5895e8b1844aSKees Cook struct adapter *padapter = 5896e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.sa_query_timer); 5897554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 5898554c0a3aSHans de Goede /* disconnect */ 5899554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 5900554c0a3aSHans de Goede 59010ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, _FW_LINKED)) { 5902554c0a3aSHans de Goede rtw_disassoc_cmd(padapter, 0, true); 5903554c0a3aSHans de Goede rtw_indicate_disconnect(padapter); 5904554c0a3aSHans de Goede rtw_free_assoc_resources(padapter, 1); 5905554c0a3aSHans de Goede } 5906554c0a3aSHans de Goede 5907554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 5908554c0a3aSHans de Goede DBG_871X("SA query timeout disconnect\n"); 5909554c0a3aSHans de Goede } 5910554c0a3aSHans de Goede 5911554c0a3aSHans de Goede u8 NULL_hdl(struct adapter *padapter, u8 *pbuf) 5912554c0a3aSHans de Goede { 5913554c0a3aSHans de Goede return H2C_SUCCESS; 5914554c0a3aSHans de Goede } 5915554c0a3aSHans de Goede 5916554c0a3aSHans de Goede #ifdef CONFIG_AUTO_AP_MODE 5917554c0a3aSHans de Goede static int rtw_auto_ap_start_beacon(struct adapter *adapter) 5918554c0a3aSHans de Goede { 5919554c0a3aSHans de Goede int ret = 0; 5920554c0a3aSHans de Goede u8 *pbuf = NULL; 5921554c0a3aSHans de Goede uint len; 5922554c0a3aSHans de Goede u8 supportRate[16]; 5923554c0a3aSHans de Goede int sz = 0, rateLen; 5924554c0a3aSHans de Goede u8 *ie; 5925554c0a3aSHans de Goede u8 wireless_mode, oper_channel; 5926554c0a3aSHans de Goede u8 ssid[3] = {0}; /* hidden ssid */ 5927554c0a3aSHans de Goede u32 ssid_len = sizeof(ssid); 5928554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(adapter->mlmepriv); 5929554c0a3aSHans de Goede 5930554c0a3aSHans de Goede 5931554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_AP_STATE) != true) 5932554c0a3aSHans de Goede return -EINVAL; 5933554c0a3aSHans de Goede 5934554c0a3aSHans de Goede 5935554c0a3aSHans de Goede len = 128; 5936554c0a3aSHans de Goede pbuf = rtw_zmalloc(len); 5937554c0a3aSHans de Goede if (!pbuf) 5938554c0a3aSHans de Goede return -ENOMEM; 5939554c0a3aSHans de Goede 5940554c0a3aSHans de Goede 5941554c0a3aSHans de Goede /* generate beacon */ 5942554c0a3aSHans de Goede ie = pbuf; 5943554c0a3aSHans de Goede 5944554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 5945554c0a3aSHans de Goede sz += 8; 5946554c0a3aSHans de Goede ie += sz; 5947554c0a3aSHans de Goede 5948554c0a3aSHans de Goede /* beacon interval : 2bytes */ 5949554c0a3aSHans de Goede *(u16 *)ie = cpu_to_le16((u16)100);/* BCN_INTERVAL = 100; */ 5950554c0a3aSHans de Goede sz += 2; 5951554c0a3aSHans de Goede ie += 2; 5952554c0a3aSHans de Goede 5953554c0a3aSHans de Goede /* capability info */ 5954554c0a3aSHans de Goede *(u16 *)ie = 0; 59552415ae7fSRoss Schmidt *(u16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_ESS); 59562415ae7fSRoss Schmidt *(u16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); 59572415ae7fSRoss Schmidt /* u16*)ie |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); */ 5958554c0a3aSHans de Goede sz += 2; 5959554c0a3aSHans de Goede ie += 2; 5960554c0a3aSHans de Goede 5961554c0a3aSHans de Goede /* SSID */ 59623f15277bSRoss Schmidt ie = rtw_set_ie(ie, WLAN_EID_SSID, ssid_len, ssid, &sz); 5963554c0a3aSHans de Goede 5964554c0a3aSHans de Goede /* supported rates */ 5965554c0a3aSHans de Goede wireless_mode = WIRELESS_11BG_24N; 5966554c0a3aSHans de Goede rtw_set_supported_rate(supportRate, wireless_mode); 5967554c0a3aSHans de Goede rateLen = rtw_get_rateset_len(supportRate); 5968554c0a3aSHans de Goede if (rateLen > 8) { 5969c34c45edSRoss Schmidt ie = rtw_set_ie(ie, WLAN_EID_SUPP_RATES, 8, supportRate, &sz); 5970554c0a3aSHans de Goede } else { 5971c34c45edSRoss Schmidt ie = rtw_set_ie(ie, WLAN_EID_SUPP_RATES, rateLen, supportRate, &sz); 5972554c0a3aSHans de Goede } 5973554c0a3aSHans de Goede 5974554c0a3aSHans de Goede 5975554c0a3aSHans de Goede /* DS parameter set */ 5976554c0a3aSHans de Goede if (check_buddy_fwstate(adapter, _FW_LINKED) && 5977554c0a3aSHans de Goede check_buddy_fwstate(adapter, WIFI_STATION_STATE)) { 5978554c0a3aSHans de Goede struct adapter *pbuddystruct adapter = adapter->pbuddystruct adapter; 5979554c0a3aSHans de Goede struct mlme_ext_priv *pbuddy_mlmeext = &pbuddystruct adapter->mlmeextpriv; 5980554c0a3aSHans de Goede 5981554c0a3aSHans de Goede oper_channel = pbuddy_mlmeext->cur_channel; 5982554c0a3aSHans de Goede } else { 5983554c0a3aSHans de Goede oper_channel = adapter_to_dvobj(adapter)->oper_channel; 5984554c0a3aSHans de Goede } 59858f6a9446SRoss Schmidt ie = rtw_set_ie(ie, WLAN_EID_DS_PARAMS, 1, &oper_channel, &sz); 5986554c0a3aSHans de Goede 5987554c0a3aSHans de Goede /* ext supported rates */ 5988554c0a3aSHans de Goede if (rateLen > 8) { 5989554c0a3aSHans de Goede ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz); 5990554c0a3aSHans de Goede } 5991554c0a3aSHans de Goede 5992554c0a3aSHans de Goede DBG_871X("%s, start auto ap beacon sz =%d\n", __func__, sz); 5993554c0a3aSHans de Goede 5994554c0a3aSHans de Goede /* lunch ap mode & start to issue beacon */ 5995554c0a3aSHans de Goede if (rtw_check_beacon_data(adapter, pbuf, sz) == _SUCCESS) { 5996554c0a3aSHans de Goede 5997554c0a3aSHans de Goede } else { 5998554c0a3aSHans de Goede ret = -EINVAL; 5999554c0a3aSHans de Goede } 6000554c0a3aSHans de Goede 6001554c0a3aSHans de Goede 6002554c0a3aSHans de Goede kfree(pbuf); 6003554c0a3aSHans de Goede 6004554c0a3aSHans de Goede return ret; 6005554c0a3aSHans de Goede 6006554c0a3aSHans de Goede } 6007554c0a3aSHans de Goede #endif/* CONFIG_AUTO_AP_MODE */ 6008554c0a3aSHans de Goede 6009554c0a3aSHans de Goede u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) 6010554c0a3aSHans de Goede { 6011554c0a3aSHans de Goede u8 type; 6012554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6013554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6014554c0a3aSHans de Goede struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf; 6015554c0a3aSHans de Goede 6016554c0a3aSHans de Goede if (psetop->mode == Ndis802_11APMode) { 6017554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_AP_STATE; 6018554c0a3aSHans de Goede type = _HW_STATE_AP_; 6019554c0a3aSHans de Goede /* start_ap_mode(padapter); */ 6020554c0a3aSHans de Goede } else if (psetop->mode == Ndis802_11Infrastructure) { 6021554c0a3aSHans de Goede pmlmeinfo->state &= ~(BIT(0)|BIT(1));/* clear state */ 6022554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */ 6023554c0a3aSHans de Goede type = _HW_STATE_STATION_; 6024554c0a3aSHans de Goede } else if (psetop->mode == Ndis802_11IBSS) { 6025554c0a3aSHans de Goede type = _HW_STATE_ADHOC_; 6026554c0a3aSHans de Goede } else { 6027554c0a3aSHans de Goede type = _HW_STATE_NOLINK_; 6028554c0a3aSHans de Goede } 6029554c0a3aSHans de Goede 6030554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type)); 6031eb569cc0SNishka Dasgupta /* Set_MSR(padapter, type); */ 6032554c0a3aSHans de Goede 6033554c0a3aSHans de Goede 6034554c0a3aSHans de Goede #ifdef CONFIG_AUTO_AP_MODE 6035554c0a3aSHans de Goede if (psetop->mode == Ndis802_11APMode) 6036554c0a3aSHans de Goede rtw_auto_ap_start_beacon(padapter); 6037554c0a3aSHans de Goede #endif 6038554c0a3aSHans de Goede 6039554c0a3aSHans de Goede if (psetop->mode == Ndis802_11APMode) { 6040554c0a3aSHans de Goede /* Do this after port switch to */ 6041554c0a3aSHans de Goede /* prevent from downloading rsvd page to wrong port */ 6042554c0a3aSHans de Goede rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */ 6043554c0a3aSHans de Goede } 6044554c0a3aSHans de Goede 6045554c0a3aSHans de Goede return H2C_SUCCESS; 6046554c0a3aSHans de Goede 6047554c0a3aSHans de Goede } 6048554c0a3aSHans de Goede 6049554c0a3aSHans de Goede u8 createbss_hdl(struct adapter *padapter, u8 *pbuf) 6050554c0a3aSHans de Goede { 6051554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6052554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6053554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 6054554c0a3aSHans de Goede struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf; 6055554c0a3aSHans de Goede /* u32 initialgain; */ 6056554c0a3aSHans de Goede 6057554c0a3aSHans de Goede if (pmlmeinfo->state == WIFI_FW_AP_STATE) { 6058554c0a3aSHans de Goede struct wlan_bssid_ex *network = &padapter->mlmepriv.cur_network.network; 6059c926f022SSimran Singhal 6060554c0a3aSHans de Goede start_bss_network(padapter, (u8 *)network); 6061554c0a3aSHans de Goede return H2C_SUCCESS; 6062554c0a3aSHans de Goede } 6063554c0a3aSHans de Goede 6064554c0a3aSHans de Goede /* below is for ad-hoc master */ 6065554c0a3aSHans de Goede if (pparm->network.InfrastructureMode == Ndis802_11IBSS) { 6066554c0a3aSHans de Goede rtw_joinbss_reset(padapter); 6067554c0a3aSHans de Goede 6068554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 6069554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 6070554c0a3aSHans de Goede pmlmeinfo->ERP_enable = 0; 6071554c0a3aSHans de Goede pmlmeinfo->WMM_enable = 0; 6072554c0a3aSHans de Goede pmlmeinfo->HT_enable = 0; 6073554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 0; 6074554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 0; 6075554c0a3aSHans de Goede pmlmeinfo->agg_enable_bitmap = 0; 6076554c0a3aSHans de Goede pmlmeinfo->candidate_tid_bitmap = 0; 6077554c0a3aSHans de Goede 6078554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 6079554c0a3aSHans de Goede Save_DM_Func_Flag(padapter); 6080554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); 6081554c0a3aSHans de Goede 6082554c0a3aSHans de Goede /* config the initial gain under linking, need to write the BB registers */ 6083554c0a3aSHans de Goede /* initialgain = 0x1E; */ 6084554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */ 6085554c0a3aSHans de Goede 6086554c0a3aSHans de Goede /* cancel link timer */ 6087554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 6088554c0a3aSHans de Goede 6089554c0a3aSHans de Goede /* clear CAM */ 6090554c0a3aSHans de Goede flush_all_cam_entry(padapter); 6091554c0a3aSHans de Goede 6092554c0a3aSHans de Goede memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength)); 6093554c0a3aSHans de Goede pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength; 6094554c0a3aSHans de Goede 6095554c0a3aSHans de Goede if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ 6096554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6097554c0a3aSHans de Goede 6098554c0a3aSHans de Goede memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength); 6099554c0a3aSHans de Goede 6100554c0a3aSHans de Goede start_create_ibss(padapter); 6101554c0a3aSHans de Goede 6102554c0a3aSHans de Goede } 6103554c0a3aSHans de Goede 6104554c0a3aSHans de Goede return H2C_SUCCESS; 6105554c0a3aSHans de Goede 6106554c0a3aSHans de Goede } 6107554c0a3aSHans de Goede 6108554c0a3aSHans de Goede u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf) 6109554c0a3aSHans de Goede { 6110554c0a3aSHans de Goede u8 join_type; 6111554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 6112554c0a3aSHans de Goede struct registry_priv *pregpriv = &padapter->registrypriv; 6113554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6114554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6115554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 6116554c0a3aSHans de Goede u32 i; 6117554c0a3aSHans de Goede u8 cbw40_enable = 0; 6118554c0a3aSHans de Goede /* u32 initialgain; */ 6119554c0a3aSHans de Goede /* u32 acparm; */ 6120554c0a3aSHans de Goede u8 ch, bw, offset; 6121554c0a3aSHans de Goede 6122554c0a3aSHans de Goede /* check already connecting to AP or not */ 6123554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { 6124554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_STATION_STATE) { 6125554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); 6126554c0a3aSHans de Goede } 6127554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 6128554c0a3aSHans de Goede 6129554c0a3aSHans de Goede /* clear CAM */ 6130554c0a3aSHans de Goede flush_all_cam_entry(padapter); 6131554c0a3aSHans de Goede 6132554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 6133554c0a3aSHans de Goede 6134554c0a3aSHans de Goede /* set MSR to nolink -> infra. mode */ 6135554c0a3aSHans de Goede /* Set_MSR(padapter, _HW_STATE_NOLINK_); */ 6136554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_STATION_); 6137554c0a3aSHans de Goede 6138554c0a3aSHans de Goede 6139554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL); 6140554c0a3aSHans de Goede } 6141554c0a3aSHans de Goede 6142554c0a3aSHans de Goede rtw_joinbss_reset(padapter); 6143554c0a3aSHans de Goede 6144554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 6145554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 6146554c0a3aSHans de Goede pmlmeinfo->ERP_enable = 0; 6147554c0a3aSHans de Goede pmlmeinfo->WMM_enable = 0; 6148554c0a3aSHans de Goede pmlmeinfo->HT_enable = 0; 6149554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 0; 6150554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 0; 6151554c0a3aSHans de Goede pmlmeinfo->agg_enable_bitmap = 0; 6152554c0a3aSHans de Goede pmlmeinfo->candidate_tid_bitmap = 0; 6153554c0a3aSHans de Goede pmlmeinfo->bwmode_updated = false; 6154554c0a3aSHans de Goede /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */ 6155554c0a3aSHans de Goede pmlmeinfo->VHT_enable = 0; 6156554c0a3aSHans de Goede 6157554c0a3aSHans de Goede memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength)); 6158554c0a3aSHans de Goede pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength; 6159554c0a3aSHans de Goede 6160554c0a3aSHans de Goede if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ 6161554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6162554c0a3aSHans de Goede 6163554c0a3aSHans de Goede memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength); 6164554c0a3aSHans de Goede 6165554c0a3aSHans de Goede pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; 6166554c0a3aSHans de Goede pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); 6167554c0a3aSHans de Goede 6168554c0a3aSHans de Goede /* Check AP vendor to move rtw_joinbss_cmd() */ 6169554c0a3aSHans de Goede /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */ 6170554c0a3aSHans de Goede 6171554c0a3aSHans de Goede /* sizeof(struct ndis_802_11_fix_ie) */ 6172554c0a3aSHans de Goede for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) { 6173554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pnetwork->IEs + i); 6174554c0a3aSHans de Goede 6175554c0a3aSHans de Goede switch (pIE->ElementID) { 6176b05cc3a9SRoss Schmidt case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */ 6177554c0a3aSHans de Goede if (!memcmp(pIE->data, WMM_OUI, 4)) 6178554c0a3aSHans de Goede WMM_param_handler(padapter, pIE); 6179554c0a3aSHans de Goede break; 6180554c0a3aSHans de Goede 6181fc6a6528SRoss Schmidt case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */ 6182554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 1; 6183554c0a3aSHans de Goede break; 6184554c0a3aSHans de Goede 6185332ec9dbSRoss Schmidt case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */ 6186554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 1; 6187554c0a3aSHans de Goede 6188554c0a3aSHans de Goede /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */ 6189554c0a3aSHans de Goede { 6190554c0a3aSHans de Goede struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data); 6191554c0a3aSHans de Goede 6192554c0a3aSHans de Goede if (pnetwork->Configuration.DSConfig > 14) { 6193554c0a3aSHans de Goede if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20) 6194554c0a3aSHans de Goede cbw40_enable = 1; 6195554c0a3aSHans de Goede } else { 6196554c0a3aSHans de Goede if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20) 6197554c0a3aSHans de Goede cbw40_enable = 1; 6198554c0a3aSHans de Goede } 6199554c0a3aSHans de Goede 6200554c0a3aSHans de Goede if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) { 6201554c0a3aSHans de Goede /* switch to the 40M Hz mode according to the AP */ 6202554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_40; 6203554c0a3aSHans de Goede switch (pht_info->infos[0] & 0x3) { 6204554c0a3aSHans de Goede case 1: 6205554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; 6206554c0a3aSHans de Goede break; 6207554c0a3aSHans de Goede 6208554c0a3aSHans de Goede case 3: 6209554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; 6210554c0a3aSHans de Goede break; 6211554c0a3aSHans de Goede 6212554c0a3aSHans de Goede default: 6213554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 6214554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 6215554c0a3aSHans de Goede break; 6216554c0a3aSHans de Goede } 6217554c0a3aSHans de Goede 6218554c0a3aSHans de Goede DBG_871X("set HT ch/bw before connected\n"); 6219554c0a3aSHans de Goede } 6220554c0a3aSHans de Goede } 6221554c0a3aSHans de Goede break; 6222554c0a3aSHans de Goede default: 6223554c0a3aSHans de Goede break; 6224554c0a3aSHans de Goede } 6225554c0a3aSHans de Goede 6226554c0a3aSHans de Goede i += (pIE->Length + 2); 6227554c0a3aSHans de Goede } 6228554c0a3aSHans de Goede 6229554c0a3aSHans de Goede /* check channel, bandwidth, offset and switch */ 6230554c0a3aSHans de Goede if (rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) { 6231554c0a3aSHans de Goede report_join_res(padapter, (-4)); 6232554c0a3aSHans de Goede return H2C_SUCCESS; 6233554c0a3aSHans de Goede } 6234554c0a3aSHans de Goede 6235554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 6236554c0a3aSHans de Goede /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */ 6237554c0a3aSHans de Goede 6238554c0a3aSHans de Goede /* config the initial gain under linking, need to write the BB registers */ 6239554c0a3aSHans de Goede /* initialgain = 0x1E; */ 6240554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */ 6241554c0a3aSHans de Goede 6242554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress); 6243554c0a3aSHans de Goede join_type = 0; 6244554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 6245554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL); 6246554c0a3aSHans de Goede 6247554c0a3aSHans de Goede set_channel_bwmode(padapter, ch, offset, bw); 6248554c0a3aSHans de Goede 6249554c0a3aSHans de Goede /* cancel link timer */ 6250554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 6251554c0a3aSHans de Goede 6252554c0a3aSHans de Goede start_clnt_join(padapter); 6253554c0a3aSHans de Goede 6254554c0a3aSHans de Goede return H2C_SUCCESS; 6255554c0a3aSHans de Goede 6256554c0a3aSHans de Goede } 6257554c0a3aSHans de Goede 6258554c0a3aSHans de Goede u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf) 6259554c0a3aSHans de Goede { 6260554c0a3aSHans de Goede struct disconnect_parm *param = (struct disconnect_parm *)pbuf; 6261554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6262554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6263554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 6264554c0a3aSHans de Goede u8 val8; 6265554c0a3aSHans de Goede 6266554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter)) { 6267554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100); 6268554c0a3aSHans de Goede } 6269554c0a3aSHans de Goede 6270554c0a3aSHans de Goede if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) { 6271554c0a3aSHans de Goede /* Stop BCN */ 6272554c0a3aSHans de Goede val8 = 0; 6273554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8)); 6274554c0a3aSHans de Goede } 6275554c0a3aSHans de Goede 6276554c0a3aSHans de Goede rtw_mlmeext_disconnect(padapter); 6277554c0a3aSHans de Goede 6278554c0a3aSHans de Goede rtw_free_uc_swdec_pending_queue(padapter); 6279554c0a3aSHans de Goede 6280554c0a3aSHans de Goede return H2C_SUCCESS; 6281554c0a3aSHans de Goede } 6282554c0a3aSHans de Goede 6283554c0a3aSHans de Goede static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out, 6284554c0a3aSHans de Goede u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num) 6285554c0a3aSHans de Goede { 6286554c0a3aSHans de Goede int i, j; 6287554c0a3aSHans de Goede int set_idx; 6288554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6289554c0a3aSHans de Goede 6290554c0a3aSHans de Goede /* clear first */ 6291554c0a3aSHans de Goede memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num); 6292554c0a3aSHans de Goede 6293554c0a3aSHans de Goede /* acquire channels from in */ 6294554c0a3aSHans de Goede j = 0; 6295554c0a3aSHans de Goede for (i = 0; i < in_num; i++) { 6296554c0a3aSHans de Goede 6297554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i])); 6298554c0a3aSHans de Goede 6299554c0a3aSHans de Goede set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value); 6300554c0a3aSHans de Goede if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) 6301554c0a3aSHans de Goede && set_idx >= 0 63020ad02fa8SGeorgiana Chelu && rtw_mlme_band_check(padapter, in[i].hw_value) 6303554c0a3aSHans de Goede ) { 6304554c0a3aSHans de Goede if (j >= out_num) { 6305554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n", 6306554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), out_num); 6307554c0a3aSHans de Goede break; 6308554c0a3aSHans de Goede } 6309554c0a3aSHans de Goede 6310554c0a3aSHans de Goede memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel)); 6311554c0a3aSHans de Goede 6312554c0a3aSHans de Goede if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE) 6313554c0a3aSHans de Goede out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; 6314554c0a3aSHans de Goede 6315554c0a3aSHans de Goede j++; 6316554c0a3aSHans de Goede } 6317554c0a3aSHans de Goede if (j >= out_num) 6318554c0a3aSHans de Goede break; 6319554c0a3aSHans de Goede } 6320554c0a3aSHans de Goede 6321554c0a3aSHans de Goede /* if out is empty, use channel_set as default */ 6322554c0a3aSHans de Goede if (j == 0) { 6323554c0a3aSHans de Goede for (i = 0; i < pmlmeext->max_chan_nums; i++) { 6324554c0a3aSHans de Goede 6325554c0a3aSHans de Goede DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), pmlmeext->channel_set[i].ChannelNum); 6326554c0a3aSHans de Goede 63270ad02fa8SGeorgiana Chelu if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum)) { 6328554c0a3aSHans de Goede 6329554c0a3aSHans de Goede if (j >= out_num) { 6330554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n", 6331554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), out_num); 6332554c0a3aSHans de Goede break; 6333554c0a3aSHans de Goede } 6334554c0a3aSHans de Goede 6335554c0a3aSHans de Goede out[j].hw_value = pmlmeext->channel_set[i].ChannelNum; 6336554c0a3aSHans de Goede 6337554c0a3aSHans de Goede if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) 6338554c0a3aSHans de Goede out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; 6339554c0a3aSHans de Goede 6340554c0a3aSHans de Goede j++; 6341554c0a3aSHans de Goede } 6342554c0a3aSHans de Goede } 6343554c0a3aSHans de Goede } 6344554c0a3aSHans de Goede 6345554c0a3aSHans de Goede return j; 6346554c0a3aSHans de Goede } 6347554c0a3aSHans de Goede 6348554c0a3aSHans de Goede u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf) 6349554c0a3aSHans de Goede { 6350554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6351554c0a3aSHans de Goede struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf; 6352554c0a3aSHans de Goede u8 bdelayscan = false; 6353554c0a3aSHans de Goede u8 val8; 6354554c0a3aSHans de Goede u32 initialgain; 6355554c0a3aSHans de Goede u32 i; 6356554c0a3aSHans de Goede 6357554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) { 6358554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_START; 6359554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt = 0; 6360554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = 0; 6361554c0a3aSHans de Goede 6362554c0a3aSHans de Goede for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { 6363554c0a3aSHans de Goede if (pparm->ssid[i].SsidLength) { 6364554c0a3aSHans de Goede memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE); 6365554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength; 6366554c0a3aSHans de Goede } else { 6367554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0; 6368554c0a3aSHans de Goede } 6369554c0a3aSHans de Goede } 6370554c0a3aSHans de Goede 6371554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter 6372554c0a3aSHans de Goede , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT 6373554c0a3aSHans de Goede , pparm->ch, pparm->ch_num 6374554c0a3aSHans de Goede ); 6375554c0a3aSHans de Goede 6376554c0a3aSHans de Goede pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode; 6377554c0a3aSHans de Goede 6378554c0a3aSHans de Goede /* issue null data if associating to the AP */ 63790ad02fa8SGeorgiana Chelu if (is_client_associated_to_ap(padapter)) { 6380554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_TXNULL; 6381554c0a3aSHans de Goede 6382554c0a3aSHans de Goede issue_nulldata(padapter, NULL, 1, 3, 500); 6383554c0a3aSHans de Goede 6384554c0a3aSHans de Goede bdelayscan = true; 6385554c0a3aSHans de Goede } 6386554c0a3aSHans de Goede if (bdelayscan) { 6387554c0a3aSHans de Goede /* delay 50ms to protect nulldata(1). */ 6388554c0a3aSHans de Goede set_survey_timer(pmlmeext, 50); 6389554c0a3aSHans de Goede return H2C_SUCCESS; 6390554c0a3aSHans de Goede } 6391554c0a3aSHans de Goede } 6392554c0a3aSHans de Goede 6393554c0a3aSHans de Goede if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) { 6394554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 6395554c0a3aSHans de Goede Save_DM_Func_Flag(padapter); 6396554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); 6397554c0a3aSHans de Goede 63984d17363dSAndreas Hellmich /* config the initial gain under scanning, need to write the BB 63994d17363dSAndreas Hellmich * registers 64004d17363dSAndreas Hellmich */ 6401554c0a3aSHans de Goede initialgain = 0x1e; 6402554c0a3aSHans de Goede 6403554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 6404554c0a3aSHans de Goede 6405554c0a3aSHans de Goede /* set MSR to no link state */ 6406554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_NOLINK_); 6407554c0a3aSHans de Goede 6408554c0a3aSHans de Goede val8 = 1; /* under site survey */ 6409554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); 6410554c0a3aSHans de Goede 6411554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_PROCESS; 6412554c0a3aSHans de Goede } 6413554c0a3aSHans de Goede 6414554c0a3aSHans de Goede site_survey(padapter); 6415554c0a3aSHans de Goede 6416554c0a3aSHans de Goede return H2C_SUCCESS; 6417554c0a3aSHans de Goede 6418554c0a3aSHans de Goede } 6419554c0a3aSHans de Goede 6420554c0a3aSHans de Goede u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf) 6421554c0a3aSHans de Goede { 6422554c0a3aSHans de Goede struct setauth_parm *pparm = (struct setauth_parm *)pbuf; 6423554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6424554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6425554c0a3aSHans de Goede 6426a65f0d18SVatsala Narang if (pparm->mode < 4) 6427554c0a3aSHans de Goede pmlmeinfo->auth_algo = pparm->mode; 6428554c0a3aSHans de Goede 6429554c0a3aSHans de Goede return H2C_SUCCESS; 6430554c0a3aSHans de Goede } 6431554c0a3aSHans de Goede 6432554c0a3aSHans de Goede u8 setkey_hdl(struct adapter *padapter, u8 *pbuf) 6433554c0a3aSHans de Goede { 6434554c0a3aSHans de Goede u16 ctrl = 0; 6435554c0a3aSHans de Goede s16 cam_id = 0; 6436554c0a3aSHans de Goede struct setkey_parm *pparm = (struct setkey_parm *)pbuf; 6437554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6438554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6439554c0a3aSHans de Goede unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 6440554c0a3aSHans de Goede u8 *addr; 6441554c0a3aSHans de Goede 6442554c0a3aSHans de Goede /* main tx key for wep. */ 6443554c0a3aSHans de Goede if (pparm->set_tx) 6444554c0a3aSHans de Goede pmlmeinfo->key_index = pparm->keyid; 6445554c0a3aSHans de Goede 6446554c0a3aSHans de Goede cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid); 6447554c0a3aSHans de Goede 6448554c0a3aSHans de Goede if (cam_id < 0) { 6449554c0a3aSHans de Goede } else { 6450554c0a3aSHans de Goede if (cam_id > 3) /* not default key, searched by A2 */ 6451554c0a3aSHans de Goede addr = get_bssid(&padapter->mlmepriv); 6452554c0a3aSHans de Goede else 6453554c0a3aSHans de Goede addr = null_addr; 6454554c0a3aSHans de Goede 6455554c0a3aSHans de Goede ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid; 6456554c0a3aSHans de Goede write_cam(padapter, cam_id, ctrl, addr, pparm->key); 6457bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "set group key camid:%d, addr:%pM, kid:%d, type:%s\n" 6458554c0a3aSHans de Goede , cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm)); 6459554c0a3aSHans de Goede } 6460554c0a3aSHans de Goede 6461554c0a3aSHans de Goede if (cam_id >= 0 && cam_id <= 3) 6462554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true); 6463554c0a3aSHans de Goede 6464554c0a3aSHans de Goede /* allow multicast packets to driver */ 6465554c0a3aSHans de Goede padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr); 6466554c0a3aSHans de Goede 6467554c0a3aSHans de Goede return H2C_SUCCESS; 6468554c0a3aSHans de Goede } 6469554c0a3aSHans de Goede 6470554c0a3aSHans de Goede u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf) 6471554c0a3aSHans de Goede { 6472554c0a3aSHans de Goede u16 ctrl = 0; 6473554c0a3aSHans de Goede s16 cam_id = 0; 6474554c0a3aSHans de Goede u8 ret = H2C_SUCCESS; 6475554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6476554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6477554c0a3aSHans de Goede struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf; 6478554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 6479554c0a3aSHans de Goede struct sta_info *psta; 6480554c0a3aSHans de Goede 6481554c0a3aSHans de Goede if (pparm->algorithm == _NO_PRIVACY_) 6482554c0a3aSHans de Goede goto write_to_cam; 6483554c0a3aSHans de Goede 6484554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, pparm->addr); 6485554c0a3aSHans de Goede if (!psta) { 6486bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "%s sta:%pM not found\n", __func__, MAC_ARG(pparm->addr)); 6487554c0a3aSHans de Goede ret = H2C_REJECTED; 6488554c0a3aSHans de Goede goto exit; 6489554c0a3aSHans de Goede } 6490554c0a3aSHans de Goede 6491554c0a3aSHans de Goede pmlmeinfo->enc_algo = pparm->algorithm; 6492554c0a3aSHans de Goede cam_id = rtw_camid_alloc(padapter, psta, 0); 6493554c0a3aSHans de Goede if (cam_id < 0) 6494554c0a3aSHans de Goede goto exit; 6495554c0a3aSHans de Goede 6496554c0a3aSHans de Goede write_to_cam: 6497554c0a3aSHans de Goede if (pparm->algorithm == _NO_PRIVACY_) { 6498554c0a3aSHans de Goede while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) { 6499bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "clear key for addr:%pM, camid:%d\n", MAC_ARG(pparm->addr), cam_id); 6500554c0a3aSHans de Goede clear_cam_entry(padapter, cam_id); 6501554c0a3aSHans de Goede rtw_camid_free(padapter, cam_id); 6502554c0a3aSHans de Goede } 6503554c0a3aSHans de Goede } else { 6504bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "set pairwise key camid:%d, addr:%pM, kid:%d, type:%s\n", 6505554c0a3aSHans de Goede cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm)); 6506554c0a3aSHans de Goede ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid; 6507554c0a3aSHans de Goede write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key); 6508554c0a3aSHans de Goede } 6509554c0a3aSHans de Goede ret = H2C_SUCCESS_RSP; 6510554c0a3aSHans de Goede 6511554c0a3aSHans de Goede exit: 6512554c0a3aSHans de Goede return ret; 6513554c0a3aSHans de Goede } 6514554c0a3aSHans de Goede 6515554c0a3aSHans de Goede u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf) 6516554c0a3aSHans de Goede { 6517554c0a3aSHans de Goede struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf; 6518554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6519554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6520554c0a3aSHans de Goede 6521554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr); 6522554c0a3aSHans de Goede 6523554c0a3aSHans de Goede if (!psta) 6524554c0a3aSHans de Goede return H2C_SUCCESS; 6525554c0a3aSHans de Goede 6526554c0a3aSHans de Goede if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) || 6527554c0a3aSHans de Goede ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) { 6528554c0a3aSHans de Goede /* pmlmeinfo->ADDBA_retry_count = 0; */ 6529554c0a3aSHans de Goede /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */ 6530554c0a3aSHans de Goede /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */ 6531f4acd33cSRoss Schmidt issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid); 6532554c0a3aSHans de Goede /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */ 6533554c0a3aSHans de Goede _set_timer(&psta->addba_retry_timer, ADDBA_TO); 6534554c0a3aSHans de Goede } else { 6535554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid); 6536554c0a3aSHans de Goede } 6537554c0a3aSHans de Goede return H2C_SUCCESS; 6538554c0a3aSHans de Goede } 6539554c0a3aSHans de Goede 6540554c0a3aSHans de Goede 6541554c0a3aSHans de Goede u8 chk_bmc_sleepq_cmd(struct adapter *padapter) 6542554c0a3aSHans de Goede { 6543554c0a3aSHans de Goede struct cmd_obj *ph2c; 6544554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 6545554c0a3aSHans de Goede u8 res = _SUCCESS; 6546554c0a3aSHans de Goede 65472ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 6548554c0a3aSHans de Goede if (ph2c == NULL) { 6549554c0a3aSHans de Goede res = _FAIL; 6550554c0a3aSHans de Goede goto exit; 6551554c0a3aSHans de Goede } 6552554c0a3aSHans de Goede 6553554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq)); 6554554c0a3aSHans de Goede 6555554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 6556554c0a3aSHans de Goede 6557554c0a3aSHans de Goede exit: 6558554c0a3aSHans de Goede return res; 6559554c0a3aSHans de Goede } 6560554c0a3aSHans de Goede 6561554c0a3aSHans de Goede u8 set_tx_beacon_cmd(struct adapter *padapter) 6562554c0a3aSHans de Goede { 6563554c0a3aSHans de Goede struct cmd_obj *ph2c; 6564554c0a3aSHans de Goede struct Tx_Beacon_param *ptxBeacon_parm; 6565554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 6566554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6567554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 6568554c0a3aSHans de Goede u8 res = _SUCCESS; 6569554c0a3aSHans de Goede int len_diff = 0; 6570554c0a3aSHans de Goede 65712ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 6572554c0a3aSHans de Goede if (ph2c == NULL) { 6573554c0a3aSHans de Goede res = _FAIL; 6574554c0a3aSHans de Goede goto exit; 6575554c0a3aSHans de Goede } 6576554c0a3aSHans de Goede 65772ef2b7c2SJoe Perches ptxBeacon_parm = rtw_zmalloc(sizeof(struct Tx_Beacon_param)); 6578554c0a3aSHans de Goede if (ptxBeacon_parm == NULL) { 65798f24f505SMadhumitha Prabakaran kfree(ph2c); 6580554c0a3aSHans de Goede res = _FAIL; 6581554c0a3aSHans de Goede goto exit; 6582554c0a3aSHans de Goede } 6583554c0a3aSHans de Goede 6584554c0a3aSHans de Goede memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex)); 6585554c0a3aSHans de Goede 65865641eeecSRoss Schmidt len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_, 65875641eeecSRoss Schmidt ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_, 65885641eeecSRoss Schmidt pmlmeinfo->hidden_ssid_mode); 6589554c0a3aSHans de Goede ptxBeacon_parm->network.IELength += len_diff; 6590554c0a3aSHans de Goede 6591554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon)); 6592554c0a3aSHans de Goede 6593554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 6594554c0a3aSHans de Goede 6595554c0a3aSHans de Goede exit: 6596554c0a3aSHans de Goede return res; 6597554c0a3aSHans de Goede } 6598554c0a3aSHans de Goede 6599554c0a3aSHans de Goede 6600554c0a3aSHans de Goede u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf) 6601554c0a3aSHans de Goede { 6602554c0a3aSHans de Goede u8 evt_code, evt_seq; 6603554c0a3aSHans de Goede u16 evt_sz; 6604554c0a3aSHans de Goede uint *peventbuf; 6605554c0a3aSHans de Goede void (*event_callback)(struct adapter *dev, u8 *pbuf); 6606554c0a3aSHans de Goede struct evt_priv *pevt_priv = &(padapter->evtpriv); 6607554c0a3aSHans de Goede 6608554c0a3aSHans de Goede if (pbuf == NULL) 6609554c0a3aSHans de Goede goto _abort_event_; 6610554c0a3aSHans de Goede 6611554c0a3aSHans de Goede peventbuf = (uint *)pbuf; 6612554c0a3aSHans de Goede evt_sz = (u16)(*peventbuf&0xffff); 6613554c0a3aSHans de Goede evt_seq = (u8)((*peventbuf>>24)&0x7f); 6614554c0a3aSHans de Goede evt_code = (u8)((*peventbuf>>16)&0xff); 6615554c0a3aSHans de Goede 6616554c0a3aSHans de Goede 6617554c0a3aSHans de Goede #ifdef CHECK_EVENT_SEQ 6618554c0a3aSHans de Goede /* checking event sequence... */ 6619554c0a3aSHans de Goede if (evt_seq != (atomic_read(&pevt_priv->event_seq) & 0x7f)) { 6620103ab687SColin Ian King RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, 6621103ab687SColin Ian King ("Event Seq Error! %d vs %d\n", (evt_seq & 0x7f), 6622103ab687SColin Ian King (atomic_read(&pevt_priv->event_seq) & 0x7f))); 6623554c0a3aSHans de Goede 6624554c0a3aSHans de Goede pevt_priv->event_seq = (evt_seq+1)&0x7f; 6625554c0a3aSHans de Goede 6626554c0a3aSHans de Goede goto _abort_event_; 6627554c0a3aSHans de Goede } 6628554c0a3aSHans de Goede #endif 6629554c0a3aSHans de Goede 6630554c0a3aSHans de Goede /* checking if event code is valid */ 6631554c0a3aSHans de Goede if (evt_code >= MAX_C2HEVT) { 6632554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent Code(%d) mismatch!\n", evt_code)); 6633554c0a3aSHans de Goede goto _abort_event_; 6634554c0a3aSHans de Goede } 6635554c0a3aSHans de Goede 6636554c0a3aSHans de Goede /* checking if event size match the event parm size */ 6637554c0a3aSHans de Goede if ((wlanevents[evt_code].parmsize != 0) && 6638554c0a3aSHans de Goede (wlanevents[evt_code].parmsize != evt_sz)) { 6639554c0a3aSHans de Goede 6640554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n", 6641554c0a3aSHans de Goede evt_code, wlanevents[evt_code].parmsize, evt_sz)); 6642554c0a3aSHans de Goede goto _abort_event_; 6643554c0a3aSHans de Goede 6644554c0a3aSHans de Goede } 6645554c0a3aSHans de Goede 6646554c0a3aSHans de Goede atomic_inc(&pevt_priv->event_seq); 6647554c0a3aSHans de Goede 6648554c0a3aSHans de Goede peventbuf += 2; 6649554c0a3aSHans de Goede 6650554c0a3aSHans de Goede if (peventbuf) { 6651554c0a3aSHans de Goede event_callback = wlanevents[evt_code].event_callback; 6652554c0a3aSHans de Goede event_callback(padapter, (u8 *)peventbuf); 6653554c0a3aSHans de Goede 6654554c0a3aSHans de Goede pevt_priv->evt_done_cnt++; 6655554c0a3aSHans de Goede } 6656554c0a3aSHans de Goede 6657554c0a3aSHans de Goede 6658554c0a3aSHans de Goede _abort_event_: 6659554c0a3aSHans de Goede 6660554c0a3aSHans de Goede 6661554c0a3aSHans de Goede return H2C_SUCCESS; 6662554c0a3aSHans de Goede 6663554c0a3aSHans de Goede } 6664554c0a3aSHans de Goede 6665554c0a3aSHans de Goede u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf) 6666554c0a3aSHans de Goede { 6667554c0a3aSHans de Goede if (!pbuf) 6668554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6669554c0a3aSHans de Goede 6670554c0a3aSHans de Goede return H2C_SUCCESS; 6671554c0a3aSHans de Goede } 6672554c0a3aSHans de Goede 6673554c0a3aSHans de Goede u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) 6674554c0a3aSHans de Goede { 6675554c0a3aSHans de Goede struct sta_info *psta_bmc; 6676554c0a3aSHans de Goede struct list_head *xmitframe_plist, *xmitframe_phead; 6677554c0a3aSHans de Goede struct xmit_frame *pxmitframe = NULL; 6678554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 6679554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 6680554c0a3aSHans de Goede 6681554c0a3aSHans de Goede /* for BC/MC Frames */ 6682554c0a3aSHans de Goede psta_bmc = rtw_get_bcmc_stainfo(padapter); 6683554c0a3aSHans de Goede if (!psta_bmc) 6684554c0a3aSHans de Goede return H2C_SUCCESS; 6685554c0a3aSHans de Goede 6686554c0a3aSHans de Goede if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) { 6687554c0a3aSHans de Goede msleep(10);/* 10ms, ATIM(HIQ) Windows */ 6688554c0a3aSHans de Goede 6689554c0a3aSHans de Goede /* spin_lock_bh(&psta_bmc->sleep_q.lock); */ 6690554c0a3aSHans de Goede spin_lock_bh(&pxmitpriv->lock); 6691554c0a3aSHans de Goede 6692554c0a3aSHans de Goede xmitframe_phead = get_list_head(&psta_bmc->sleep_q); 6693554c0a3aSHans de Goede xmitframe_plist = get_next(xmitframe_phead); 6694554c0a3aSHans de Goede 6695554c0a3aSHans de Goede while (xmitframe_phead != xmitframe_plist) { 669619cf9d7aSRoss Schmidt pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); 6697554c0a3aSHans de Goede 6698554c0a3aSHans de Goede xmitframe_plist = get_next(xmitframe_plist); 6699554c0a3aSHans de Goede 6700554c0a3aSHans de Goede list_del_init(&pxmitframe->list); 6701554c0a3aSHans de Goede 6702554c0a3aSHans de Goede psta_bmc->sleepq_len--; 6703554c0a3aSHans de Goede if (psta_bmc->sleepq_len > 0) 6704554c0a3aSHans de Goede pxmitframe->attrib.mdata = 1; 6705554c0a3aSHans de Goede else 6706554c0a3aSHans de Goede pxmitframe->attrib.mdata = 0; 6707554c0a3aSHans de Goede 6708554c0a3aSHans de Goede pxmitframe->attrib.triggered = 1; 6709554c0a3aSHans de Goede 67100ad02fa8SGeorgiana Chelu if (xmitframe_hiq_filter(pxmitframe)) 6711554c0a3aSHans de Goede pxmitframe->attrib.qsel = 0x11;/* HIQ */ 6712554c0a3aSHans de Goede 6713554c0a3aSHans de Goede rtw_hal_xmitframe_enqueue(padapter, pxmitframe); 6714554c0a3aSHans de Goede } 6715554c0a3aSHans de Goede 6716554c0a3aSHans de Goede /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ 6717554c0a3aSHans de Goede spin_unlock_bh(&pxmitpriv->lock); 6718554c0a3aSHans de Goede 6719554c0a3aSHans de Goede /* check hi queue and bmc_sleepq */ 6720554c0a3aSHans de Goede rtw_chk_hi_queue_cmd(padapter); 6721554c0a3aSHans de Goede } 6722554c0a3aSHans de Goede 6723554c0a3aSHans de Goede return H2C_SUCCESS; 6724554c0a3aSHans de Goede } 6725554c0a3aSHans de Goede 6726554c0a3aSHans de Goede u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf) 6727554c0a3aSHans de Goede { 6728554c0a3aSHans de Goede if (send_beacon(padapter) == _FAIL) { 6729554c0a3aSHans de Goede DBG_871X("issue_beacon, fail!\n"); 6730554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6731554c0a3aSHans de Goede } 6732554c0a3aSHans de Goede 6733554c0a3aSHans de Goede /* tx bc/mc frames after update TIM */ 6734554c0a3aSHans de Goede chk_bmc_sleepq_hdl(padapter, NULL); 6735554c0a3aSHans de Goede 6736554c0a3aSHans de Goede return H2C_SUCCESS; 6737554c0a3aSHans de Goede } 6738554c0a3aSHans de Goede 6739554c0a3aSHans de Goede int rtw_chk_start_clnt_join(struct adapter *padapter, u8 *ch, u8 *bw, u8 *offset) 6740554c0a3aSHans de Goede { 6741554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6742554c0a3aSHans de Goede unsigned char cur_ch = pmlmeext->cur_channel; 6743554c0a3aSHans de Goede unsigned char cur_bw = pmlmeext->cur_bwmode; 6744554c0a3aSHans de Goede unsigned char cur_ch_offset = pmlmeext->cur_ch_offset; 6745554c0a3aSHans de Goede bool connect_allow = true; 6746554c0a3aSHans de Goede 6747554c0a3aSHans de Goede if (!ch || !bw || !offset) { 6748554c0a3aSHans de Goede rtw_warn_on(1); 6749554c0a3aSHans de Goede connect_allow = false; 6750554c0a3aSHans de Goede } 6751554c0a3aSHans de Goede 67520ad02fa8SGeorgiana Chelu if (connect_allow) { 6753554c0a3aSHans de Goede DBG_871X("start_join_set_ch_bw: ch =%d, bwmode =%d, ch_offset =%d\n", cur_ch, cur_bw, cur_ch_offset); 6754554c0a3aSHans de Goede *ch = cur_ch; 6755554c0a3aSHans de Goede *bw = cur_bw; 6756554c0a3aSHans de Goede *offset = cur_ch_offset; 6757554c0a3aSHans de Goede } 6758554c0a3aSHans de Goede 675963a9c3edSJeeeun Evans return connect_allow ? _SUCCESS : _FAIL; 6760554c0a3aSHans de Goede } 6761554c0a3aSHans de Goede 6762554c0a3aSHans de Goede /* Find union about ch, bw, ch_offset of all linked/linking interfaces */ 6763554c0a3aSHans de Goede int rtw_get_ch_setting_union(struct adapter *adapter, u8 *ch, u8 *bw, u8 *offset) 6764554c0a3aSHans de Goede { 6765554c0a3aSHans de Goede struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); 6766554c0a3aSHans de Goede struct adapter *iface; 6767554c0a3aSHans de Goede 6768554c0a3aSHans de Goede if (ch) 6769554c0a3aSHans de Goede *ch = 0; 6770554c0a3aSHans de Goede if (bw) 6771554c0a3aSHans de Goede *bw = CHANNEL_WIDTH_20; 6772554c0a3aSHans de Goede if (offset) 6773554c0a3aSHans de Goede *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 6774554c0a3aSHans de Goede 6775554c0a3aSHans de Goede iface = dvobj->padapters; 6776554c0a3aSHans de Goede 6777554c0a3aSHans de Goede if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING)) 6778554c0a3aSHans de Goede return 0; 6779554c0a3aSHans de Goede 6780554c0a3aSHans de Goede return 1; 6781554c0a3aSHans de Goede } 6782554c0a3aSHans de Goede 6783554c0a3aSHans de Goede u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf) 6784554c0a3aSHans de Goede { 6785554c0a3aSHans de Goede struct set_ch_parm *set_ch_parm; 6786554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6787554c0a3aSHans de Goede 6788554c0a3aSHans de Goede if (!pbuf) 6789554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6790554c0a3aSHans de Goede 6791554c0a3aSHans de Goede set_ch_parm = (struct set_ch_parm *)pbuf; 6792554c0a3aSHans de Goede 6793554c0a3aSHans de Goede DBG_871X(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n", 6794554c0a3aSHans de Goede FUNC_NDEV_ARG(padapter->pnetdev), 6795554c0a3aSHans de Goede set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset); 6796554c0a3aSHans de Goede 6797554c0a3aSHans de Goede pmlmeext->cur_channel = set_ch_parm->ch; 6798554c0a3aSHans de Goede pmlmeext->cur_ch_offset = set_ch_parm->ch_offset; 6799554c0a3aSHans de Goede pmlmeext->cur_bwmode = set_ch_parm->bw; 6800554c0a3aSHans de Goede 6801554c0a3aSHans de Goede set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw); 6802554c0a3aSHans de Goede 6803554c0a3aSHans de Goede return H2C_SUCCESS; 6804554c0a3aSHans de Goede } 6805554c0a3aSHans de Goede 6806554c0a3aSHans de Goede u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf) 6807554c0a3aSHans de Goede { 6808554c0a3aSHans de Goede struct SetChannelPlan_param *setChannelPlan_param; 6809554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6810554c0a3aSHans de Goede 6811554c0a3aSHans de Goede if (!pbuf) 6812554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6813554c0a3aSHans de Goede 6814554c0a3aSHans de Goede setChannelPlan_param = (struct SetChannelPlan_param *)pbuf; 6815554c0a3aSHans de Goede 6816554c0a3aSHans de Goede pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set); 6817554c0a3aSHans de Goede init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); 6818554c0a3aSHans de Goede 681934557e23SIzabela Bakollari if (padapter->rtw_wdev && padapter->rtw_wdev->wiphy) { 6820554c0a3aSHans de Goede struct regulatory_request request; 6821c926f022SSimran Singhal 6822554c0a3aSHans de Goede request.initiator = NL80211_REGDOM_SET_BY_DRIVER; 6823554c0a3aSHans de Goede rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request); 6824554c0a3aSHans de Goede } 6825554c0a3aSHans de Goede 6826554c0a3aSHans de Goede return H2C_SUCCESS; 6827554c0a3aSHans de Goede } 6828554c0a3aSHans de Goede 6829554c0a3aSHans de Goede u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf) 6830554c0a3aSHans de Goede { 6831554c0a3aSHans de Goede struct LedBlink_param *ledBlink_param; 6832554c0a3aSHans de Goede 6833554c0a3aSHans de Goede if (!pbuf) 6834554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6835554c0a3aSHans de Goede 6836554c0a3aSHans de Goede ledBlink_param = (struct LedBlink_param *)pbuf; 6837554c0a3aSHans de Goede return H2C_SUCCESS; 6838554c0a3aSHans de Goede } 6839554c0a3aSHans de Goede 6840554c0a3aSHans de Goede u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf) 6841554c0a3aSHans de Goede { 6842554c0a3aSHans de Goede return H2C_REJECTED; 6843554c0a3aSHans de Goede } 6844554c0a3aSHans de Goede 6845554c0a3aSHans de Goede /* TDLS_ESTABLISHED : write RCR DATA BIT */ 6846554c0a3aSHans de Goede /* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */ 6847554c0a3aSHans de Goede /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */ 6848554c0a3aSHans de Goede /* TDLS_DONE_CH_SEN: channel sensing and report candidate channel */ 6849554c0a3aSHans de Goede /* TDLS_OFF_CH : first time set channel to off channel */ 6850554c0a3aSHans de Goede /* TDLS_BASE_CH : go back tp the channel linked with AP when set base channel as target channel */ 6851554c0a3aSHans de Goede /* TDLS_P_OFF_CH : periodically go to off channel */ 6852554c0a3aSHans de Goede /* TDLS_P_BASE_CH : periodically go back to base channel */ 6853554c0a3aSHans de Goede /* TDLS_RS_RCR : restore RCR */ 6854554c0a3aSHans de Goede /* TDLS_TEAR_STA : free tdls sta */ 6855554c0a3aSHans de Goede u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf) 6856554c0a3aSHans de Goede { 6857554c0a3aSHans de Goede return H2C_REJECTED; 6858554c0a3aSHans de Goede } 6859554c0a3aSHans de Goede 6860554c0a3aSHans de Goede u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf) 6861554c0a3aSHans de Goede { 6862554c0a3aSHans de Goede struct RunInThread_param *p; 6863554c0a3aSHans de Goede 6864554c0a3aSHans de Goede 6865554c0a3aSHans de Goede if (NULL == pbuf) 6866554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6867554c0a3aSHans de Goede p = (struct RunInThread_param *)pbuf; 6868554c0a3aSHans de Goede 6869554c0a3aSHans de Goede if (p->func) 6870554c0a3aSHans de Goede p->func(p->context); 6871554c0a3aSHans de Goede 6872554c0a3aSHans de Goede return H2C_SUCCESS; 6873554c0a3aSHans de Goede } 6874