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 *********************************************************/ 74f0e46c47SMarco Cesati static struct 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 84f0e46c47SMarco Cesati static struct 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 124f0e46c47SMarco Cesati static struct 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 */ 212f0e46c47SMarco Cesati static struct 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 */ 220f0e46c47SMarco Cesati int rtw_ch_set_search_ch(struct 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 328f0e46c47SMarco Cesati static int has_channel(struct 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 343f0e46c47SMarco Cesati static void init_channel_list(struct adapter *padapter, struct 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 395f0e46c47SMarco Cesati static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct 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 401f0e46c47SMarco Cesati memset(channel_set, 0, sizeof(struct rt_channel_info)*MAX_CHANNEL_NUM); 402554c0a3aSHans de Goede 403709c8e49SFabio Aiuto if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) 404554c0a3aSHans de Goede return chanset_size; 405554c0a3aSHans de Goede 406554c0a3aSHans de Goede if (IsSupported24G(padapter->registrypriv.wireless_mode)) { 407554c0a3aSHans de Goede b2_4GBand = true; 408554c0a3aSHans de Goede if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan) 409554c0a3aSHans de Goede Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; 410554c0a3aSHans de Goede else 411554c0a3aSHans de Goede Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G; 412554c0a3aSHans de Goede } 413554c0a3aSHans de Goede 414554c0a3aSHans de Goede if (b2_4GBand) { 415554c0a3aSHans de Goede for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) { 416554c0a3aSHans de Goede channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index]; 417554c0a3aSHans de Goede 418554c0a3aSHans de Goede if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */ 419554c0a3aSHans de Goede (RT_CHANNEL_DOMAIN_GLOBAL_NULL == ChannelPlan)) { 420554c0a3aSHans de Goede if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11) 421554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 422554c0a3aSHans de Goede else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14)) 423554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 424554c0a3aSHans de Goede } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan || 425554c0a3aSHans de Goede RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan || 426554c0a3aSHans de Goede RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { /* channel 12~13, passive scan */ 427554c0a3aSHans de Goede if (channel_set[chanset_size].ChannelNum <= 11) 428554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 429554c0a3aSHans de Goede else 430554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 431554c0a3aSHans de Goede } else 432554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 433554c0a3aSHans de Goede 434554c0a3aSHans de Goede chanset_size++; 435554c0a3aSHans de Goede } 436554c0a3aSHans de Goede } 437554c0a3aSHans de Goede 438554c0a3aSHans de Goede if (b5GBand) { 439554c0a3aSHans de Goede for (index = 0; index < RTW_ChannelPlan5G[Index5G].Len; index++) { 440554c0a3aSHans de Goede if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48 441554c0a3aSHans de Goede || RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) { 442554c0a3aSHans de Goede channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index]; 443554c0a3aSHans de Goede if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)/* passive scan for all 5G channels */ 444554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 445554c0a3aSHans de Goede else 446554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 447554c0a3aSHans de Goede chanset_size++; 448554c0a3aSHans de Goede } 449554c0a3aSHans de Goede } 450554c0a3aSHans de Goede } 451554c0a3aSHans de Goede 452554c0a3aSHans de Goede return chanset_size; 453554c0a3aSHans de Goede } 454554c0a3aSHans de Goede 455067756acSHariprasad Kelam void init_mlme_ext_priv(struct adapter *padapter) 456554c0a3aSHans de Goede { 457554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 458554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 459c872ed07SVatsala Narang struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 460c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 461554c0a3aSHans de Goede 462554c0a3aSHans de Goede pmlmeext->padapter = padapter; 463554c0a3aSHans de Goede 464554c0a3aSHans de Goede /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */ 465554c0a3aSHans de Goede 466554c0a3aSHans de Goede init_mlme_ext_priv_value(padapter); 4672646633fSAastha Gupta pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req; 468554c0a3aSHans de Goede 469554c0a3aSHans de Goede init_mlme_ext_timer(padapter); 470554c0a3aSHans de Goede 471554c0a3aSHans de Goede init_mlme_ap_info(padapter); 472554c0a3aSHans de Goede 473554c0a3aSHans de Goede pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set); 474554c0a3aSHans de Goede init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); 475554c0a3aSHans de Goede pmlmeext->last_scan_time = 0; 476554c0a3aSHans de Goede pmlmeext->chan_scan_time = SURVEY_TO; 477554c0a3aSHans de Goede pmlmeext->mlmeext_init = true; 478554c0a3aSHans de Goede pmlmeext->active_keep_alive_check = true; 479554c0a3aSHans de Goede 480554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 481554c0a3aSHans de Goede pmlmeext->fixed_chan = 0xFF; 482554c0a3aSHans de Goede #endif 483554c0a3aSHans de Goede } 484554c0a3aSHans de Goede 485554c0a3aSHans de Goede void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) 486554c0a3aSHans de Goede { 487554c0a3aSHans de Goede struct adapter *padapter = pmlmeext->padapter; 488554c0a3aSHans de Goede 489554c0a3aSHans de Goede if (!padapter) 490554c0a3aSHans de Goede return; 491554c0a3aSHans de Goede 4920ad02fa8SGeorgiana Chelu if (padapter->bDriverStopped) { 493554c0a3aSHans de Goede del_timer_sync(&pmlmeext->survey_timer); 494554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 495554c0a3aSHans de Goede /* del_timer_sync(&pmlmeext->ADDBA_timer); */ 496554c0a3aSHans de Goede } 497554c0a3aSHans de Goede } 498554c0a3aSHans de Goede 499554c0a3aSHans de Goede static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame) 500554c0a3aSHans de Goede { 501554c0a3aSHans de Goede u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 502554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 503554c0a3aSHans de Goede 504554c0a3aSHans de Goede if (ptable->func) { 505554c0a3aSHans de Goede /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ 506554c0a3aSHans de Goede if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && 507554c0a3aSHans de Goede memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) 508554c0a3aSHans de Goede return; 509554c0a3aSHans de Goede 510554c0a3aSHans de Goede ptable->func(padapter, precv_frame); 511554c0a3aSHans de Goede } 512554c0a3aSHans de Goede } 513554c0a3aSHans de Goede 514554c0a3aSHans de Goede void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame) 515554c0a3aSHans de Goede { 516554c0a3aSHans de Goede int index; 517554c0a3aSHans de Goede struct mlme_handler *ptable; 518554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 519554c0a3aSHans de Goede u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 520554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 521554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe)); 522554c0a3aSHans de Goede struct dvobj_priv *psdpriv = padapter->dvobj; 523554c0a3aSHans de Goede struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; 524554c0a3aSHans de Goede 5250ac666f8SFabio Aiuto if (GetFrameType(pframe) != WIFI_MGT_TYPE) 526554c0a3aSHans de Goede return; 527554c0a3aSHans de Goede 528554c0a3aSHans de Goede /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ 529554c0a3aSHans de Goede if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && 530554c0a3aSHans de Goede memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) { 531554c0a3aSHans de Goede return; 532554c0a3aSHans de Goede } 533554c0a3aSHans de Goede 534554c0a3aSHans de Goede ptable = mlme_sta_tbl; 535554c0a3aSHans de Goede 536554c0a3aSHans de Goede index = GetFrameSubType(pframe) >> 4; 537554c0a3aSHans de Goede 5380ac666f8SFabio Aiuto if (index >= ARRAY_SIZE(mlme_sta_tbl)) 539554c0a3aSHans de Goede return; 5400ac666f8SFabio Aiuto 541554c0a3aSHans de Goede ptable += index; 542554c0a3aSHans de Goede 54334557e23SIzabela Bakollari if (psta) { 544554c0a3aSHans de Goede if (GetRetry(pframe)) { 545554c0a3aSHans de Goede if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) { 546554c0a3aSHans de Goede /* drop the duplicate management frame */ 547554c0a3aSHans de Goede pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++; 548554c0a3aSHans de Goede return; 549554c0a3aSHans de Goede } 550554c0a3aSHans de Goede } 551554c0a3aSHans de Goede psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num; 552554c0a3aSHans de Goede } 553554c0a3aSHans de Goede 554554c0a3aSHans de Goede switch (GetFrameSubType(pframe)) { 555554c0a3aSHans de Goede case WIFI_AUTH: 5560ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) 557554c0a3aSHans de Goede ptable->func = &OnAuth; 558554c0a3aSHans de Goede else 559554c0a3aSHans de Goede ptable->func = &OnAuthClient; 56052a1d9d4SGustavo A. R. Silva fallthrough; 561554c0a3aSHans de Goede case WIFI_ASSOCREQ: 562554c0a3aSHans de Goede case WIFI_REASSOCREQ: 563554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 564554c0a3aSHans de Goede break; 565554c0a3aSHans de Goede case WIFI_PROBEREQ: 566554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 567554c0a3aSHans de Goede break; 568554c0a3aSHans de Goede case WIFI_BEACON: 569554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 570554c0a3aSHans de Goede break; 571554c0a3aSHans de Goede case WIFI_ACTION: 572554c0a3aSHans de Goede /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */ 573554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 574554c0a3aSHans de Goede break; 575554c0a3aSHans de Goede default: 576554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 577554c0a3aSHans de Goede break; 578554c0a3aSHans de Goede } 579554c0a3aSHans de Goede } 580554c0a3aSHans de Goede 581554c0a3aSHans de Goede /**************************************************************************** 582554c0a3aSHans de Goede 583554c0a3aSHans de Goede Following are the callback functions for each subtype of the management frames 584554c0a3aSHans de Goede 585554c0a3aSHans de Goede *****************************************************************************/ 586554c0a3aSHans de Goede 587554c0a3aSHans de Goede unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame) 588554c0a3aSHans de Goede { 589554c0a3aSHans de Goede unsigned int ielen; 590554c0a3aSHans de Goede unsigned char *p; 591554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 592554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 593c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 594c872ed07SVatsala Narang struct wlan_bssid_ex *cur = &pmlmeinfo->network; 595554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 596554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 597554c0a3aSHans de Goede u8 is_valid_p2p_probereq = false; 598554c0a3aSHans de Goede 599554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) 600554c0a3aSHans de Goede return _SUCCESS; 601554c0a3aSHans de Goede 602554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) == false && 603554c0a3aSHans de Goede check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) { 604554c0a3aSHans de Goede return _SUCCESS; 605554c0a3aSHans de Goede } 606554c0a3aSHans de Goede 6073f15277bSRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_SSID, (int *)&ielen, 608554c0a3aSHans de Goede len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); 609554c0a3aSHans de Goede 610554c0a3aSHans de Goede 611554c0a3aSHans de Goede /* check (wildcard) SSID */ 61234557e23SIzabela Bakollari if (p) { 6130ad02fa8SGeorgiana Chelu if (is_valid_p2p_probereq) 614554c0a3aSHans de Goede goto _issue_probersp; 615554c0a3aSHans de Goede 616554c0a3aSHans de Goede if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) 617554c0a3aSHans de Goede || (ielen == 0 && pmlmeinfo->hidden_ssid_mode) 618554c0a3aSHans de Goede ) 619554c0a3aSHans de Goede return _SUCCESS; 620554c0a3aSHans de Goede 621554c0a3aSHans de Goede _issue_probersp: 6220ad02fa8SGeorgiana Chelu if ((check_fwstate(pmlmepriv, _FW_LINKED) && 623*af6afdb6SFabio Aiuto pmlmepriv->cur_network.join_res) || 624*af6afdb6SFabio Aiuto check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) 625554c0a3aSHans de Goede issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq); 626554c0a3aSHans de Goede } 627554c0a3aSHans de Goede 628554c0a3aSHans de Goede return _SUCCESS; 629554c0a3aSHans de Goede 630554c0a3aSHans de Goede } 631554c0a3aSHans de Goede 632554c0a3aSHans de Goede unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame) 633554c0a3aSHans de Goede { 634554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 635554c0a3aSHans de Goede 636554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 637554c0a3aSHans de Goede report_survey_event(padapter, precv_frame); 638554c0a3aSHans de Goede return _SUCCESS; 639554c0a3aSHans de Goede } 640554c0a3aSHans de Goede 641554c0a3aSHans de Goede return _SUCCESS; 642554c0a3aSHans de Goede 643554c0a3aSHans de Goede } 644554c0a3aSHans de Goede 645554c0a3aSHans de Goede unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame) 646554c0a3aSHans de Goede { 647554c0a3aSHans de Goede int cam_idx; 648554c0a3aSHans de Goede struct sta_info *psta; 649554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 650554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 651554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 652554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 653554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 654554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 655554c0a3aSHans de Goede struct wlan_bssid_ex *pbss; 656554c0a3aSHans de Goede int ret = _SUCCESS; 657554c0a3aSHans de Goede u8 *p = NULL; 658554c0a3aSHans de Goede u32 ielen = 0; 659554c0a3aSHans de Goede 66000f0b682SRoss Schmidt p = rtw_get_ie(pframe + sizeof(struct ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, WLAN_EID_EXT_SUPP_RATES, &ielen, precv_frame->u.hdr.len - sizeof(struct ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_); 66134557e23SIzabela Bakollari if (p && ielen > 0) { 662709c8e49SFabio Aiuto if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) 663554c0a3aSHans de Goede /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */ 664554c0a3aSHans de Goede *(p + 1) = ielen - 1; 665554c0a3aSHans de Goede } 666554c0a3aSHans de Goede 667554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 668554c0a3aSHans de Goede report_survey_event(padapter, precv_frame); 669554c0a3aSHans de Goede return _SUCCESS; 670554c0a3aSHans de Goede } 671554c0a3aSHans de Goede 672554c0a3aSHans de Goede if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) { 673554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { 674554c0a3aSHans de Goede /* we should update current network before auth, or some IE is wrong */ 6752ef2b7c2SJoe Perches pbss = rtw_malloc(sizeof(struct wlan_bssid_ex)); 676554c0a3aSHans de Goede if (pbss) { 677554c0a3aSHans de Goede if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) { 678554c0a3aSHans de Goede update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true); 679554c0a3aSHans de Goede rtw_get_bcn_info(&(pmlmepriv->cur_network)); 680554c0a3aSHans de Goede } 6818f24f505SMadhumitha Prabakaran kfree(pbss); 682554c0a3aSHans de Goede } 683554c0a3aSHans de Goede 684554c0a3aSHans de Goede /* check the vendor of the assoc AP */ 685554c0a3aSHans de Goede pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr)); 686554c0a3aSHans de Goede 687554c0a3aSHans de Goede /* update TSF Value */ 688554c0a3aSHans de Goede update_TSF(pmlmeext, pframe, len); 689554c0a3aSHans de Goede 690554c0a3aSHans de Goede /* reset for adaptive_early_32k */ 691554c0a3aSHans de Goede pmlmeext->adaptive_tsf_done = false; 692554c0a3aSHans de Goede pmlmeext->DrvBcnEarly = 0xff; 693554c0a3aSHans de Goede pmlmeext->DrvBcnTimeOut = 0xff; 694554c0a3aSHans de Goede pmlmeext->bcn_cnt = 0; 695554c0a3aSHans de Goede memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt)); 696554c0a3aSHans de Goede memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio)); 697554c0a3aSHans de Goede 698554c0a3aSHans de Goede /* start auth */ 699554c0a3aSHans de Goede start_clnt_auth(padapter); 700554c0a3aSHans de Goede 701554c0a3aSHans de Goede return _SUCCESS; 702554c0a3aSHans de Goede } 703554c0a3aSHans de Goede 704554c0a3aSHans de Goede if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { 705554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 70634557e23SIzabela Bakollari if (psta) { 707554c0a3aSHans de Goede ret = rtw_check_bcn_info(padapter, pframe, len); 708554c0a3aSHans de Goede if (!ret) { 709554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "ap has changed, disconnect now\n "); 710554c0a3aSHans de Goede receive_disconnect(padapter, pmlmeinfo->network.MacAddress, 0); 711554c0a3aSHans de Goede return _SUCCESS; 712554c0a3aSHans de Goede } 713554c0a3aSHans de Goede /* update WMM, ERP in the beacon */ 714554c0a3aSHans de Goede /* todo: the timer is used instead of the number of the beacon received */ 715554c0a3aSHans de Goede if ((sta_rx_pkts(psta) & 0xf) == 0) 716554c0a3aSHans de Goede update_beacon_info(padapter, pframe, len, psta); 717554c0a3aSHans de Goede 718554c0a3aSHans de Goede adaptive_early_32k(pmlmeext, pframe, len); 719554c0a3aSHans de Goede } 720554c0a3aSHans de Goede } else if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 721554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 72234557e23SIzabela Bakollari if (psta) { 723554c0a3aSHans de Goede /* update WMM, ERP in the beacon */ 724554c0a3aSHans de Goede /* todo: the timer is used instead of the number of the beacon received */ 725554c0a3aSHans de Goede if ((sta_rx_pkts(psta) & 0xf) == 0) { 726554c0a3aSHans de Goede update_beacon_info(padapter, pframe, len, psta); 727554c0a3aSHans de Goede } 728554c0a3aSHans de Goede } else { 729554c0a3aSHans de Goede /* allocate a new CAM entry for IBSS station */ 730554c0a3aSHans de Goede cam_idx = allocate_fw_sta_entry(padapter); 731554c0a3aSHans de Goede if (cam_idx == NUM_STA) 732554c0a3aSHans de Goede goto _END_ONBEACON_; 733554c0a3aSHans de Goede 734554c0a3aSHans de Goede /* get supported rate */ 735554c0a3aSHans 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) { 736554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[cam_idx].status = 0; 737554c0a3aSHans de Goede goto _END_ONBEACON_; 738554c0a3aSHans de Goede } 739554c0a3aSHans de Goede 740554c0a3aSHans de Goede /* update TSF Value */ 741554c0a3aSHans de Goede update_TSF(pmlmeext, pframe, len); 742554c0a3aSHans de Goede 743554c0a3aSHans de Goede /* report sta add event */ 744554c0a3aSHans de Goede report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx); 745554c0a3aSHans de Goede } 746554c0a3aSHans de Goede } 747554c0a3aSHans de Goede } 748554c0a3aSHans de Goede 749554c0a3aSHans de Goede _END_ONBEACON_: 750554c0a3aSHans de Goede 751554c0a3aSHans de Goede return _SUCCESS; 752554c0a3aSHans de Goede 753554c0a3aSHans de Goede } 754554c0a3aSHans de Goede 755554c0a3aSHans de Goede unsigned int OnAuth(struct adapter *padapter, union recv_frame *precv_frame) 756554c0a3aSHans de Goede { 757554c0a3aSHans de Goede unsigned int auth_mode, seq, ie_len; 758554c0a3aSHans de Goede unsigned char *sa, *p; 759554c0a3aSHans de Goede u16 algorithm; 760554c0a3aSHans de Goede int status; 761554c0a3aSHans de Goede static struct sta_info stat; 762554c0a3aSHans de Goede struct sta_info *pstat = NULL; 763554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 764554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 765554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 766554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 767554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 768554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 769554c0a3aSHans de Goede u8 offset = 0; 770554c0a3aSHans de Goede 771554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 772554c0a3aSHans de Goede return _FAIL; 773554c0a3aSHans de Goede 774554c0a3aSHans de Goede sa = GetAddr2Ptr(pframe); 775554c0a3aSHans de Goede 776554c0a3aSHans de Goede auth_mode = psecuritypriv->dot11AuthAlgrthm; 777554c0a3aSHans de Goede 778554c0a3aSHans de Goede if (GetPrivacy(pframe)) { 779554c0a3aSHans de Goede u8 *iv; 780554c0a3aSHans de Goede struct rx_pkt_attrib *prxattrib = &(precv_frame->u.hdr.attrib); 781554c0a3aSHans de Goede 782554c0a3aSHans de Goede prxattrib->hdrlen = WLAN_HDR_A3_LEN; 783554c0a3aSHans de Goede prxattrib->encrypt = _WEP40_; 784554c0a3aSHans de Goede 785554c0a3aSHans de Goede iv = pframe+prxattrib->hdrlen; 786554c0a3aSHans de Goede prxattrib->key_index = ((iv[3]>>6)&0x3); 787554c0a3aSHans de Goede 788554c0a3aSHans de Goede prxattrib->iv_len = 4; 789554c0a3aSHans de Goede prxattrib->icv_len = 4; 790554c0a3aSHans de Goede 791554c0a3aSHans de Goede rtw_wep_decrypt(padapter, (u8 *)precv_frame); 792554c0a3aSHans de Goede 793554c0a3aSHans de Goede offset = 4; 794554c0a3aSHans de Goede } 795554c0a3aSHans de Goede 796554c0a3aSHans de Goede algorithm = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset)); 797554c0a3aSHans de Goede seq = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2)); 798554c0a3aSHans de Goede 799554c0a3aSHans de Goede if (auth_mode == 2 && 800554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ && 801554c0a3aSHans de Goede psecuritypriv->dot11PrivacyAlgrthm != _WEP104_) 802554c0a3aSHans de Goede auth_mode = 0; 803554c0a3aSHans de Goede 804554c0a3aSHans de Goede if ((algorithm > 0 && auth_mode == 0) || /* rx a shared-key auth but shared not enabled */ 805554c0a3aSHans de Goede (algorithm == 0 && auth_mode == 1)) { /* rx a open-system auth but shared-key is enabled */ 806554c0a3aSHans de Goede 8076d75b504SRoss Schmidt status = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; 808554c0a3aSHans de Goede 809554c0a3aSHans de Goede goto auth_fail; 810554c0a3aSHans de Goede } 811554c0a3aSHans de Goede 812554c0a3aSHans de Goede if (rtw_access_ctrl(padapter, sa) == false) { 8136d75b504SRoss Schmidt status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 814554c0a3aSHans de Goede goto auth_fail; 815554c0a3aSHans de Goede } 816554c0a3aSHans de Goede 817554c0a3aSHans de Goede pstat = rtw_get_stainfo(pstapriv, sa); 818554c0a3aSHans de Goede if (pstat == NULL) { 819554c0a3aSHans de Goede 820554c0a3aSHans de Goede /* allocate a new one */ 821554c0a3aSHans de Goede pstat = rtw_alloc_stainfo(pstapriv, sa); 822554c0a3aSHans de Goede if (pstat == NULL) { 8236d75b504SRoss Schmidt status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 824554c0a3aSHans de Goede goto auth_fail; 825554c0a3aSHans de Goede } 826554c0a3aSHans de Goede 827554c0a3aSHans de Goede pstat->state = WIFI_FW_AUTH_NULL; 828554c0a3aSHans de Goede pstat->auth_seq = 0; 829554c0a3aSHans de Goede 830554c0a3aSHans de Goede /* pstat->flags = 0; */ 831554c0a3aSHans de Goede /* pstat->capability = 0; */ 832554c0a3aSHans de Goede } else { 833554c0a3aSHans de Goede 834554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 835554c0a3aSHans de Goede if (list_empty(&pstat->asoc_list) == false) { 836554c0a3aSHans de Goede list_del_init(&pstat->asoc_list); 837554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 838554c0a3aSHans de Goede if (pstat->expire_to > 0) { 839554c0a3aSHans de Goede /* TODO: STA re_auth within expire_to */ 840554c0a3aSHans de Goede } 841554c0a3aSHans de Goede } 842554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 843554c0a3aSHans de Goede 844554c0a3aSHans de Goede if (seq == 1) { 845554c0a3aSHans de Goede /* TODO: STA re_auth and auth timeout */ 846554c0a3aSHans de Goede } 847554c0a3aSHans de Goede } 848554c0a3aSHans de Goede 849554c0a3aSHans de Goede spin_lock_bh(&pstapriv->auth_list_lock); 850554c0a3aSHans de Goede if (list_empty(&pstat->auth_list)) { 851554c0a3aSHans de Goede 852554c0a3aSHans de Goede list_add_tail(&pstat->auth_list, &pstapriv->auth_list); 853554c0a3aSHans de Goede pstapriv->auth_list_cnt++; 854554c0a3aSHans de Goede } 855554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->auth_list_lock); 856554c0a3aSHans de Goede 857554c0a3aSHans de Goede if (pstat->auth_seq == 0) 858554c0a3aSHans de Goede pstat->expire_to = pstapriv->auth_to; 859554c0a3aSHans de Goede 860554c0a3aSHans de Goede 861554c0a3aSHans de Goede if ((pstat->auth_seq + 1) != seq) { 8626d75b504SRoss Schmidt status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; 863554c0a3aSHans de Goede goto auth_fail; 864554c0a3aSHans de Goede } 865554c0a3aSHans de Goede 866554c0a3aSHans de Goede if (algorithm == 0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3)) { 867554c0a3aSHans de Goede if (seq == 1) { 868554c0a3aSHans de Goede pstat->state &= ~WIFI_FW_AUTH_NULL; 869554c0a3aSHans de Goede pstat->state |= WIFI_FW_AUTH_SUCCESS; 870554c0a3aSHans de Goede pstat->expire_to = pstapriv->assoc_to; 871554c0a3aSHans de Goede pstat->authalg = algorithm; 872554c0a3aSHans de Goede } else { 8736d75b504SRoss Schmidt status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; 874554c0a3aSHans de Goede goto auth_fail; 875554c0a3aSHans de Goede } 876554c0a3aSHans de Goede } else { /* shared system or auto authentication */ 877554c0a3aSHans de Goede if (seq == 1) { 878554c0a3aSHans de Goede /* prepare for the challenging txt... */ 879554c0a3aSHans de Goede memset((void *)pstat->chg_txt, 78, 128); 880554c0a3aSHans de Goede 881554c0a3aSHans de Goede pstat->state &= ~WIFI_FW_AUTH_NULL; 882554c0a3aSHans de Goede pstat->state |= WIFI_FW_AUTH_STATE; 883554c0a3aSHans de Goede pstat->authalg = algorithm; 884554c0a3aSHans de Goede pstat->auth_seq = 2; 885554c0a3aSHans de Goede } else if (seq == 3) { 886554c0a3aSHans de Goede 88738caee0aSRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&ie_len, 888554c0a3aSHans de Goede len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4); 889554c0a3aSHans de Goede 890554c0a3aSHans de Goede if ((p == NULL) || (ie_len <= 0)) { 8916d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 892554c0a3aSHans de Goede goto auth_fail; 893554c0a3aSHans de Goede } 894554c0a3aSHans de Goede 895554c0a3aSHans de Goede if (!memcmp((void *)(p + 2), pstat->chg_txt, 128)) { 896554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_AUTH_STATE); 897554c0a3aSHans de Goede pstat->state |= WIFI_FW_AUTH_SUCCESS; 898554c0a3aSHans de Goede /* challenging txt is correct... */ 899554c0a3aSHans de Goede pstat->expire_to = pstapriv->assoc_to; 900554c0a3aSHans de Goede } else { 9016d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 902554c0a3aSHans de Goede goto auth_fail; 903554c0a3aSHans de Goede } 904554c0a3aSHans de Goede } else { 9056d75b504SRoss Schmidt status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; 906554c0a3aSHans de Goede goto auth_fail; 907554c0a3aSHans de Goede } 908554c0a3aSHans de Goede } 909554c0a3aSHans de Goede 910554c0a3aSHans de Goede 911554c0a3aSHans de Goede /* Now, we are going to issue_auth... */ 912554c0a3aSHans de Goede pstat->auth_seq = seq + 1; 913554c0a3aSHans de Goede 9146d75b504SRoss Schmidt issue_auth(padapter, pstat, (unsigned short)(WLAN_STATUS_SUCCESS)); 915554c0a3aSHans de Goede 916554c0a3aSHans de Goede if (pstat->state & WIFI_FW_AUTH_SUCCESS) 917554c0a3aSHans de Goede pstat->auth_seq = 0; 918554c0a3aSHans de Goede 919554c0a3aSHans de Goede 920554c0a3aSHans de Goede return _SUCCESS; 921554c0a3aSHans de Goede 922554c0a3aSHans de Goede auth_fail: 923554c0a3aSHans de Goede 924554c0a3aSHans de Goede if (pstat) 925554c0a3aSHans de Goede rtw_free_stainfo(padapter, pstat); 926554c0a3aSHans de Goede 927554c0a3aSHans de Goede pstat = &stat; 928554c0a3aSHans de Goede memset((char *)pstat, '\0', sizeof(stat)); 929554c0a3aSHans de Goede pstat->auth_seq = 2; 930554c0a3aSHans de Goede memcpy(pstat->hwaddr, sa, 6); 931554c0a3aSHans de Goede 932554c0a3aSHans de Goede issue_auth(padapter, pstat, (unsigned short)status); 933554c0a3aSHans de Goede 934554c0a3aSHans de Goede return _FAIL; 935554c0a3aSHans de Goede 936554c0a3aSHans de Goede } 937554c0a3aSHans de Goede 938554c0a3aSHans de Goede unsigned int OnAuthClient(struct adapter *padapter, union recv_frame *precv_frame) 939554c0a3aSHans de Goede { 9403a0514a9SJason Yan unsigned int seq, len, status, offset; 941554c0a3aSHans de Goede unsigned char *p; 942554c0a3aSHans de Goede unsigned int go2asoc = 0; 943554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 944554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 945554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 946554c0a3aSHans de Goede uint pkt_len = precv_frame->u.hdr.len; 947554c0a3aSHans de Goede 948554c0a3aSHans de Goede /* check A1 matches or not */ 949554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) 950554c0a3aSHans de Goede return _SUCCESS; 951554c0a3aSHans de Goede 952554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE)) 953554c0a3aSHans de Goede return _SUCCESS; 954554c0a3aSHans de Goede 955554c0a3aSHans de Goede offset = (GetPrivacy(pframe)) ? 4 : 0; 956554c0a3aSHans de Goede 957554c0a3aSHans de Goede seq = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2)); 958554c0a3aSHans de Goede status = le16_to_cpu(*(__le16 *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4)); 959554c0a3aSHans de Goede 960554c0a3aSHans de Goede if (status != 0) { 961554c0a3aSHans de Goede if (status == 13) { /* pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto) */ 962554c0a3aSHans de Goede if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) 963554c0a3aSHans de Goede pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; 964554c0a3aSHans de Goede else 965554c0a3aSHans de Goede pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; 966554c0a3aSHans de Goede /* pmlmeinfo->reauth_count = 0; */ 967554c0a3aSHans de Goede } 968554c0a3aSHans de Goede 969554c0a3aSHans de Goede set_link_timer(pmlmeext, 1); 970554c0a3aSHans de Goede goto authclnt_fail; 971554c0a3aSHans de Goede } 972554c0a3aSHans de Goede 973554c0a3aSHans de Goede if (seq == 2) { 974554c0a3aSHans de Goede if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { 975554c0a3aSHans de Goede /* legendary shared system */ 97638caee0aSRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, WLAN_EID_CHALLENGE, (int *)&len, 977554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_); 978554c0a3aSHans de Goede 979e427bdd8SFabio Aiuto if (!p) 980554c0a3aSHans de Goede goto authclnt_fail; 981554c0a3aSHans de Goede 982554c0a3aSHans de Goede memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len); 983554c0a3aSHans de Goede pmlmeinfo->auth_seq = 3; 984554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 985554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 986554c0a3aSHans de Goede 987554c0a3aSHans de Goede return _SUCCESS; 988554c0a3aSHans de Goede } else { 989554c0a3aSHans de Goede /* open system */ 990554c0a3aSHans de Goede go2asoc = 1; 991554c0a3aSHans de Goede } 992554c0a3aSHans de Goede } else if (seq == 4) { 993554c0a3aSHans de Goede if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) { 994554c0a3aSHans de Goede go2asoc = 1; 995554c0a3aSHans de Goede } else { 996554c0a3aSHans de Goede goto authclnt_fail; 997554c0a3aSHans de Goede } 998554c0a3aSHans de Goede } else { 999554c0a3aSHans de Goede /* this is also illegal */ 1000554c0a3aSHans de Goede goto authclnt_fail; 1001554c0a3aSHans de Goede } 1002554c0a3aSHans de Goede 1003554c0a3aSHans de Goede if (go2asoc) { 1004554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "auth success, start assoc\n"); 1005554c0a3aSHans de Goede start_clnt_assoc(padapter); 1006554c0a3aSHans de Goede return _SUCCESS; 1007554c0a3aSHans de Goede } 1008554c0a3aSHans de Goede 1009554c0a3aSHans de Goede authclnt_fail: 1010554c0a3aSHans de Goede 1011554c0a3aSHans de Goede /* pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE); */ 1012554c0a3aSHans de Goede 1013554c0a3aSHans de Goede return _FAIL; 1014554c0a3aSHans de Goede 1015554c0a3aSHans de Goede } 1016554c0a3aSHans de Goede 1017554c0a3aSHans de Goede unsigned int OnAssocReq(struct adapter *padapter, union recv_frame *precv_frame) 1018554c0a3aSHans de Goede { 101947548aa9SJason Yan u16 capab_info; 1020554c0a3aSHans de Goede struct rtw_ieee802_11_elems elems; 1021554c0a3aSHans de Goede struct sta_info *pstat; 1022554c0a3aSHans de Goede unsigned char reassoc, *p, *pos, *wpa_ie; 1023554c0a3aSHans de Goede unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; 1024554c0a3aSHans de Goede int i, ie_len, wpa_ie_len, left; 1025554c0a3aSHans de Goede unsigned char supportRate[16]; 1026554c0a3aSHans de Goede int supportRateNum; 10276d75b504SRoss Schmidt unsigned short status = WLAN_STATUS_SUCCESS; 1028554c0a3aSHans de Goede unsigned short frame_type, ie_offset = 0; 1029554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1030554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 1031554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1032554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1033554c0a3aSHans de Goede struct wlan_bssid_ex *cur = &(pmlmeinfo->network); 1034554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1035554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1036554c0a3aSHans de Goede uint pkt_len = precv_frame->u.hdr.len; 1037554c0a3aSHans de Goede 1038554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 1039554c0a3aSHans de Goede return _FAIL; 1040554c0a3aSHans de Goede 1041554c0a3aSHans de Goede frame_type = GetFrameSubType(pframe); 1042554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) { 1043554c0a3aSHans de Goede reassoc = 0; 1044554c0a3aSHans de Goede ie_offset = _ASOCREQ_IE_OFFSET_; 1045554c0a3aSHans de Goede } else { /* WIFI_REASSOCREQ */ 1046554c0a3aSHans de Goede reassoc = 1; 1047554c0a3aSHans de Goede ie_offset = _REASOCREQ_IE_OFFSET_; 1048554c0a3aSHans de Goede } 1049554c0a3aSHans de Goede 1050554c0a3aSHans de Goede 1051709c8e49SFabio Aiuto if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset) 1052554c0a3aSHans de Goede return _FAIL; 1053554c0a3aSHans de Goede 1054554c0a3aSHans de Goede pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 105541452327SVatsala Narang if (!pstat) { 10565ed3e6f2SRoss Schmidt status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; 1057554c0a3aSHans de Goede goto asoc_class2_error; 1058554c0a3aSHans de Goede } 1059554c0a3aSHans de Goede 1060d48603afSRoss Schmidt capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN); 1061554c0a3aSHans de Goede /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */ 1062554c0a3aSHans de Goede 10637d0b4f3cSQuytelda Kahja left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset); 10647d0b4f3cSQuytelda Kahja pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset); 1065554c0a3aSHans de Goede 1066554c0a3aSHans de Goede /* check if this stat has been successfully authenticated/assocated */ 1067554c0a3aSHans de Goede if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) { 1068554c0a3aSHans de Goede if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) { 10695ed3e6f2SRoss Schmidt status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; 1070554c0a3aSHans de Goede goto asoc_class2_error; 1071554c0a3aSHans de Goede } else { 1072554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); 1073554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_STATE; 1074554c0a3aSHans de Goede } 1075554c0a3aSHans de Goede } else { 1076554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_AUTH_SUCCESS); 1077554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_STATE; 1078554c0a3aSHans de Goede } 1079554c0a3aSHans de Goede 1080554c0a3aSHans de Goede 1081554c0a3aSHans de Goede pstat->capability = capab_info; 1082554c0a3aSHans de Goede 1083554c0a3aSHans de Goede /* now parse all ieee802_11 ie to point to elems */ 1084554c0a3aSHans de Goede if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed || 1085554c0a3aSHans de Goede !elems.ssid) { 10866d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1087554c0a3aSHans de Goede goto OnAssocReqFail; 1088554c0a3aSHans de Goede } 1089554c0a3aSHans de Goede 1090554c0a3aSHans de Goede /* now we should check all the fields... */ 1091554c0a3aSHans de Goede /* checking SSID */ 10923f15277bSRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SSID, &ie_len, 1093554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - ie_offset); 1094554c0a3aSHans de Goede 10956493a78fSAymen Qader if (!p || ie_len == 0) { 10966493a78fSAymen Qader /* broadcast ssid, however it is not allowed in assocreq */ 10976d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 10986493a78fSAymen Qader goto OnAssocReqFail; 10996493a78fSAymen Qader } else { 1100554c0a3aSHans de Goede /* check if ssid match */ 1101554c0a3aSHans de Goede if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength)) 11026d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1103554c0a3aSHans de Goede 1104554c0a3aSHans de Goede if (ie_len != cur->Ssid.SsidLength) 11056d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1106554c0a3aSHans de Goede } 1107554c0a3aSHans de Goede 11086d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 1109554c0a3aSHans de Goede goto OnAssocReqFail; 1110554c0a3aSHans de Goede 1111554c0a3aSHans de Goede /* check if the supported rate is ok */ 1112c34c45edSRoss 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); 1113554c0a3aSHans de Goede if (p == NULL) { 1114554c0a3aSHans de Goede /* use our own rate set as statoin used */ 1115554c0a3aSHans de Goede /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ 1116554c0a3aSHans de Goede /* supportRateNum = AP_BSSRATE_LEN; */ 1117554c0a3aSHans de Goede 11186d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1119554c0a3aSHans de Goede goto OnAssocReqFail; 1120554c0a3aSHans de Goede } else { 1121554c0a3aSHans de Goede memcpy(supportRate, p+2, ie_len); 1122554c0a3aSHans de Goede supportRateNum = ie_len; 1123554c0a3aSHans de Goede 112400f0b682SRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_EXT_SUPP_RATES, &ie_len, 1125554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - ie_offset); 1126554c0a3aSHans de Goede if (p != NULL) { 1127554c0a3aSHans de Goede 1128554c0a3aSHans de Goede if (supportRateNum <= sizeof(supportRate)) { 1129554c0a3aSHans de Goede memcpy(supportRate+supportRateNum, p+2, ie_len); 1130554c0a3aSHans de Goede supportRateNum += ie_len; 1131554c0a3aSHans de Goede } 1132554c0a3aSHans de Goede } 1133554c0a3aSHans de Goede } 1134554c0a3aSHans de Goede 1135554c0a3aSHans de Goede /* todo: mask supportRate between AP & STA -> move to update raid */ 1136554c0a3aSHans de Goede /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */ 1137554c0a3aSHans de Goede 1138554c0a3aSHans de Goede /* update station supportRate */ 1139554c0a3aSHans de Goede pstat->bssratelen = supportRateNum; 1140554c0a3aSHans de Goede memcpy(pstat->bssrateset, supportRate, supportRateNum); 1141554c0a3aSHans de Goede UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen); 1142554c0a3aSHans de Goede 1143554c0a3aSHans de Goede /* check RSN/WPA/WPS */ 1144554c0a3aSHans de Goede pstat->dot8021xalg = 0; 1145554c0a3aSHans de Goede pstat->wpa_psk = 0; 1146554c0a3aSHans de Goede pstat->wpa_group_cipher = 0; 1147554c0a3aSHans de Goede pstat->wpa2_group_cipher = 0; 1148554c0a3aSHans de Goede pstat->wpa_pairwise_cipher = 0; 1149554c0a3aSHans de Goede pstat->wpa2_pairwise_cipher = 0; 1150554c0a3aSHans de Goede memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie)); 1151554c0a3aSHans de Goede if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) { 1152554c0a3aSHans de Goede 1153554c0a3aSHans de Goede int group_cipher = 0, pairwise_cipher = 0; 1154554c0a3aSHans de Goede 1155554c0a3aSHans de Goede wpa_ie = elems.rsn_ie; 1156554c0a3aSHans de Goede wpa_ie_len = elems.rsn_ie_len; 1157554c0a3aSHans de Goede 1158554c0a3aSHans de Goede if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { 1159554c0a3aSHans de Goede pstat->dot8021xalg = 1;/* psk, todo:802.1x */ 1160554c0a3aSHans de Goede pstat->wpa_psk |= BIT(1); 1161554c0a3aSHans de Goede 1162554c0a3aSHans de Goede pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher; 1163554c0a3aSHans de Goede pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher; 1164554c0a3aSHans de Goede 1165554c0a3aSHans de Goede if (!pstat->wpa2_group_cipher) 11666d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_GROUP_CIPHER; 1167554c0a3aSHans de Goede 1168554c0a3aSHans de Goede if (!pstat->wpa2_pairwise_cipher) 11696d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; 1170554c0a3aSHans de Goede } else { 1171554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1172554c0a3aSHans de Goede } 1173554c0a3aSHans de Goede 1174554c0a3aSHans de Goede } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) { 1175554c0a3aSHans de Goede 1176554c0a3aSHans de Goede int group_cipher = 0, pairwise_cipher = 0; 1177554c0a3aSHans de Goede 1178554c0a3aSHans de Goede wpa_ie = elems.wpa_ie; 1179554c0a3aSHans de Goede wpa_ie_len = elems.wpa_ie_len; 1180554c0a3aSHans de Goede 1181554c0a3aSHans de Goede if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { 1182554c0a3aSHans de Goede pstat->dot8021xalg = 1;/* psk, todo:802.1x */ 1183554c0a3aSHans de Goede pstat->wpa_psk |= BIT(0); 1184554c0a3aSHans de Goede 1185554c0a3aSHans de Goede pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher; 1186554c0a3aSHans de Goede pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher; 1187554c0a3aSHans de Goede 1188554c0a3aSHans de Goede if (!pstat->wpa_group_cipher) 11896d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_GROUP_CIPHER; 1190554c0a3aSHans de Goede 1191554c0a3aSHans de Goede if (!pstat->wpa_pairwise_cipher) 11926d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; 1193554c0a3aSHans de Goede 1194554c0a3aSHans de Goede } else { 1195554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1196554c0a3aSHans de Goede } 1197554c0a3aSHans de Goede 1198554c0a3aSHans de Goede } else { 1199554c0a3aSHans de Goede wpa_ie = NULL; 1200554c0a3aSHans de Goede wpa_ie_len = 0; 1201554c0a3aSHans de Goede } 1202554c0a3aSHans de Goede 12036d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 1204554c0a3aSHans de Goede goto OnAssocReqFail; 1205554c0a3aSHans de Goede 1206554c0a3aSHans de Goede pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); 120741452327SVatsala Narang if (!wpa_ie) { 1208554c0a3aSHans de Goede if (elems.wps_ie) { 1209554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WPS; 1210554c0a3aSHans de Goede /* wpabuf_free(sta->wps_ie); */ 1211554c0a3aSHans de Goede /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */ 1212554c0a3aSHans de Goede /* elems.wps_ie_len - 4); */ 1213554c0a3aSHans de Goede } else { 1214554c0a3aSHans de Goede pstat->flags |= WLAN_STA_MAYBE_WPS; 1215554c0a3aSHans de Goede } 1216554c0a3aSHans de Goede 1217554c0a3aSHans de Goede 1218554c0a3aSHans de Goede /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */ 1219554c0a3aSHans de Goede /* that the selected registrar of AP is _FLASE */ 1220554c0a3aSHans de Goede if ((psecuritypriv->wpa_psk > 0) 1221554c0a3aSHans de Goede && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) { 1222554c0a3aSHans de Goede if (pmlmepriv->wps_beacon_ie) { 1223554c0a3aSHans de Goede u8 selected_registrar = 0; 1224554c0a3aSHans de Goede 1225554c0a3aSHans de Goede rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL); 1226554c0a3aSHans de Goede 1227554c0a3aSHans de Goede if (!selected_registrar) { 12286d75b504SRoss Schmidt status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 1229554c0a3aSHans de Goede 1230554c0a3aSHans de Goede goto OnAssocReqFail; 1231554c0a3aSHans de Goede } 1232554c0a3aSHans de Goede } 1233554c0a3aSHans de Goede } 1234554c0a3aSHans de Goede 1235554c0a3aSHans de Goede } else { 1236554c0a3aSHans de Goede int copy_len; 1237554c0a3aSHans de Goede 1238554c0a3aSHans de Goede if (psecuritypriv->wpa_psk == 0) { 1239554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1240554c0a3aSHans de Goede 1241554c0a3aSHans de Goede goto OnAssocReqFail; 1242554c0a3aSHans de Goede 1243554c0a3aSHans de Goede } 1244554c0a3aSHans de Goede 1245554c0a3aSHans de Goede if (elems.wps_ie) { 1246554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WPS; 1247554c0a3aSHans de Goede copy_len = 0; 1248554c0a3aSHans de Goede } else { 1249554c0a3aSHans de Goede copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2); 1250554c0a3aSHans de Goede } 1251554c0a3aSHans de Goede 1252554c0a3aSHans de Goede 1253554c0a3aSHans de Goede if (copy_len > 0) 1254554c0a3aSHans de Goede memcpy(pstat->wpa_ie, wpa_ie-2, copy_len); 1255554c0a3aSHans de Goede 1256554c0a3aSHans de Goede } 1257554c0a3aSHans de Goede 1258554c0a3aSHans de Goede 1259554c0a3aSHans de Goede /* check if there is WMM IE & support WWM-PS */ 1260554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_WME; 1261554c0a3aSHans de Goede pstat->qos_option = 0; 1262554c0a3aSHans de Goede pstat->qos_info = 0; 1263554c0a3aSHans de Goede pstat->has_legacy_ac = true; 1264554c0a3aSHans de Goede pstat->uapsd_vo = 0; 1265554c0a3aSHans de Goede pstat->uapsd_vi = 0; 1266554c0a3aSHans de Goede pstat->uapsd_be = 0; 1267554c0a3aSHans de Goede pstat->uapsd_bk = 0; 1268554c0a3aSHans de Goede if (pmlmepriv->qospriv.qos_option) { 1269554c0a3aSHans de Goede p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0; 1270554c0a3aSHans de Goede for (;;) { 1271b05cc3a9SRoss Schmidt p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); 127234557e23SIzabela Bakollari if (p) { 1273554c0a3aSHans de Goede if (!memcmp(p+2, WMM_IE, 6)) { 1274554c0a3aSHans de Goede 1275554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WME; 1276554c0a3aSHans de Goede 1277554c0a3aSHans de Goede pstat->qos_option = 1; 1278554c0a3aSHans de Goede pstat->qos_info = *(p+8); 1279554c0a3aSHans de Goede 1280554c0a3aSHans de Goede pstat->max_sp_len = (pstat->qos_info>>5)&0x3; 1281554c0a3aSHans de Goede 1282554c0a3aSHans de Goede if ((pstat->qos_info&0xf) != 0xf) 1283554c0a3aSHans de Goede pstat->has_legacy_ac = true; 1284554c0a3aSHans de Goede else 1285554c0a3aSHans de Goede pstat->has_legacy_ac = false; 1286554c0a3aSHans de Goede 1287554c0a3aSHans de Goede if (pstat->qos_info&0xf) { 1288554c0a3aSHans de Goede if (pstat->qos_info&BIT(0)) 1289554c0a3aSHans de Goede pstat->uapsd_vo = BIT(0)|BIT(1); 1290554c0a3aSHans de Goede else 1291554c0a3aSHans de Goede pstat->uapsd_vo = 0; 1292554c0a3aSHans de Goede 1293554c0a3aSHans de Goede if (pstat->qos_info&BIT(1)) 1294554c0a3aSHans de Goede pstat->uapsd_vi = BIT(0)|BIT(1); 1295554c0a3aSHans de Goede else 1296554c0a3aSHans de Goede pstat->uapsd_vi = 0; 1297554c0a3aSHans de Goede 1298554c0a3aSHans de Goede if (pstat->qos_info&BIT(2)) 1299554c0a3aSHans de Goede pstat->uapsd_bk = BIT(0)|BIT(1); 1300554c0a3aSHans de Goede else 1301554c0a3aSHans de Goede pstat->uapsd_bk = 0; 1302554c0a3aSHans de Goede 1303554c0a3aSHans de Goede if (pstat->qos_info&BIT(3)) 1304554c0a3aSHans de Goede pstat->uapsd_be = BIT(0)|BIT(1); 1305554c0a3aSHans de Goede else 1306554c0a3aSHans de Goede pstat->uapsd_be = 0; 1307554c0a3aSHans de Goede 1308554c0a3aSHans de Goede } 1309554c0a3aSHans de Goede 1310554c0a3aSHans de Goede break; 1311554c0a3aSHans de Goede } 1312554c0a3aSHans de Goede } else { 1313554c0a3aSHans de Goede break; 1314554c0a3aSHans de Goede } 1315554c0a3aSHans de Goede p = p + ie_len + 2; 1316554c0a3aSHans de Goede } 1317554c0a3aSHans de Goede } 1318554c0a3aSHans de Goede 1319554c0a3aSHans de Goede /* save HT capabilities in the sta object */ 1320c25d8a7dSRoss Schmidt memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap)); 1321c25d8a7dSRoss Schmidt if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) { 1322554c0a3aSHans de Goede pstat->flags |= WLAN_STA_HT; 1323554c0a3aSHans de Goede 1324554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WME; 1325554c0a3aSHans de Goede 1326c25d8a7dSRoss Schmidt memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap)); 1327554c0a3aSHans de Goede 1328554c0a3aSHans de Goede } else 1329554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_HT; 1330554c0a3aSHans de Goede 1331554c0a3aSHans de Goede 1332554c0a3aSHans de Goede if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT)) { 13336d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1334554c0a3aSHans de Goede goto OnAssocReqFail; 1335554c0a3aSHans de Goede } 1336554c0a3aSHans de Goede 1337554c0a3aSHans de Goede 1338554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_HT) && 1339554c0a3aSHans de Goede ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) || 1340554c0a3aSHans de Goede (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) { 13416d75b504SRoss Schmidt /* status = WLAN_STATUS_CIPHER_SUITE_REJECTED; */ 1342554c0a3aSHans de Goede /* goto OnAssocReqFail; */ 1343554c0a3aSHans de Goede } 1344554c0a3aSHans de Goede pstat->flags |= WLAN_STA_NONERP; 1345554c0a3aSHans de Goede for (i = 0; i < pstat->bssratelen; i++) { 1346554c0a3aSHans de Goede if ((pstat->bssrateset[i] & 0x7f) > 22) { 1347554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_NONERP; 1348554c0a3aSHans de Goede break; 1349554c0a3aSHans de Goede } 1350554c0a3aSHans de Goede } 1351554c0a3aSHans de Goede 1352554c0a3aSHans de Goede if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) 1353554c0a3aSHans de Goede pstat->flags |= WLAN_STA_SHORT_PREAMBLE; 1354554c0a3aSHans de Goede else 1355554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE; 1356554c0a3aSHans de Goede 1357554c0a3aSHans de Goede 1358554c0a3aSHans de Goede 13596d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 1360554c0a3aSHans de Goede goto OnAssocReqFail; 1361554c0a3aSHans de Goede 1362554c0a3aSHans de Goede /* TODO: identify_proprietary_vendor_ie(); */ 1363554c0a3aSHans de Goede /* Realtek proprietary IE */ 1364554c0a3aSHans de Goede /* identify if this is Broadcom sta */ 1365554c0a3aSHans de Goede /* identify if this is ralink sta */ 1366554c0a3aSHans de Goede /* Customer proprietary IE */ 1367554c0a3aSHans de Goede 1368554c0a3aSHans de Goede 1369554c0a3aSHans de Goede 1370554c0a3aSHans de Goede /* get a unique AID */ 137121e161c3SFabio Aiuto if (pstat->aid == 0) { 137287e4a540SYoung Xiao for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) 1373554c0a3aSHans de Goede if (pstapriv->sta_aid[pstat->aid - 1] == NULL) 1374554c0a3aSHans de Goede break; 1375554c0a3aSHans de Goede 1376554c0a3aSHans de Goede /* if (pstat->aid > NUM_STA) { */ 1377554c0a3aSHans de Goede if (pstat->aid > pstapriv->max_num_sta) { 1378554c0a3aSHans de Goede 1379554c0a3aSHans de Goede pstat->aid = 0; 1380554c0a3aSHans de Goede 1381554c0a3aSHans de Goede status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 1382554c0a3aSHans de Goede 1383554c0a3aSHans de Goede goto OnAssocReqFail; 1384554c0a3aSHans de Goede 1385554c0a3aSHans de Goede 1386554c0a3aSHans de Goede } else { 1387554c0a3aSHans de Goede pstapriv->sta_aid[pstat->aid - 1] = pstat; 1388554c0a3aSHans de Goede } 1389554c0a3aSHans de Goede } 1390554c0a3aSHans de Goede 1391554c0a3aSHans de Goede 1392554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_ASSOC_STATE); 1393554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_SUCCESS; 1394554c0a3aSHans de Goede 1395554c0a3aSHans de Goede spin_lock_bh(&pstapriv->auth_list_lock); 1396554c0a3aSHans de Goede if (!list_empty(&pstat->auth_list)) { 1397554c0a3aSHans de Goede list_del_init(&pstat->auth_list); 1398554c0a3aSHans de Goede pstapriv->auth_list_cnt--; 1399554c0a3aSHans de Goede } 1400554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->auth_list_lock); 1401554c0a3aSHans de Goede 1402554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1403554c0a3aSHans de Goede if (list_empty(&pstat->asoc_list)) { 1404554c0a3aSHans de Goede pstat->expire_to = pstapriv->expire_to; 1405554c0a3aSHans de Goede list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list); 1406554c0a3aSHans de Goede pstapriv->asoc_list_cnt++; 1407554c0a3aSHans de Goede } 1408554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1409554c0a3aSHans de Goede 1410554c0a3aSHans de Goede /* now the station is qualified to join our BSS... */ 14116d75b504SRoss Schmidt if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (WLAN_STATUS_SUCCESS == status)) { 1412554c0a3aSHans de Goede /* 1 bss_cap_update & sta_info_update */ 1413554c0a3aSHans de Goede bss_cap_update_on_sta_join(padapter, pstat); 1414554c0a3aSHans de Goede sta_info_update(padapter, pstat); 1415554c0a3aSHans de Goede 1416554c0a3aSHans de Goede /* 2 issue assoc rsp before notify station join event. */ 1417554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) 1418554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); 1419554c0a3aSHans de Goede else 1420554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); 1421554c0a3aSHans de Goede 1422554c0a3aSHans de Goede spin_lock_bh(&pstat->lock); 1423554c0a3aSHans de Goede if (pstat->passoc_req) { 1424554c0a3aSHans de Goede kfree(pstat->passoc_req); 1425554c0a3aSHans de Goede pstat->passoc_req = NULL; 1426554c0a3aSHans de Goede pstat->assoc_req_len = 0; 1427554c0a3aSHans de Goede } 1428554c0a3aSHans de Goede 1429554c0a3aSHans de Goede pstat->passoc_req = rtw_zmalloc(pkt_len); 1430554c0a3aSHans de Goede if (pstat->passoc_req) { 1431554c0a3aSHans de Goede memcpy(pstat->passoc_req, pframe, pkt_len); 1432554c0a3aSHans de Goede pstat->assoc_req_len = pkt_len; 1433554c0a3aSHans de Goede } 1434554c0a3aSHans de Goede spin_unlock_bh(&pstat->lock); 1435554c0a3aSHans de Goede 1436554c0a3aSHans de Goede /* 3-(1) report sta add event */ 1437554c0a3aSHans de Goede report_add_sta_event(padapter, pstat->hwaddr, pstat->aid); 1438554c0a3aSHans de Goede } 1439554c0a3aSHans de Goede 1440554c0a3aSHans de Goede return _SUCCESS; 1441554c0a3aSHans de Goede 1442554c0a3aSHans de Goede asoc_class2_error: 1443554c0a3aSHans de Goede 1444554c0a3aSHans de Goede issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status); 1445554c0a3aSHans de Goede 1446554c0a3aSHans de Goede return _FAIL; 1447554c0a3aSHans de Goede 1448554c0a3aSHans de Goede OnAssocReqFail: 1449554c0a3aSHans de Goede 1450554c0a3aSHans de Goede pstat->aid = 0; 1451554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) 1452554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); 1453554c0a3aSHans de Goede else 1454554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); 1455554c0a3aSHans de Goede 1456554c0a3aSHans de Goede return _FAIL; 1457554c0a3aSHans de Goede } 1458554c0a3aSHans de Goede 1459554c0a3aSHans de Goede unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame) 1460554c0a3aSHans de Goede { 1461554c0a3aSHans de Goede uint i; 1462554c0a3aSHans de Goede int res; 1463554c0a3aSHans de Goede unsigned short status; 1464554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 1465554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1466554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1467554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1468554c0a3aSHans de Goede /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */ 1469554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1470554c0a3aSHans de Goede uint pkt_len = precv_frame->u.hdr.len; 1471554c0a3aSHans de Goede 1472554c0a3aSHans de Goede /* check A1 matches or not */ 1473554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) 1474554c0a3aSHans de Goede return _SUCCESS; 1475554c0a3aSHans de Goede 1476554c0a3aSHans de Goede if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) 1477554c0a3aSHans de Goede return _SUCCESS; 1478554c0a3aSHans de Goede 1479554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) 1480554c0a3aSHans de Goede return _SUCCESS; 1481554c0a3aSHans de Goede 1482554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 1483554c0a3aSHans de Goede 1484554c0a3aSHans de Goede /* status */ 1485554c0a3aSHans de Goede status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2)); 1486554c0a3aSHans de Goede if (status > 0) { 1487554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 1488554c0a3aSHans de Goede res = -4; 1489554c0a3aSHans de Goede goto report_assoc_result; 1490554c0a3aSHans de Goede } 1491554c0a3aSHans de Goede 1492554c0a3aSHans de Goede /* get capabilities */ 1493554c0a3aSHans de Goede pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1494554c0a3aSHans de Goede 1495554c0a3aSHans de Goede /* set slot time */ 1496554c0a3aSHans de Goede pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20; 1497554c0a3aSHans de Goede 1498554c0a3aSHans de Goede /* AID */ 1499554c0a3aSHans de Goede res = pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff); 1500554c0a3aSHans de Goede 1501554c0a3aSHans de Goede /* following are moved to join event callback function */ 1502554c0a3aSHans de Goede /* to handle HT, WMM, rate adaptive, update MAC reg */ 1503554c0a3aSHans de Goede /* for not to handle the synchronous IO in the tasklet */ 1504554c0a3aSHans de Goede for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) { 1505554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pframe + i); 1506554c0a3aSHans de Goede 1507554c0a3aSHans de Goede switch (pIE->ElementID) { 1508b05cc3a9SRoss Schmidt case WLAN_EID_VENDOR_SPECIFIC: 1509554c0a3aSHans de Goede if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */ 1510554c0a3aSHans de Goede WMM_param_handler(padapter, pIE); 1511554c0a3aSHans de Goede break; 1512554c0a3aSHans de Goede 1513fc6a6528SRoss Schmidt case WLAN_EID_HT_CAPABILITY: /* HT caps */ 1514554c0a3aSHans de Goede HT_caps_handler(padapter, pIE); 1515554c0a3aSHans de Goede break; 1516554c0a3aSHans de Goede 1517332ec9dbSRoss Schmidt case WLAN_EID_HT_OPERATION: /* HT info */ 1518554c0a3aSHans de Goede HT_info_handler(padapter, pIE); 1519554c0a3aSHans de Goede break; 1520554c0a3aSHans de Goede 15217bd332ecSRoss Schmidt case WLAN_EID_ERP_INFO: 1522554c0a3aSHans de Goede ERP_IE_handler(padapter, pIE); 15232811861bSGustavo A. R. Silva break; 1524554c0a3aSHans de Goede 1525554c0a3aSHans de Goede default: 1526554c0a3aSHans de Goede break; 1527554c0a3aSHans de Goede } 1528554c0a3aSHans de Goede 1529554c0a3aSHans de Goede i += (pIE->Length + 2); 1530554c0a3aSHans de Goede } 1531554c0a3aSHans de Goede 1532554c0a3aSHans de Goede pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE); 1533554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 1534554c0a3aSHans de Goede 1535554c0a3aSHans de Goede /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ 1536554c0a3aSHans de Goede UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates); 1537554c0a3aSHans de Goede 1538554c0a3aSHans de Goede report_assoc_result: 1539554c0a3aSHans de Goede if (res > 0) { 1540554c0a3aSHans de Goede rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len); 1541554c0a3aSHans de Goede } else { 1542554c0a3aSHans de Goede rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len); 1543554c0a3aSHans de Goede } 1544554c0a3aSHans de Goede 1545554c0a3aSHans de Goede report_join_res(padapter, res); 1546554c0a3aSHans de Goede 1547554c0a3aSHans de Goede return _SUCCESS; 1548554c0a3aSHans de Goede } 1549554c0a3aSHans de Goede 1550554c0a3aSHans de Goede unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame) 1551554c0a3aSHans de Goede { 1552554c0a3aSHans de Goede unsigned short reason; 1553554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1554554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1555554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1556554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1557554c0a3aSHans de Goede 1558554c0a3aSHans de Goede /* check A3 */ 1559554c0a3aSHans de Goede if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) 1560554c0a3aSHans de Goede return _SUCCESS; 1561554c0a3aSHans de Goede 1562554c0a3aSHans de Goede reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1563554c0a3aSHans de Goede 15640ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 1565554c0a3aSHans de Goede struct sta_info *psta; 1566554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1567554c0a3aSHans de Goede 1568554c0a3aSHans de Goede /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ 1569554c0a3aSHans de Goede /* rtw_free_stainfo(padapter, psta); */ 1570554c0a3aSHans de Goede /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ 1571554c0a3aSHans de Goede 1572554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "ap recv deauth reason code(%d) sta:%pM\n", 1573554c0a3aSHans de Goede reason, GetAddr2Ptr(pframe)); 1574554c0a3aSHans de Goede 1575554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1576554c0a3aSHans de Goede if (psta) { 1577554c0a3aSHans de Goede u8 updated = false; 1578554c0a3aSHans de Goede 1579554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1580554c0a3aSHans de Goede if (list_empty(&psta->asoc_list) == false) { 1581554c0a3aSHans de Goede list_del_init(&psta->asoc_list); 1582554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 1583554c0a3aSHans de Goede updated = ap_free_sta(padapter, psta, false, reason); 1584554c0a3aSHans de Goede 1585554c0a3aSHans de Goede } 1586554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1587554c0a3aSHans de Goede 1588554c0a3aSHans de Goede associated_clients_update(padapter, updated); 1589554c0a3aSHans de Goede } 1590554c0a3aSHans de Goede 1591554c0a3aSHans de Goede 1592554c0a3aSHans de Goede return _SUCCESS; 1593554c0a3aSHans de Goede } else { 1594554c0a3aSHans de Goede int ignore_received_deauth = 0; 1595554c0a3aSHans de Goede 1596554c0a3aSHans de Goede /* Commented by Albert 20130604 */ 1597554c0a3aSHans de Goede /* Before sending the auth frame to start the STA/GC mode connection with AP/GO, */ 1598554c0a3aSHans de Goede /* we will send the deauth first. */ 1599554c0a3aSHans de Goede /* However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */ 1600554c0a3aSHans de Goede /* Added the following code to avoid this case. */ 1601554c0a3aSHans de Goede if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) || 1602554c0a3aSHans de Goede (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) { 1603554c0a3aSHans de Goede if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) { 1604554c0a3aSHans de Goede ignore_received_deauth = 1; 1605554c0a3aSHans de Goede } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) { 1606554c0a3aSHans de Goede /* TODO: 802.11r */ 1607554c0a3aSHans de Goede ignore_received_deauth = 1; 1608554c0a3aSHans de Goede } 1609554c0a3aSHans de Goede } 1610554c0a3aSHans de Goede 1611554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n", 1612554c0a3aSHans de Goede reason, GetAddr3Ptr(pframe), ignore_received_deauth); 1613554c0a3aSHans de Goede 1614554c0a3aSHans de Goede if (0 == ignore_received_deauth) { 1615554c0a3aSHans de Goede receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); 1616554c0a3aSHans de Goede } 1617554c0a3aSHans de Goede } 1618554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bBusyTraffic = false; 1619554c0a3aSHans de Goede return _SUCCESS; 1620554c0a3aSHans de Goede 1621554c0a3aSHans de Goede } 1622554c0a3aSHans de Goede 1623554c0a3aSHans de Goede unsigned int OnDisassoc(struct adapter *padapter, union recv_frame *precv_frame) 1624554c0a3aSHans de Goede { 1625554c0a3aSHans de Goede unsigned short reason; 1626554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1627554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1628554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1629554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1630554c0a3aSHans de Goede 1631554c0a3aSHans de Goede /* check A3 */ 1632554c0a3aSHans de Goede if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) 1633554c0a3aSHans de Goede return _SUCCESS; 1634554c0a3aSHans de Goede 1635554c0a3aSHans de Goede reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1636554c0a3aSHans de Goede 16370ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 1638554c0a3aSHans de Goede struct sta_info *psta; 1639554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1640554c0a3aSHans de Goede 1641554c0a3aSHans de Goede /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ 1642554c0a3aSHans de Goede /* rtw_free_stainfo(padapter, psta); */ 1643554c0a3aSHans de Goede /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ 1644554c0a3aSHans de Goede 1645554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "ap recv disassoc reason code(%d) sta:%pM\n", 1646554c0a3aSHans de Goede reason, GetAddr2Ptr(pframe)); 1647554c0a3aSHans de Goede 1648554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1649554c0a3aSHans de Goede if (psta) { 1650554c0a3aSHans de Goede u8 updated = false; 1651554c0a3aSHans de Goede 1652554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1653554c0a3aSHans de Goede if (list_empty(&psta->asoc_list) == false) { 1654554c0a3aSHans de Goede list_del_init(&psta->asoc_list); 1655554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 1656554c0a3aSHans de Goede updated = ap_free_sta(padapter, psta, false, reason); 1657554c0a3aSHans de Goede 1658554c0a3aSHans de Goede } 1659554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1660554c0a3aSHans de Goede 1661554c0a3aSHans de Goede associated_clients_update(padapter, updated); 1662554c0a3aSHans de Goede } 1663554c0a3aSHans de Goede 1664554c0a3aSHans de Goede return _SUCCESS; 1665554c0a3aSHans de Goede } else { 1666554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "sta recv disassoc reason code(%d) sta:%pM\n", 1667554c0a3aSHans de Goede reason, GetAddr3Ptr(pframe)); 1668554c0a3aSHans de Goede 1669554c0a3aSHans de Goede receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); 1670554c0a3aSHans de Goede } 1671554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bBusyTraffic = false; 1672554c0a3aSHans de Goede return _SUCCESS; 1673554c0a3aSHans de Goede 1674554c0a3aSHans de Goede } 1675554c0a3aSHans de Goede 1676554c0a3aSHans de Goede unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame) 1677554c0a3aSHans de Goede { 1678554c0a3aSHans de Goede return _SUCCESS; 1679554c0a3aSHans de Goede } 1680554c0a3aSHans de Goede 1681554c0a3aSHans de Goede unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame) 1682554c0a3aSHans de Goede { 1683554c0a3aSHans de Goede struct sta_info *psta = NULL; 1684554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1685554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1686554c0a3aSHans de Goede u8 *frame_body = (u8 *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1687554c0a3aSHans de Goede u8 category; 1688554c0a3aSHans de Goede u8 action; 1689554c0a3aSHans de Goede 1690554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1691554c0a3aSHans de Goede 1692554c0a3aSHans de Goede if (!psta) 1693554c0a3aSHans de Goede goto exit; 1694554c0a3aSHans de Goede 1695554c0a3aSHans de Goede category = frame_body[0]; 1696554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT) 1697554c0a3aSHans de Goede goto exit; 1698554c0a3aSHans de Goede 1699554c0a3aSHans de Goede action = frame_body[1]; 1700554c0a3aSHans de Goede switch (action) { 170172cac683SRoss Schmidt case WLAN_ACTION_SPCT_MSR_REQ: 170272cac683SRoss Schmidt case WLAN_ACTION_SPCT_MSR_RPRT: 170372cac683SRoss Schmidt case WLAN_ACTION_SPCT_TPC_REQ: 170472cac683SRoss Schmidt case WLAN_ACTION_SPCT_TPC_RPRT: 170572cac683SRoss Schmidt case WLAN_ACTION_SPCT_CHL_SWITCH: 1706554c0a3aSHans de Goede break; 1707554c0a3aSHans de Goede default: 1708554c0a3aSHans de Goede break; 1709554c0a3aSHans de Goede } 1710554c0a3aSHans de Goede 1711554c0a3aSHans de Goede exit: 17121c4bfacfSHariprasad Kelam return _FAIL; 1713554c0a3aSHans de Goede } 1714554c0a3aSHans de Goede 1715554c0a3aSHans de Goede unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame) 1716554c0a3aSHans de Goede { 1717554c0a3aSHans de Goede u8 *addr; 1718554c0a3aSHans de Goede struct sta_info *psta = NULL; 1719554c0a3aSHans de Goede struct recv_reorder_ctrl *preorder_ctrl; 1720554c0a3aSHans de Goede unsigned char *frame_body; 1721554c0a3aSHans de Goede unsigned char category, action; 1722554c0a3aSHans de Goede unsigned short tid, status, reason_code = 0; 1723554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1724554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1725554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1726554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1727554c0a3aSHans de Goede 1728554c0a3aSHans de Goede /* check RA matches or not */ 1729554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */ 1730554c0a3aSHans de Goede return _SUCCESS; 1731554c0a3aSHans de Goede 1732554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 1733554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) 1734554c0a3aSHans de Goede return _SUCCESS; 1735554c0a3aSHans de Goede 1736554c0a3aSHans de Goede addr = GetAddr2Ptr(pframe); 1737554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, addr); 1738554c0a3aSHans de Goede 173941452327SVatsala Narang if (!psta) 1740554c0a3aSHans de Goede return _SUCCESS; 1741554c0a3aSHans de Goede 1742554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1743554c0a3aSHans de Goede 1744554c0a3aSHans de Goede category = frame_body[0]; 1745554c0a3aSHans de Goede if (category == RTW_WLAN_CATEGORY_BACK) {/* representing Block Ack */ 1746a65f0d18SVatsala Narang if (!pmlmeinfo->HT_enable) 1747554c0a3aSHans de Goede return _SUCCESS; 1748554c0a3aSHans de Goede 1749554c0a3aSHans de Goede action = frame_body[1]; 1750554c0a3aSHans de Goede switch (action) { 1751f4acd33cSRoss Schmidt case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ 1752554c0a3aSHans de Goede 1753554c0a3aSHans de Goede memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); 1754554c0a3aSHans de Goede /* process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */ 1755554c0a3aSHans de Goede process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); 1756554c0a3aSHans de Goede 17572646633fSAastha Gupta if (pmlmeinfo->accept_addba_req) { 1758f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 0); 1759554c0a3aSHans de Goede } else { 1760f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */ 1761554c0a3aSHans de Goede } 1762554c0a3aSHans de Goede 1763554c0a3aSHans de Goede break; 1764554c0a3aSHans de Goede 1765f4acd33cSRoss Schmidt case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ 1766d48603afSRoss Schmidt status = get_unaligned_le16(&frame_body[3]); 1767554c0a3aSHans de Goede tid = ((frame_body[5] >> 2) & 0x7); 1768554c0a3aSHans de Goede 1769554c0a3aSHans de Goede if (status == 0) { 1770554c0a3aSHans de Goede /* successful */ 1771e52d8d0dSVatsala Narang psta->htpriv.agg_enable_bitmap |= BIT(tid); 1772554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); 1773554c0a3aSHans de Goede } else { 1774554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 1775554c0a3aSHans de Goede } 1776554c0a3aSHans de Goede 1777554c0a3aSHans de Goede if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { 1778554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 1779554c0a3aSHans de Goede psta->expire_to = pstapriv->expire_to; 1780554c0a3aSHans de Goede psta->state ^= WIFI_STA_ALIVE_CHK_STATE; 1781554c0a3aSHans de Goede } 1782554c0a3aSHans de Goede 1783554c0a3aSHans de Goede break; 1784554c0a3aSHans de Goede 1785f4acd33cSRoss Schmidt case WLAN_ACTION_DELBA: /* DELBA */ 1786554c0a3aSHans de Goede if ((frame_body[3] & BIT(3)) == 0) { 1787e52d8d0dSVatsala Narang psta->htpriv.agg_enable_bitmap &= 1788e52d8d0dSVatsala Narang ~BIT((frame_body[3] >> 4) & 0xf); 1789e52d8d0dSVatsala Narang psta->htpriv.candidate_tid_bitmap &= 1790e52d8d0dSVatsala Narang ~BIT((frame_body[3] >> 4) & 0xf); 1791554c0a3aSHans de Goede 1792554c0a3aSHans de Goede /* reason_code = frame_body[4] | (frame_body[5] << 8); */ 1793d48603afSRoss Schmidt reason_code = get_unaligned_le16(&frame_body[4]); 1794554c0a3aSHans de Goede } else if ((frame_body[3] & BIT(3)) == BIT(3)) { 1795554c0a3aSHans de Goede tid = (frame_body[3] >> 4) & 0x0F; 1796554c0a3aSHans de Goede 1797554c0a3aSHans de Goede preorder_ctrl = &psta->recvreorder_ctrl[tid]; 1798554c0a3aSHans de Goede preorder_ctrl->enable = false; 1799554c0a3aSHans de Goede preorder_ctrl->indicate_seq = 0xffff; 1800554c0a3aSHans de Goede } 1801554c0a3aSHans de Goede /* todo: how to notify the host while receiving DELETE BA */ 1802554c0a3aSHans de Goede break; 1803554c0a3aSHans de Goede 1804554c0a3aSHans de Goede default: 1805554c0a3aSHans de Goede break; 1806554c0a3aSHans de Goede } 1807554c0a3aSHans de Goede } 1808554c0a3aSHans de Goede return _SUCCESS; 1809554c0a3aSHans de Goede } 1810554c0a3aSHans de Goede 1811554c0a3aSHans de Goede static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token) 1812554c0a3aSHans de Goede { 1813554c0a3aSHans de Goede struct adapter *adapter = recv_frame->u.hdr.adapter; 1814554c0a3aSHans de Goede struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv); 1815554c0a3aSHans de Goede u8 *frame = recv_frame->u.hdr.rx_data; 1816554c0a3aSHans de Goede u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) | 1817554c0a3aSHans de Goede (recv_frame->u.hdr.attrib.frag_num & 0xf); 1818554c0a3aSHans de Goede 1819554c0a3aSHans de Goede if (GetRetry(frame)) { 1820554c0a3aSHans de Goede if (token >= 0) { 1821554c0a3aSHans de Goede if ((seq_ctrl == mlmeext->action_public_rxseq) 1822709c8e49SFabio Aiuto && (token == mlmeext->action_public_dialog_token)) 1823554c0a3aSHans de Goede return _FAIL; 1824554c0a3aSHans de Goede } else { 1825709c8e49SFabio Aiuto if (seq_ctrl == mlmeext->action_public_rxseq) 1826554c0a3aSHans de Goede return _FAIL; 1827554c0a3aSHans de Goede } 1828554c0a3aSHans de Goede } 1829554c0a3aSHans de Goede 1830554c0a3aSHans de Goede mlmeext->action_public_rxseq = seq_ctrl; 1831554c0a3aSHans de Goede 1832554c0a3aSHans de Goede if (token >= 0) 1833554c0a3aSHans de Goede mlmeext->action_public_dialog_token = token; 1834554c0a3aSHans de Goede 1835554c0a3aSHans de Goede return _SUCCESS; 1836554c0a3aSHans de Goede } 1837554c0a3aSHans de Goede 1838554c0a3aSHans de Goede static unsigned int on_action_public_p2p(union recv_frame *precv_frame) 1839554c0a3aSHans de Goede { 1840554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1841554c0a3aSHans de Goede u8 *frame_body; 1842554c0a3aSHans de Goede u8 dialogToken = 0; 1843554c0a3aSHans de Goede 1844554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1845554c0a3aSHans de Goede 1846554c0a3aSHans de Goede dialogToken = frame_body[7]; 1847554c0a3aSHans de Goede 1848554c0a3aSHans de Goede if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL) 1849554c0a3aSHans de Goede return _FAIL; 1850554c0a3aSHans de Goede 1851554c0a3aSHans de Goede return _SUCCESS; 1852554c0a3aSHans de Goede } 1853554c0a3aSHans de Goede 1854554c0a3aSHans de Goede static unsigned int on_action_public_vendor(union recv_frame *precv_frame) 1855554c0a3aSHans de Goede { 1856554c0a3aSHans de Goede unsigned int ret = _FAIL; 1857554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1858554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 1859554c0a3aSHans de Goede 1860554c0a3aSHans de Goede if (!memcmp(frame_body + 2, P2P_OUI, 4)) { 1861554c0a3aSHans de Goede ret = on_action_public_p2p(precv_frame); 1862554c0a3aSHans de Goede } 1863554c0a3aSHans de Goede 1864554c0a3aSHans de Goede return ret; 1865554c0a3aSHans de Goede } 1866554c0a3aSHans de Goede 1867554c0a3aSHans de Goede static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action) 1868554c0a3aSHans de Goede { 1869554c0a3aSHans de Goede unsigned int ret = _FAIL; 1870554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1871554c0a3aSHans de Goede uint frame_len = precv_frame->u.hdr.len; 1872554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 1873554c0a3aSHans de Goede u8 token; 1874554c0a3aSHans de Goede struct adapter *adapter = precv_frame->u.hdr.adapter; 1875554c0a3aSHans de Goede char msg[64]; 1876554c0a3aSHans de Goede 1877554c0a3aSHans de Goede token = frame_body[2]; 1878554c0a3aSHans de Goede 1879554c0a3aSHans de Goede if (rtw_action_public_decache(precv_frame, token) == _FAIL) 1880554c0a3aSHans de Goede goto exit; 1881554c0a3aSHans de Goede 188241b25593SCandy Febriyanto scnprintf(msg, sizeof(msg), "%s(token:%u)", action_public_str(action), token); 1883554c0a3aSHans de Goede rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg); 1884554c0a3aSHans de Goede 1885554c0a3aSHans de Goede ret = _SUCCESS; 1886554c0a3aSHans de Goede 1887554c0a3aSHans de Goede exit: 1888554c0a3aSHans de Goede return ret; 1889554c0a3aSHans de Goede } 1890554c0a3aSHans de Goede 1891554c0a3aSHans de Goede unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame) 1892554c0a3aSHans de Goede { 1893554c0a3aSHans de Goede unsigned int ret = _FAIL; 1894554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1895554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 1896554c0a3aSHans de Goede u8 category, action; 1897554c0a3aSHans de Goede 1898554c0a3aSHans de Goede /* check RA matches or not */ 1899554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN)) 1900554c0a3aSHans de Goede goto exit; 1901554c0a3aSHans de Goede 1902554c0a3aSHans de Goede category = frame_body[0]; 1903554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_PUBLIC) 1904554c0a3aSHans de Goede goto exit; 1905554c0a3aSHans de Goede 1906554c0a3aSHans de Goede action = frame_body[1]; 1907554c0a3aSHans de Goede switch (action) { 1908554c0a3aSHans de Goede case ACT_PUBLIC_VENDOR: 1909554c0a3aSHans de Goede ret = on_action_public_vendor(precv_frame); 1910554c0a3aSHans de Goede break; 1911554c0a3aSHans de Goede default: 1912554c0a3aSHans de Goede ret = on_action_public_default(precv_frame, action); 1913554c0a3aSHans de Goede break; 1914554c0a3aSHans de Goede } 1915554c0a3aSHans de Goede 1916554c0a3aSHans de Goede exit: 1917554c0a3aSHans de Goede return ret; 1918554c0a3aSHans de Goede } 1919554c0a3aSHans de Goede 1920554c0a3aSHans de Goede unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame) 1921554c0a3aSHans de Goede { 1922554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1923554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 1924554c0a3aSHans de Goede u8 category, action; 1925554c0a3aSHans de Goede 1926554c0a3aSHans de Goede /* check RA matches or not */ 1927554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN)) 1928554c0a3aSHans de Goede goto exit; 1929554c0a3aSHans de Goede 1930554c0a3aSHans de Goede category = frame_body[0]; 1931554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_HT) 1932554c0a3aSHans de Goede goto exit; 1933554c0a3aSHans de Goede 1934554c0a3aSHans de Goede action = frame_body[1]; 1935554c0a3aSHans de Goede switch (action) { 1936a9d87638SRoss Schmidt case WLAN_HT_ACTION_COMPRESSED_BF: 1937554c0a3aSHans de Goede break; 1938554c0a3aSHans de Goede default: 1939554c0a3aSHans de Goede break; 1940554c0a3aSHans de Goede } 1941554c0a3aSHans de Goede 1942554c0a3aSHans de Goede exit: 1943554c0a3aSHans de Goede 1944554c0a3aSHans de Goede return _SUCCESS; 1945554c0a3aSHans de Goede } 1946554c0a3aSHans de Goede 1947554c0a3aSHans de Goede unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv_frame) 1948554c0a3aSHans de Goede { 1949554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1950554c0a3aSHans de Goede struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; 1951554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 1952554c0a3aSHans de Goede unsigned short tid; 1953554c0a3aSHans de Goede 1954554c0a3aSHans de Goede switch (pframe[WLAN_HDR_A3_LEN+1]) { 1955554c0a3aSHans de Goede case 0: /* SA Query req */ 1956554c0a3aSHans de Goede memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short)); 1957554c0a3aSHans de Goede issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid); 1958554c0a3aSHans de Goede break; 1959554c0a3aSHans de Goede 1960554c0a3aSHans de Goede case 1: /* SA Query rsp */ 1961554c0a3aSHans de Goede del_timer_sync(&pmlmeext->sa_query_timer); 1962554c0a3aSHans de Goede break; 1963554c0a3aSHans de Goede default: 1964554c0a3aSHans de Goede break; 1965554c0a3aSHans de Goede } 1966554c0a3aSHans de Goede if (0) { 1967554c0a3aSHans de Goede int pp; 1968c926f022SSimran Singhal 1969554c0a3aSHans de Goede printk("pattrib->pktlen = %d =>", pattrib->pkt_len); 1970554c0a3aSHans de Goede for (pp = 0; pp < pattrib->pkt_len; pp++) 1971554c0a3aSHans de Goede printk(" %02x ", pframe[pp]); 1972554c0a3aSHans de Goede printk("\n"); 1973554c0a3aSHans de Goede } 1974554c0a3aSHans de Goede 1975554c0a3aSHans de Goede return _SUCCESS; 1976554c0a3aSHans de Goede } 1977554c0a3aSHans de Goede 1978554c0a3aSHans de Goede unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame) 1979554c0a3aSHans de Goede { 1980554c0a3aSHans de Goede int i; 1981554c0a3aSHans de Goede unsigned char category; 1982554c0a3aSHans de Goede struct action_handler *ptable; 1983554c0a3aSHans de Goede unsigned char *frame_body; 1984554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1985554c0a3aSHans de Goede 1986554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1987554c0a3aSHans de Goede 1988554c0a3aSHans de Goede category = frame_body[0]; 1989554c0a3aSHans de Goede 199060db8d10SJérémy Lefaure for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) { 1991554c0a3aSHans de Goede ptable = &OnAction_tbl[i]; 1992554c0a3aSHans de Goede 1993554c0a3aSHans de Goede if (category == ptable->num) 1994554c0a3aSHans de Goede ptable->func(padapter, precv_frame); 1995554c0a3aSHans de Goede 1996554c0a3aSHans de Goede } 1997554c0a3aSHans de Goede 1998554c0a3aSHans de Goede return _SUCCESS; 1999554c0a3aSHans de Goede 2000554c0a3aSHans de Goede } 2001554c0a3aSHans de Goede 2002554c0a3aSHans de Goede unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame) 2003554c0a3aSHans de Goede { 2004554c0a3aSHans de Goede return _SUCCESS; 2005554c0a3aSHans de Goede } 2006554c0a3aSHans de Goede 2007554c0a3aSHans de Goede static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once) 2008554c0a3aSHans de Goede { 2009554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2010554c0a3aSHans de Goede struct xmit_buf *pxmitbuf; 2011554c0a3aSHans de Goede 2012554c0a3aSHans de Goede if (once) 2013554c0a3aSHans de Goede pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv); 2014554c0a3aSHans de Goede else 2015554c0a3aSHans de Goede pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv); 2016554c0a3aSHans de Goede 2017e427bdd8SFabio Aiuto if (!pmgntframe) 2018554c0a3aSHans de Goede goto exit; 2019554c0a3aSHans de Goede 2020554c0a3aSHans de Goede pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv); 2021554c0a3aSHans de Goede if (pxmitbuf == NULL) { 2022554c0a3aSHans de Goede rtw_free_xmitframe(pxmitpriv, pmgntframe); 2023554c0a3aSHans de Goede pmgntframe = NULL; 2024554c0a3aSHans de Goede goto exit; 2025554c0a3aSHans de Goede } 2026554c0a3aSHans de Goede 2027554c0a3aSHans de Goede pmgntframe->frame_tag = MGNT_FRAMETAG; 2028554c0a3aSHans de Goede pmgntframe->pxmitbuf = pxmitbuf; 2029554c0a3aSHans de Goede pmgntframe->buf_addr = pxmitbuf->pbuf; 2030554c0a3aSHans de Goede pxmitbuf->priv_data = pmgntframe; 2031554c0a3aSHans de Goede 2032554c0a3aSHans de Goede exit: 2033554c0a3aSHans de Goede return pmgntframe; 2034554c0a3aSHans de Goede 2035554c0a3aSHans de Goede } 2036554c0a3aSHans de Goede 2037554c0a3aSHans de Goede inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv) 2038554c0a3aSHans de Goede { 2039554c0a3aSHans de Goede return _alloc_mgtxmitframe(pxmitpriv, false); 2040554c0a3aSHans de Goede } 2041554c0a3aSHans de Goede 2042554c0a3aSHans de Goede /**************************************************************************** 2043554c0a3aSHans de Goede 204468468503SAndreas Hellmich Following are some TX functions for WiFi MLME 2045554c0a3aSHans de Goede 2046554c0a3aSHans de Goede *****************************************************************************/ 2047554c0a3aSHans de Goede 2048554c0a3aSHans de Goede void update_mgnt_tx_rate(struct adapter *padapter, u8 rate) 2049554c0a3aSHans de Goede { 2050554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2051554c0a3aSHans de Goede 2052554c0a3aSHans de Goede pmlmeext->tx_rate = rate; 2053554c0a3aSHans de Goede } 2054554c0a3aSHans de Goede 2055554c0a3aSHans de Goede void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib) 2056554c0a3aSHans de Goede { 2057554c0a3aSHans de Goede u8 wireless_mode; 2058554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2059554c0a3aSHans de Goede 2060554c0a3aSHans de Goede /* memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */ 2061554c0a3aSHans de Goede 2062554c0a3aSHans de Goede pattrib->hdrlen = 24; 2063554c0a3aSHans de Goede pattrib->nr_frags = 1; 2064554c0a3aSHans de Goede pattrib->priority = 7; 2065554c0a3aSHans de Goede pattrib->mac_id = 0; 2066554c0a3aSHans de Goede pattrib->qsel = 0x12; 2067554c0a3aSHans de Goede 2068554c0a3aSHans de Goede pattrib->pktlen = 0; 2069554c0a3aSHans de Goede 2070554c0a3aSHans de Goede if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB) 2071554c0a3aSHans de Goede wireless_mode = WIRELESS_11B; 2072554c0a3aSHans de Goede else 2073554c0a3aSHans de Goede wireless_mode = WIRELESS_11G; 2074554c0a3aSHans de Goede pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode); 2075554c0a3aSHans de Goede pattrib->rate = pmlmeext->tx_rate; 2076554c0a3aSHans de Goede 2077554c0a3aSHans de Goede pattrib->encrypt = _NO_PRIVACY_; 2078554c0a3aSHans de Goede pattrib->bswenc = false; 2079554c0a3aSHans de Goede 2080554c0a3aSHans de Goede pattrib->qos_en = false; 2081554c0a3aSHans de Goede pattrib->ht_en = false; 2082554c0a3aSHans de Goede pattrib->bwmode = CHANNEL_WIDTH_20; 2083554c0a3aSHans de Goede pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 2084554c0a3aSHans de Goede pattrib->sgi = false; 2085554c0a3aSHans de Goede 2086554c0a3aSHans de Goede pattrib->seqnum = pmlmeext->mgnt_seq; 2087554c0a3aSHans de Goede 2088554c0a3aSHans de Goede pattrib->retry_ctrl = true; 2089554c0a3aSHans de Goede 2090554c0a3aSHans de Goede pattrib->mbssid = 0; 2091554c0a3aSHans de Goede 2092554c0a3aSHans de Goede } 2093554c0a3aSHans de Goede 2094554c0a3aSHans de Goede void update_mgntframe_attrib_addr(struct adapter *padapter, struct xmit_frame *pmgntframe) 2095554c0a3aSHans de Goede { 2096554c0a3aSHans de Goede u8 *pframe; 2097554c0a3aSHans de Goede struct pkt_attrib *pattrib = &pmgntframe->attrib; 2098554c0a3aSHans de Goede 2099554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2100554c0a3aSHans de Goede 2101554c0a3aSHans de Goede memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN); 2102554c0a3aSHans de Goede memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN); 2103554c0a3aSHans de Goede } 2104554c0a3aSHans de Goede 2105554c0a3aSHans de Goede void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe) 2106554c0a3aSHans de Goede { 21070ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 21080ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2109554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2110554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2111554c0a3aSHans de Goede return; 2112554c0a3aSHans de Goede } 2113554c0a3aSHans de Goede 2114554c0a3aSHans de Goede rtw_hal_mgnt_xmit(padapter, pmgntframe); 2115554c0a3aSHans de Goede } 2116554c0a3aSHans de Goede 2117554c0a3aSHans de Goede s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms) 2118554c0a3aSHans de Goede { 2119554c0a3aSHans de Goede s32 ret = _FAIL; 212000d5865cSMarco Cesati unsigned long irqL; 2121554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 2122554c0a3aSHans de Goede struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf; 2123554c0a3aSHans de Goede struct submit_ctx sctx; 2124554c0a3aSHans de Goede 21250ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 21260ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2127554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2128554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2129554c0a3aSHans de Goede return ret; 2130554c0a3aSHans de Goede } 2131554c0a3aSHans de Goede 2132554c0a3aSHans de Goede rtw_sctx_init(&sctx, timeout_ms); 2133554c0a3aSHans de Goede pxmitbuf->sctx = &sctx; 2134554c0a3aSHans de Goede 2135554c0a3aSHans de Goede ret = rtw_hal_mgnt_xmit(padapter, pmgntframe); 2136554c0a3aSHans de Goede 2137554c0a3aSHans de Goede if (ret == _SUCCESS) 2138554c0a3aSHans de Goede ret = rtw_sctx_wait(&sctx, __func__); 2139554c0a3aSHans de Goede 2140554c0a3aSHans de Goede spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); 2141554c0a3aSHans de Goede pxmitbuf->sctx = NULL; 2142554c0a3aSHans de Goede spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL); 2143554c0a3aSHans de Goede 2144554c0a3aSHans de Goede return ret; 2145554c0a3aSHans de Goede } 2146554c0a3aSHans de Goede 2147554c0a3aSHans de Goede s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe) 2148554c0a3aSHans de Goede { 214940d4aa0fSShreeya Patel static u8 seq_no; 2150554c0a3aSHans de Goede s32 ret = _FAIL; 2151554c0a3aSHans de Goede u32 timeout_ms = 500;/* 500ms */ 2152554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 2153554c0a3aSHans de Goede 21540ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 21550ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2156554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2157554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2158554c0a3aSHans de Goede return -1; 2159554c0a3aSHans de Goede } 2160554c0a3aSHans de Goede 2161554c0a3aSHans de Goede if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex) == 0) { 2162554c0a3aSHans de Goede pxmitpriv->ack_tx = true; 2163554c0a3aSHans de Goede pxmitpriv->seq_no = seq_no++; 2164554c0a3aSHans de Goede pmgntframe->ack_report = 1; 2165a65f0d18SVatsala Narang if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) 2166554c0a3aSHans de Goede ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms); 2167554c0a3aSHans de Goede 2168554c0a3aSHans de Goede pxmitpriv->ack_tx = false; 2169554c0a3aSHans de Goede mutex_unlock(&pxmitpriv->ack_tx_mutex); 2170554c0a3aSHans de Goede } 2171554c0a3aSHans de Goede 2172554c0a3aSHans de Goede return ret; 2173554c0a3aSHans de Goede } 2174554c0a3aSHans de Goede 2175554c0a3aSHans de Goede static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) 2176554c0a3aSHans de Goede { 2177554c0a3aSHans de Goede u8 *ssid_ie; 2178d495c550SMarco Cesati signed int ssid_len_ori; 2179554c0a3aSHans de Goede int len_diff = 0; 2180554c0a3aSHans de Goede 2181554c0a3aSHans de Goede ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len); 2182554c0a3aSHans de Goede 2183554c0a3aSHans de Goede if (ssid_ie && ssid_len_ori > 0) { 2184554c0a3aSHans de Goede switch (hidden_ssid_mode) { 2185554c0a3aSHans de Goede case 1: 2186554c0a3aSHans de Goede { 2187554c0a3aSHans de Goede u8 *next_ie = ssid_ie + 2 + ssid_len_ori; 2188554c0a3aSHans de Goede u32 remain_len = 0; 2189554c0a3aSHans de Goede 2190554c0a3aSHans de Goede remain_len = ies_len - (next_ie-ies); 2191554c0a3aSHans de Goede 2192554c0a3aSHans de Goede ssid_ie[1] = 0; 2193554c0a3aSHans de Goede memcpy(ssid_ie+2, next_ie, remain_len); 2194554c0a3aSHans de Goede len_diff -= ssid_len_ori; 2195554c0a3aSHans de Goede 2196554c0a3aSHans de Goede break; 2197554c0a3aSHans de Goede } 2198554c0a3aSHans de Goede case 2: 2199554c0a3aSHans de Goede memset(&ssid_ie[2], 0, ssid_len_ori); 2200554c0a3aSHans de Goede break; 2201554c0a3aSHans de Goede default: 2202554c0a3aSHans de Goede break; 2203554c0a3aSHans de Goede } 2204554c0a3aSHans de Goede } 2205554c0a3aSHans de Goede 2206554c0a3aSHans de Goede return len_diff; 2207554c0a3aSHans de Goede } 2208554c0a3aSHans de Goede 2209554c0a3aSHans de Goede void issue_beacon(struct adapter *padapter, int timeout_ms) 2210554c0a3aSHans de Goede { 2211554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2212554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2213554c0a3aSHans de Goede unsigned char *pframe; 2214554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2215554c0a3aSHans de Goede __le16 *fctrl; 2216554c0a3aSHans de Goede unsigned int rate_len; 2217554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2218554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2219554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2220554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2221554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 2222554c0a3aSHans de Goede u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 2223554c0a3aSHans de Goede 2224554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2225709c8e49SFabio Aiuto if (!pmgntframe) 2226554c0a3aSHans de Goede return; 2227554c0a3aSHans de Goede 2228554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->bcn_update_lock); 2229554c0a3aSHans de Goede 2230554c0a3aSHans de Goede /* update attribute */ 2231554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2232554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2233554c0a3aSHans de Goede pattrib->qsel = 0x10; 2234554c0a3aSHans de Goede 2235554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2236554c0a3aSHans de Goede 2237554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2238554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2239554c0a3aSHans de Goede 2240554c0a3aSHans de Goede 2241554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2242554c0a3aSHans de Goede *(fctrl) = 0; 2243554c0a3aSHans de Goede 2244554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); 2245554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 2246554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); 2247554c0a3aSHans de Goede 2248554c0a3aSHans de Goede SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); 2249554c0a3aSHans de Goede /* pmlmeext->mgnt_seq++; */ 2250554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_BEACON); 2251554c0a3aSHans de Goede 2252554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2253554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2254554c0a3aSHans de Goede 2255554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { 2256554c0a3aSHans de Goede { 2257554c0a3aSHans de Goede int len_diff; 2258c926f022SSimran Singhal 2259554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, cur_network->IELength); 22605641eeecSRoss Schmidt len_diff = update_hidden_ssid(pframe+_BEACON_IE_OFFSET_, 22615641eeecSRoss Schmidt cur_network->IELength-_BEACON_IE_OFFSET_, 22625641eeecSRoss Schmidt pmlmeinfo->hidden_ssid_mode); 2263554c0a3aSHans de Goede pframe += (cur_network->IELength+len_diff); 2264554c0a3aSHans de Goede pattrib->pktlen += (cur_network->IELength+len_diff); 2265554c0a3aSHans de Goede } 2266554c0a3aSHans de Goede 2267554c0a3aSHans de Goede { 2268554c0a3aSHans de Goede u8 *wps_ie; 2269554c0a3aSHans de Goede uint wps_ielen; 2270554c0a3aSHans de Goede u8 sr = 0; 2271c926f022SSimran Singhal 2272554c0a3aSHans de Goede wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_, 2273554c0a3aSHans de Goede pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen); 2274554c0a3aSHans de Goede if (wps_ie && wps_ielen > 0) { 2275554c0a3aSHans de Goede rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); 2276554c0a3aSHans de Goede } 2277554c0a3aSHans de Goede if (sr != 0) 2278554c0a3aSHans de Goede set_fwstate(pmlmepriv, WIFI_UNDER_WPS); 2279554c0a3aSHans de Goede else 2280554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS); 2281554c0a3aSHans de Goede } 2282554c0a3aSHans de Goede 2283554c0a3aSHans de Goede goto _issue_bcn; 2284554c0a3aSHans de Goede 2285554c0a3aSHans de Goede } 2286554c0a3aSHans de Goede 2287554c0a3aSHans de Goede /* below for ad-hoc mode */ 2288554c0a3aSHans de Goede 2289554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 2290554c0a3aSHans de Goede pframe += 8; 2291554c0a3aSHans de Goede pattrib->pktlen += 8; 2292554c0a3aSHans de Goede 2293554c0a3aSHans de Goede /* beacon interval: 2 bytes */ 2294554c0a3aSHans de Goede 2295554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 2296554c0a3aSHans de Goede 2297554c0a3aSHans de Goede pframe += 2; 2298554c0a3aSHans de Goede pattrib->pktlen += 2; 2299554c0a3aSHans de Goede 2300554c0a3aSHans de Goede /* capability info: 2 bytes */ 2301554c0a3aSHans de Goede 2302554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); 2303554c0a3aSHans de Goede 2304554c0a3aSHans de Goede pframe += 2; 2305554c0a3aSHans de Goede pattrib->pktlen += 2; 2306554c0a3aSHans de Goede 2307554c0a3aSHans de Goede /* SSID */ 23083f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); 2309554c0a3aSHans de Goede 2310554c0a3aSHans de Goede /* supported rates... */ 2311554c0a3aSHans de Goede rate_len = rtw_get_rateset_len(cur_network->SupportedRates); 2312c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); 2313554c0a3aSHans de Goede 2314554c0a3aSHans de Goede /* DS parameter set */ 23158f6a9446SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen); 2316554c0a3aSHans de Goede 2317554c0a3aSHans de Goede /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */ 2318554c0a3aSHans de Goede { 2319554c0a3aSHans de Goede u8 erpinfo = 0; 2320554c0a3aSHans de Goede u32 ATIMWindow; 2321554c0a3aSHans de Goede /* IBSS Parameter Set... */ 2322554c0a3aSHans de Goede /* ATIMWindow = cur->Configuration.ATIMWindow; */ 2323554c0a3aSHans de Goede ATIMWindow = 0; 2324e6038a48SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); 2325554c0a3aSHans de Goede 2326554c0a3aSHans de Goede /* ERP IE */ 23277bd332ecSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen); 2328554c0a3aSHans de Goede } 2329554c0a3aSHans de Goede 2330554c0a3aSHans de Goede 2331554c0a3aSHans de Goede /* EXTERNDED SUPPORTED RATE */ 2332554c0a3aSHans de Goede if (rate_len > 8) { 233300f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); 2334554c0a3aSHans de Goede } 2335554c0a3aSHans de Goede 2336554c0a3aSHans de Goede 2337554c0a3aSHans de Goede /* todo:HT for adhoc */ 2338554c0a3aSHans de Goede 2339554c0a3aSHans de Goede _issue_bcn: 2340554c0a3aSHans de Goede 2341554c0a3aSHans de Goede pmlmepriv->update_bcn = false; 2342554c0a3aSHans de Goede 2343554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->bcn_update_lock); 2344554c0a3aSHans de Goede 2345709c8e49SFabio Aiuto if ((pattrib->pktlen + TXDESC_SIZE) > 512) 2346554c0a3aSHans de Goede return; 2347554c0a3aSHans de Goede 2348554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2349554c0a3aSHans de Goede 2350554c0a3aSHans de Goede if (timeout_ms > 0) 2351554c0a3aSHans de Goede dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms); 2352554c0a3aSHans de Goede else 2353554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2354554c0a3aSHans de Goede 2355554c0a3aSHans de Goede } 2356554c0a3aSHans de Goede 2357554c0a3aSHans de Goede void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq) 2358554c0a3aSHans de Goede { 2359554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2360554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2361554c0a3aSHans de Goede unsigned char *pframe; 2362554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2363554c0a3aSHans de Goede __le16 *fctrl; 2364554c0a3aSHans de Goede unsigned char *mac, *bssid; 2365554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2366554c0a3aSHans de Goede 2367554c0a3aSHans de Goede u8 *pwps_ie; 2368554c0a3aSHans de Goede uint wps_ielen; 2369554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2370554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2371554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2372554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 2373554c0a3aSHans de Goede unsigned int rate_len; 2374554c0a3aSHans de Goede 2375554c0a3aSHans de Goede if (da == NULL) 2376554c0a3aSHans de Goede return; 2377554c0a3aSHans de Goede 2378554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2379e427bdd8SFabio Aiuto if (!pmgntframe) 2380554c0a3aSHans de Goede return; 2381554c0a3aSHans de Goede 2382554c0a3aSHans de Goede /* update attribute */ 2383554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2384554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2385554c0a3aSHans de Goede 2386554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2387554c0a3aSHans de Goede 2388554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2389554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2390554c0a3aSHans de Goede 2391554c0a3aSHans de Goede mac = myid(&(padapter->eeprompriv)); 2392554c0a3aSHans de Goede bssid = cur_network->MacAddress; 2393554c0a3aSHans de Goede 2394554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2395554c0a3aSHans de Goede *(fctrl) = 0; 2396554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 2397554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, mac, ETH_ALEN); 2398554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); 2399554c0a3aSHans de Goede 2400554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2401554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2402554c0a3aSHans de Goede SetFrameSubType(fctrl, WIFI_PROBERSP); 2403554c0a3aSHans de Goede 2404554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 2405554c0a3aSHans de Goede pattrib->pktlen = pattrib->hdrlen; 2406554c0a3aSHans de Goede pframe += pattrib->hdrlen; 2407554c0a3aSHans de Goede 2408554c0a3aSHans de Goede 2409554c0a3aSHans de Goede if (cur_network->IELength > MAX_IE_SZ) 2410554c0a3aSHans de Goede return; 2411554c0a3aSHans de Goede 2412554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { 2413554c0a3aSHans de Goede pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen); 2414554c0a3aSHans de Goede 2415554c0a3aSHans de Goede /* inerset & update wps_probe_resp_ie */ 241634557e23SIzabela Bakollari if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) { 2417554c0a3aSHans de Goede uint wps_offset, remainder_ielen; 2418554c0a3aSHans de Goede u8 *premainder_ie; 2419554c0a3aSHans de Goede 2420554c0a3aSHans de Goede wps_offset = (uint)(pwps_ie - cur_network->IEs); 2421554c0a3aSHans de Goede 2422554c0a3aSHans de Goede premainder_ie = pwps_ie + wps_ielen; 2423554c0a3aSHans de Goede 2424554c0a3aSHans de Goede remainder_ielen = cur_network->IELength - wps_offset - wps_ielen; 2425554c0a3aSHans de Goede 2426554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, wps_offset); 2427554c0a3aSHans de Goede pframe += wps_offset; 2428554c0a3aSHans de Goede pattrib->pktlen += wps_offset; 2429554c0a3aSHans de Goede 2430554c0a3aSHans de Goede wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */ 2431554c0a3aSHans de Goede if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) { 2432554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2); 2433554c0a3aSHans de Goede pframe += wps_ielen+2; 2434554c0a3aSHans de Goede pattrib->pktlen += wps_ielen+2; 2435554c0a3aSHans de Goede } 2436554c0a3aSHans de Goede 2437554c0a3aSHans de Goede if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) { 2438554c0a3aSHans de Goede memcpy(pframe, premainder_ie, remainder_ielen); 2439554c0a3aSHans de Goede pframe += remainder_ielen; 2440554c0a3aSHans de Goede pattrib->pktlen += remainder_ielen; 2441554c0a3aSHans de Goede } 2442554c0a3aSHans de Goede } else { 2443554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, cur_network->IELength); 2444554c0a3aSHans de Goede pframe += cur_network->IELength; 2445554c0a3aSHans de Goede pattrib->pktlen += cur_network->IELength; 2446554c0a3aSHans de Goede } 2447554c0a3aSHans de Goede 2448554c0a3aSHans de Goede /* retrieve SSID IE from cur_network->Ssid */ 2449554c0a3aSHans de Goede { 2450554c0a3aSHans de Goede u8 *ssid_ie; 2451d495c550SMarco Cesati signed int ssid_ielen; 2452d495c550SMarco Cesati signed int ssid_ielen_diff; 2453554c0a3aSHans de Goede u8 buf[MAX_IE_SZ]; 2454554c0a3aSHans de Goede u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr); 2455554c0a3aSHans de Goede 24563f15277bSRoss Schmidt ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, WLAN_EID_SSID, &ssid_ielen, 2457554c0a3aSHans de Goede (pframe-ies)-_FIXED_IE_LENGTH_); 2458554c0a3aSHans de Goede 2459554c0a3aSHans de Goede ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen; 2460554c0a3aSHans de Goede 2461554c0a3aSHans de Goede if (ssid_ie && cur_network->Ssid.SsidLength) { 2462554c0a3aSHans de Goede uint remainder_ielen; 2463554c0a3aSHans de Goede u8 *remainder_ie; 2464c926f022SSimran Singhal 2465554c0a3aSHans de Goede remainder_ie = ssid_ie+2; 2466554c0a3aSHans de Goede remainder_ielen = (pframe-remainder_ie); 2467554c0a3aSHans de Goede 2468554c0a3aSHans de Goede if (remainder_ielen > MAX_IE_SZ) { 2469554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter)); 2470554c0a3aSHans de Goede remainder_ielen = MAX_IE_SZ; 2471554c0a3aSHans de Goede } 2472554c0a3aSHans de Goede 2473554c0a3aSHans de Goede memcpy(buf, remainder_ie, remainder_ielen); 2474554c0a3aSHans de Goede memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen); 2475554c0a3aSHans de Goede *(ssid_ie+1) = cur_network->Ssid.SsidLength; 2476554c0a3aSHans de Goede memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength); 2477554c0a3aSHans de Goede 2478554c0a3aSHans de Goede pframe += ssid_ielen_diff; 2479554c0a3aSHans de Goede pattrib->pktlen += ssid_ielen_diff; 2480554c0a3aSHans de Goede } 2481554c0a3aSHans de Goede } 2482554c0a3aSHans de Goede } else { 2483554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 2484554c0a3aSHans de Goede pframe += 8; 2485554c0a3aSHans de Goede pattrib->pktlen += 8; 2486554c0a3aSHans de Goede 2487554c0a3aSHans de Goede /* beacon interval: 2 bytes */ 2488554c0a3aSHans de Goede 2489554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 2490554c0a3aSHans de Goede 2491554c0a3aSHans de Goede pframe += 2; 2492554c0a3aSHans de Goede pattrib->pktlen += 2; 2493554c0a3aSHans de Goede 2494554c0a3aSHans de Goede /* capability info: 2 bytes */ 2495554c0a3aSHans de Goede 2496554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); 2497554c0a3aSHans de Goede 2498554c0a3aSHans de Goede pframe += 2; 2499554c0a3aSHans de Goede pattrib->pktlen += 2; 2500554c0a3aSHans de Goede 2501554c0a3aSHans de Goede /* below for ad-hoc mode */ 2502554c0a3aSHans de Goede 2503554c0a3aSHans de Goede /* SSID */ 25043f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); 2505554c0a3aSHans de Goede 2506554c0a3aSHans de Goede /* supported rates... */ 2507554c0a3aSHans de Goede rate_len = rtw_get_rateset_len(cur_network->SupportedRates); 2508c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); 2509554c0a3aSHans de Goede 2510554c0a3aSHans de Goede /* DS parameter set */ 25118f6a9446SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen); 2512554c0a3aSHans de Goede 2513554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 2514554c0a3aSHans de Goede u8 erpinfo = 0; 2515554c0a3aSHans de Goede u32 ATIMWindow; 2516554c0a3aSHans de Goede /* IBSS Parameter Set... */ 2517554c0a3aSHans de Goede /* ATIMWindow = cur->Configuration.ATIMWindow; */ 2518554c0a3aSHans de Goede ATIMWindow = 0; 2519e6038a48SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); 2520554c0a3aSHans de Goede 2521554c0a3aSHans de Goede /* ERP IE */ 25227bd332ecSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen); 2523554c0a3aSHans de Goede } 2524554c0a3aSHans de Goede 2525554c0a3aSHans de Goede 2526554c0a3aSHans de Goede /* EXTERNDED SUPPORTED RATE */ 2527554c0a3aSHans de Goede if (rate_len > 8) { 252800f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); 2529554c0a3aSHans de Goede } 2530554c0a3aSHans de Goede 2531554c0a3aSHans de Goede 2532554c0a3aSHans de Goede /* todo:HT for adhoc */ 2533554c0a3aSHans de Goede 2534554c0a3aSHans de Goede } 2535554c0a3aSHans de Goede 2536554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2537554c0a3aSHans de Goede 2538554c0a3aSHans de Goede 2539554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2540554c0a3aSHans de Goede 2541554c0a3aSHans de Goede return; 2542554c0a3aSHans de Goede 2543554c0a3aSHans de Goede } 2544554c0a3aSHans de Goede 254542b3b621SAishwarya Pant static int _issue_probereq(struct adapter *padapter, 254642b3b621SAishwarya Pant struct ndis_802_11_ssid *pssid, 254742b3b621SAishwarya Pant u8 *da, u8 ch, bool append_wps, bool wait_ack) 2548554c0a3aSHans de Goede { 2549554c0a3aSHans de Goede int ret = _FAIL; 2550554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2551554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2552554c0a3aSHans de Goede unsigned char *pframe; 2553554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2554554c0a3aSHans de Goede __le16 *fctrl; 2555554c0a3aSHans de Goede unsigned char *mac; 2556554c0a3aSHans de Goede unsigned char bssrate[NumRates]; 2557554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2558554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2559554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2560554c0a3aSHans de Goede int bssrate_len = 0; 2561554c0a3aSHans de Goede u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 2562554c0a3aSHans de Goede 2563554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 256441452327SVatsala Narang if (!pmgntframe) 2565554c0a3aSHans de Goede goto exit; 2566554c0a3aSHans de Goede 2567554c0a3aSHans de Goede /* update attribute */ 2568554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2569554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2570554c0a3aSHans de Goede 2571554c0a3aSHans de Goede 2572554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2573554c0a3aSHans de Goede 2574554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2575554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2576554c0a3aSHans de Goede 2577554c0a3aSHans de Goede mac = myid(&(padapter->eeprompriv)); 2578554c0a3aSHans de Goede 2579554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2580554c0a3aSHans de Goede *(fctrl) = 0; 2581554c0a3aSHans de Goede 2582554c0a3aSHans de Goede if (da) { 2583554c0a3aSHans de Goede /* unicast probe request frame */ 2584554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 2585554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, da, ETH_ALEN); 2586554c0a3aSHans de Goede } else { 2587554c0a3aSHans de Goede /* broadcast probe request frame */ 2588554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); 2589554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN); 2590554c0a3aSHans de Goede } 2591554c0a3aSHans de Goede 2592554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, mac, ETH_ALEN); 2593554c0a3aSHans de Goede 2594554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2595554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2596554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_PROBEREQ); 2597554c0a3aSHans de Goede 2598554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2599554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2600554c0a3aSHans de Goede 2601554c0a3aSHans de Goede if (pssid) 26023f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen)); 2603554c0a3aSHans de Goede else 26043f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, 0, NULL, &(pattrib->pktlen)); 2605554c0a3aSHans de Goede 2606554c0a3aSHans de Goede get_rate_set(padapter, bssrate, &bssrate_len); 2607554c0a3aSHans de Goede 2608554c0a3aSHans de Goede if (bssrate_len > 8) { 2609c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen)); 261000f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); 2611554c0a3aSHans de Goede } else { 2612c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen)); 2613554c0a3aSHans de Goede } 2614554c0a3aSHans de Goede 2615554c0a3aSHans de Goede if (ch) 26168f6a9446SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, &ch, &pattrib->pktlen); 2617554c0a3aSHans de Goede 2618554c0a3aSHans de Goede if (append_wps) { 2619554c0a3aSHans de Goede /* add wps_ie for wps2.0 */ 2620554c0a3aSHans de Goede if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) { 2621554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len); 2622554c0a3aSHans de Goede pframe += pmlmepriv->wps_probe_req_ie_len; 2623554c0a3aSHans de Goede pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; 2624554c0a3aSHans de Goede } 2625554c0a3aSHans de Goede } 2626554c0a3aSHans de Goede 2627554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2628554c0a3aSHans de Goede 2629554c0a3aSHans de Goede if (wait_ack) { 2630554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 2631554c0a3aSHans de Goede } else { 2632554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2633554c0a3aSHans de Goede ret = _SUCCESS; 2634554c0a3aSHans de Goede } 2635554c0a3aSHans de Goede 2636554c0a3aSHans de Goede exit: 2637554c0a3aSHans de Goede return ret; 2638554c0a3aSHans de Goede } 2639554c0a3aSHans de Goede 2640554c0a3aSHans de Goede inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da) 2641554c0a3aSHans de Goede { 2642554c0a3aSHans de Goede _issue_probereq(padapter, pssid, da, 0, 1, false); 2643554c0a3aSHans de Goede } 2644554c0a3aSHans de Goede 2645554c0a3aSHans de Goede int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps, 2646554c0a3aSHans de Goede int try_cnt, int wait_ms) 2647554c0a3aSHans de Goede { 2648554c0a3aSHans de Goede int ret; 2649554c0a3aSHans de Goede int i = 0; 2650554c0a3aSHans de Goede 2651554c0a3aSHans de Goede do { 26529cdb1928SSaiyam Doshi ret = _issue_probereq(padapter, pssid, da, ch, append_wps, 26539cdb1928SSaiyam Doshi wait_ms > 0); 2654554c0a3aSHans de Goede 2655554c0a3aSHans de Goede i++; 2656554c0a3aSHans de Goede 2657554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 2658554c0a3aSHans de Goede break; 2659554c0a3aSHans de Goede 2660554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 2661554c0a3aSHans de Goede msleep(wait_ms); 2662554c0a3aSHans de Goede 2663554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 2664554c0a3aSHans de Goede 2665554c0a3aSHans de Goede if (ret != _FAIL) { 2666554c0a3aSHans de Goede ret = _SUCCESS; 2667554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 2668554c0a3aSHans de Goede goto exit; 2669554c0a3aSHans de Goede #endif 2670554c0a3aSHans de Goede } 2671554c0a3aSHans de Goede 2672554c0a3aSHans de Goede exit: 2673554c0a3aSHans de Goede return ret; 2674554c0a3aSHans de Goede } 2675554c0a3aSHans de Goede 267668468503SAndreas Hellmich /* if psta == NULL, indicate we are station(client) now... */ 2677554c0a3aSHans de Goede void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status) 2678554c0a3aSHans de Goede { 2679554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2680554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2681554c0a3aSHans de Goede unsigned char *pframe; 2682554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2683554c0a3aSHans de Goede __le16 *fctrl; 2684554c0a3aSHans de Goede unsigned int val32; 2685554c0a3aSHans de Goede unsigned short val16; 2686554c0a3aSHans de Goede int use_shared_key = 0; 2687554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2688554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2689554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2690554c0a3aSHans de Goede __le16 le_tmp; 2691554c0a3aSHans de Goede 2692554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2693554c0a3aSHans de Goede if (pmgntframe == NULL) 2694554c0a3aSHans de Goede return; 2695554c0a3aSHans de Goede 2696554c0a3aSHans de Goede /* update attribute */ 2697554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2698554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2699554c0a3aSHans de Goede 2700554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2701554c0a3aSHans de Goede 2702554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2703554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2704554c0a3aSHans de Goede 2705554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2706554c0a3aSHans de Goede *(fctrl) = 0; 2707554c0a3aSHans de Goede 2708554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2709554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2710554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_AUTH); 2711554c0a3aSHans de Goede 2712554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2713554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2714554c0a3aSHans de Goede 2715554c0a3aSHans de Goede 2716554c0a3aSHans de Goede if (psta) { /* for AP mode */ 2717554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN); 2718554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 2719554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN); 2720554c0a3aSHans de Goede 2721554c0a3aSHans de Goede /* setting auth algo number */ 2722554c0a3aSHans de Goede val16 = (u16)psta->authalg; 2723554c0a3aSHans de Goede 27246d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 2725554c0a3aSHans de Goede val16 = 0; 2726554c0a3aSHans de Goede 2727554c0a3aSHans de Goede if (val16) 2728554c0a3aSHans de Goede use_shared_key = 1; 2729554c0a3aSHans de Goede 2730554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 2731554c0a3aSHans de Goede 2732554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2733554c0a3aSHans de Goede 2734554c0a3aSHans de Goede /* setting auth seq number */ 2735554c0a3aSHans de Goede val16 = (u16)psta->auth_seq; 2736554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 2737554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2738554c0a3aSHans de Goede 2739554c0a3aSHans de Goede /* setting status code... */ 2740554c0a3aSHans de Goede val16 = status; 2741554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 2742554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2743554c0a3aSHans de Goede 2744554c0a3aSHans de Goede /* added challenging text... */ 2745554c0a3aSHans de Goede if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) 274638caee0aSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, psta->chg_txt, &(pattrib->pktlen)); 2747554c0a3aSHans de Goede 2748554c0a3aSHans de Goede } else { 2749554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); 2750554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); 2751554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); 2752554c0a3aSHans de Goede 2753554c0a3aSHans de Goede /* setting auth algo number */ 2754554c0a3aSHans de Goede val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */ 2755554c0a3aSHans de Goede if (val16) { 2756554c0a3aSHans de Goede use_shared_key = 1; 2757554c0a3aSHans de Goede } 2758554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 2759554c0a3aSHans de Goede 2760554c0a3aSHans de Goede /* setting IV for auth seq #3 */ 2761554c0a3aSHans de Goede if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { 2762554c0a3aSHans de Goede __le32 le_tmp32; 2763554c0a3aSHans de Goede 2764554c0a3aSHans de Goede val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30)); 2765554c0a3aSHans de Goede le_tmp32 = cpu_to_le32(val32); 2766554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen)); 2767554c0a3aSHans de Goede 2768554c0a3aSHans de Goede pattrib->iv_len = 4; 2769554c0a3aSHans de Goede } 2770554c0a3aSHans de Goede 2771554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2772554c0a3aSHans de Goede 2773554c0a3aSHans de Goede /* setting auth seq number */ 2774554c0a3aSHans de Goede le_tmp = cpu_to_le16(pmlmeinfo->auth_seq); 2775554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2776554c0a3aSHans de Goede 2777554c0a3aSHans de Goede 2778554c0a3aSHans de Goede /* setting status code... */ 2779554c0a3aSHans de Goede le_tmp = cpu_to_le16(status); 2780554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2781554c0a3aSHans de Goede 2782554c0a3aSHans de Goede /* then checking to see if sending challenging text... */ 2783554c0a3aSHans de Goede if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { 278438caee0aSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen)); 2785554c0a3aSHans de Goede 2786554c0a3aSHans de Goede SetPrivacy(fctrl); 2787554c0a3aSHans de Goede 2788554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 2789554c0a3aSHans de Goede 2790554c0a3aSHans de Goede pattrib->encrypt = _WEP40_; 2791554c0a3aSHans de Goede 2792554c0a3aSHans de Goede pattrib->icv_len = 4; 2793554c0a3aSHans de Goede 2794554c0a3aSHans de Goede pattrib->pktlen += pattrib->icv_len; 2795554c0a3aSHans de Goede 2796554c0a3aSHans de Goede } 2797554c0a3aSHans de Goede 2798554c0a3aSHans de Goede } 2799554c0a3aSHans de Goede 2800554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2801554c0a3aSHans de Goede 2802554c0a3aSHans de Goede rtw_wep_encrypt(padapter, (u8 *)pmgntframe); 2803554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2804554c0a3aSHans de Goede } 2805554c0a3aSHans de Goede 2806554c0a3aSHans de Goede 2807554c0a3aSHans de Goede void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type) 2808554c0a3aSHans de Goede { 2809554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2810554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2811554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2812554c0a3aSHans de Goede unsigned char *pbuf, *pframe; 2813554c0a3aSHans de Goede unsigned short val; 2814554c0a3aSHans de Goede __le16 *fctrl; 2815554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2816554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2817554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 2818554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2819554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); 2820554c0a3aSHans de Goede u8 *ie = pnetwork->IEs; 2821554c0a3aSHans de Goede __le16 lestatus, le_tmp; 2822554c0a3aSHans de Goede 2823554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2824554c0a3aSHans de Goede if (pmgntframe == NULL) 2825554c0a3aSHans de Goede return; 2826554c0a3aSHans de Goede 2827554c0a3aSHans de Goede /* update attribute */ 2828554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2829554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2830554c0a3aSHans de Goede 2831554c0a3aSHans de Goede 2832554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2833554c0a3aSHans de Goede 2834554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2835554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2836554c0a3aSHans de Goede 2837554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2838554c0a3aSHans de Goede *(fctrl) = 0; 2839554c0a3aSHans de Goede 2840554c0a3aSHans de Goede memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN); 2841554c0a3aSHans de Goede memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN); 2842554c0a3aSHans de Goede memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 2843554c0a3aSHans de Goede 2844554c0a3aSHans de Goede 2845554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2846554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2847554c0a3aSHans de Goede if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP)) 2848554c0a3aSHans de Goede SetFrameSubType(pwlanhdr, pkt_type); 2849554c0a3aSHans de Goede else 2850554c0a3aSHans de Goede return; 2851554c0a3aSHans de Goede 2852554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 2853554c0a3aSHans de Goede pattrib->pktlen += pattrib->hdrlen; 2854554c0a3aSHans de Goede pframe += pattrib->hdrlen; 2855554c0a3aSHans de Goede 2856554c0a3aSHans de Goede /* capability */ 2857554c0a3aSHans de Goede val = *(unsigned short *)rtw_get_capability_from_ie(ie); 2858554c0a3aSHans de Goede 2859554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &(pattrib->pktlen)); 2860554c0a3aSHans de Goede 2861554c0a3aSHans de Goede lestatus = cpu_to_le16(status); 2862554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &(pattrib->pktlen)); 2863554c0a3aSHans de Goede 2864554c0a3aSHans de Goede le_tmp = cpu_to_le16(pstat->aid | BIT(14) | BIT(15)); 2865554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2866554c0a3aSHans de Goede 2867554c0a3aSHans de Goede if (pstat->bssratelen <= 8) { 2868c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen)); 2869554c0a3aSHans de Goede } else { 2870c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, pstat->bssrateset, &(pattrib->pktlen)); 287100f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen)); 2872554c0a3aSHans de Goede } 2873554c0a3aSHans de Goede 2874554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) { 2875554c0a3aSHans de Goede uint ie_len = 0; 2876554c0a3aSHans de Goede 2877554c0a3aSHans de Goede /* FILL HT CAP INFO IE */ 2878554c0a3aSHans de Goede /* p = hostapd_eid_ht_capabilities_info(hapd, p); */ 2879fc6a6528SRoss Schmidt pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); 2880554c0a3aSHans de Goede if (pbuf && ie_len > 0) { 2881554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 2882554c0a3aSHans de Goede pframe += (ie_len+2); 2883554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 2884554c0a3aSHans de Goede } 2885554c0a3aSHans de Goede 2886554c0a3aSHans de Goede /* FILL HT ADD INFO IE */ 2887554c0a3aSHans de Goede /* p = hostapd_eid_ht_operation(hapd, p); */ 2888332ec9dbSRoss Schmidt pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); 2889554c0a3aSHans de Goede if (pbuf && ie_len > 0) { 2890554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 2891554c0a3aSHans de Goede pframe += (ie_len+2); 2892554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 2893554c0a3aSHans de Goede } 2894554c0a3aSHans de Goede 2895554c0a3aSHans de Goede } 2896554c0a3aSHans de Goede 2897554c0a3aSHans de Goede /* FILL WMM IE */ 2898554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) { 2899554c0a3aSHans de Goede uint ie_len = 0; 2900554c0a3aSHans de Goede unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; 2901554c0a3aSHans de Goede 2902554c0a3aSHans de Goede for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) { 2903b05cc3a9SRoss Schmidt pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); 2904554c0a3aSHans de Goede if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) { 2905554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 2906554c0a3aSHans de Goede pframe += (ie_len+2); 2907554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 2908554c0a3aSHans de Goede 2909554c0a3aSHans de Goede break; 2910554c0a3aSHans de Goede } 2911554c0a3aSHans de Goede 2912554c0a3aSHans de Goede if ((pbuf == NULL) || (ie_len == 0)) { 2913554c0a3aSHans de Goede break; 2914554c0a3aSHans de Goede } 2915554c0a3aSHans de Goede } 2916554c0a3aSHans de Goede 2917554c0a3aSHans de Goede } 2918554c0a3aSHans de Goede 2919554c0a3aSHans de Goede if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) { 2920b05cc3a9SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen)); 2921554c0a3aSHans de Goede } 2922554c0a3aSHans de Goede 2923554c0a3aSHans de Goede /* add WPS IE ie for wps 2.0 */ 2924554c0a3aSHans de Goede if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) { 2925554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len); 2926554c0a3aSHans de Goede 2927554c0a3aSHans de Goede pframe += pmlmepriv->wps_assoc_resp_ie_len; 2928554c0a3aSHans de Goede pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len; 2929554c0a3aSHans de Goede } 2930554c0a3aSHans de Goede 2931554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2932554c0a3aSHans de Goede 2933554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2934554c0a3aSHans de Goede } 2935554c0a3aSHans de Goede 2936554c0a3aSHans de Goede void issue_assocreq(struct adapter *padapter) 2937554c0a3aSHans de Goede { 2938554c0a3aSHans de Goede int ret = _FAIL; 2939554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2940554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2941554c0a3aSHans de Goede unsigned char *pframe; 2942554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2943554c0a3aSHans de Goede __le16 *fctrl; 2944554c0a3aSHans de Goede __le16 val16; 2945554c0a3aSHans de Goede unsigned int i, j, index = 0; 2946554c0a3aSHans de Goede unsigned char bssrate[NumRates], sta_bssrate[NumRates]; 2947554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 2948554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2949554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2950554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2951554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2952554c0a3aSHans de Goede int bssrate_len = 0, sta_bssrate_len = 0; 2953554c0a3aSHans de Goede u8 vs_ie_length = 0; 2954554c0a3aSHans de Goede 2955554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2956554c0a3aSHans de Goede if (pmgntframe == NULL) 2957554c0a3aSHans de Goede goto exit; 2958554c0a3aSHans de Goede 2959554c0a3aSHans de Goede /* update attribute */ 2960554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2961554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2962554c0a3aSHans de Goede 2963554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2964554c0a3aSHans de Goede 2965554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2966554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2967554c0a3aSHans de Goede 2968554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2969554c0a3aSHans de Goede *(fctrl) = 0; 2970554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 2971554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 2972554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 2973554c0a3aSHans de Goede 2974554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2975554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2976554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ASSOCREQ); 2977554c0a3aSHans de Goede 2978554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2979554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2980554c0a3aSHans de Goede 2981554c0a3aSHans de Goede /* caps */ 2982554c0a3aSHans de Goede memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2); 2983554c0a3aSHans de Goede 2984554c0a3aSHans de Goede pframe += 2; 2985554c0a3aSHans de Goede pattrib->pktlen += 2; 2986554c0a3aSHans de Goede 2987554c0a3aSHans de Goede /* listen interval */ 2988554c0a3aSHans de Goede /* todo: listen interval for power saving */ 2989554c0a3aSHans de Goede val16 = cpu_to_le16(3); 2990554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)&val16, 2); 2991554c0a3aSHans de Goede pframe += 2; 2992554c0a3aSHans de Goede pattrib->pktlen += 2; 2993554c0a3aSHans de Goede 2994554c0a3aSHans de Goede /* SSID */ 29953f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen)); 2996554c0a3aSHans de Goede 2997554c0a3aSHans de Goede /* supported rate & extended supported rate */ 2998554c0a3aSHans de Goede 2999554c0a3aSHans de Goede /* Check if the AP's supported rates are also supported by STA. */ 3000554c0a3aSHans de Goede get_rate_set(padapter, sta_bssrate, &sta_bssrate_len); 3001554c0a3aSHans de Goede 3002554c0a3aSHans de Goede if (pmlmeext->cur_channel == 14) /* for JAPAN, channel 14 can only uses B Mode(CCK) */ 3003554c0a3aSHans de Goede sta_bssrate_len = 4; 3004554c0a3aSHans de Goede 3005554c0a3aSHans de Goede 3006554c0a3aSHans de Goede /* for (i = 0; i < sta_bssrate_len; i++) { */ 3007554c0a3aSHans de Goede /* */ 3008554c0a3aSHans de Goede 3009554c0a3aSHans de Goede for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { 3010554c0a3aSHans de Goede if (pmlmeinfo->network.SupportedRates[i] == 0) 3011554c0a3aSHans de Goede break; 3012554c0a3aSHans de Goede } 3013554c0a3aSHans de Goede 3014554c0a3aSHans de Goede 3015554c0a3aSHans de Goede for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { 3016554c0a3aSHans de Goede if (pmlmeinfo->network.SupportedRates[i] == 0) 3017554c0a3aSHans de Goede break; 3018554c0a3aSHans de Goede 3019554c0a3aSHans de Goede 3020554c0a3aSHans de Goede /* Check if the AP's supported rates are also supported by STA. */ 3021554c0a3aSHans de Goede for (j = 0; j < sta_bssrate_len; j++) { 3022554c0a3aSHans de Goede /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */ 3023554c0a3aSHans de Goede if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK) 3024709c8e49SFabio Aiuto == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) 3025554c0a3aSHans de Goede break; 3026554c0a3aSHans de Goede } 3027554c0a3aSHans de Goede 3028709c8e49SFabio Aiuto if (j != sta_bssrate_len) 3029554c0a3aSHans de Goede /* the rate is supported by STA */ 3030554c0a3aSHans de Goede bssrate[index++] = pmlmeinfo->network.SupportedRates[i]; 3031554c0a3aSHans de Goede } 3032554c0a3aSHans de Goede 3033554c0a3aSHans de Goede bssrate_len = index; 3034554c0a3aSHans de Goede 3035554c0a3aSHans de Goede if (bssrate_len == 0) { 3036554c0a3aSHans de Goede rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); 3037554c0a3aSHans de Goede rtw_free_xmitframe(pxmitpriv, pmgntframe); 3038554c0a3aSHans de Goede goto exit; /* don't connect to AP if no joint supported rate */ 3039554c0a3aSHans de Goede } 3040554c0a3aSHans de Goede 3041554c0a3aSHans de Goede 3042554c0a3aSHans de Goede if (bssrate_len > 8) { 3043c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen)); 304400f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); 3045554c0a3aSHans de Goede } else 3046c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen)); 3047554c0a3aSHans de Goede 3048554c0a3aSHans de Goede /* vendor specific IE, such as WPA, WMM, WPS */ 3049554c0a3aSHans de Goede for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) { 3050554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i); 3051554c0a3aSHans de Goede 3052554c0a3aSHans de Goede switch (pIE->ElementID) { 3053b05cc3a9SRoss Schmidt case WLAN_EID_VENDOR_SPECIFIC: 3054554c0a3aSHans de Goede if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) || 3055554c0a3aSHans de Goede (!memcmp(pIE->data, WMM_OUI, 4)) || 3056554c0a3aSHans de Goede (!memcmp(pIE->data, WPS_OUI, 4))) { 3057554c0a3aSHans de Goede vs_ie_length = pIE->Length; 3058554c0a3aSHans de Goede if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) { 30594d17363dSAndreas Hellmich /* Commented by Kurt 20110629 30604d17363dSAndreas Hellmich * In some older APs, WPS handshake 30614d17363dSAndreas Hellmich * would be fail if we append vendor 30624d17363dSAndreas Hellmich * extensions information to AP 30634d17363dSAndreas Hellmich */ 3064554c0a3aSHans de Goede 3065554c0a3aSHans de Goede vs_ie_length = 14; 3066554c0a3aSHans de Goede } 3067554c0a3aSHans de Goede 3068b05cc3a9SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, vs_ie_length, pIE->data, &(pattrib->pktlen)); 3069554c0a3aSHans de Goede } 3070554c0a3aSHans de Goede break; 3071554c0a3aSHans de Goede 30723359e292SRoss Schmidt case WLAN_EID_RSN: 30733359e292SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_RSN, pIE->Length, pIE->data, &(pattrib->pktlen)); 3074554c0a3aSHans de Goede break; 3075fc6a6528SRoss Schmidt case WLAN_EID_HT_CAPABILITY: 30760ad02fa8SGeorgiana Chelu if (padapter->mlmepriv.htpriv.ht_option) { 3077554c0a3aSHans de Goede if (!(is_ap_in_tkip(padapter))) { 3078554c0a3aSHans de Goede memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element)); 3079fc6a6528SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_HT_CAPABILITY, pIE->Length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen)); 3080554c0a3aSHans de Goede } 3081554c0a3aSHans de Goede } 3082554c0a3aSHans de Goede break; 3083554c0a3aSHans de Goede 30845b45010fSRoss Schmidt case WLAN_EID_EXT_CAPABILITY: 30850ad02fa8SGeorgiana Chelu if (padapter->mlmepriv.htpriv.ht_option) 30865b45010fSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_CAPABILITY, pIE->Length, pIE->data, &(pattrib->pktlen)); 3087554c0a3aSHans de Goede break; 3088554c0a3aSHans de Goede default: 3089554c0a3aSHans de Goede break; 3090554c0a3aSHans de Goede } 3091554c0a3aSHans de Goede 3092554c0a3aSHans de Goede i += (pIE->Length + 2); 3093554c0a3aSHans de Goede } 3094554c0a3aSHans de Goede 3095554c0a3aSHans de Goede if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) 3096b05cc3a9SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen)); 3097554c0a3aSHans de Goede 3098554c0a3aSHans de Goede 3099554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3100554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3101554c0a3aSHans de Goede 3102554c0a3aSHans de Goede ret = _SUCCESS; 3103554c0a3aSHans de Goede 3104554c0a3aSHans de Goede exit: 3105554c0a3aSHans de Goede if (ret == _SUCCESS) 3106554c0a3aSHans de Goede rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen); 3107554c0a3aSHans de Goede else 3108554c0a3aSHans de Goede rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len); 3109554c0a3aSHans de Goede } 3110554c0a3aSHans de Goede 311168468503SAndreas Hellmich /* when wait_ack is true, this function should be called at process context */ 311242b3b621SAishwarya Pant static int _issue_nulldata(struct adapter *padapter, unsigned char *da, 311342b3b621SAishwarya Pant unsigned int power_mode, bool wait_ack) 3114554c0a3aSHans de Goede { 3115554c0a3aSHans de Goede int ret = _FAIL; 3116554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3117554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3118554c0a3aSHans de Goede unsigned char *pframe; 3119554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3120554c0a3aSHans de Goede __le16 *fctrl; 3121554c0a3aSHans de Goede struct xmit_priv *pxmitpriv; 3122554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 3123554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo; 3124554c0a3aSHans de Goede 3125554c0a3aSHans de Goede if (!padapter) 3126554c0a3aSHans de Goede goto exit; 3127554c0a3aSHans de Goede 3128554c0a3aSHans de Goede pxmitpriv = &(padapter->xmitpriv); 3129554c0a3aSHans de Goede pmlmeext = &(padapter->mlmeextpriv); 3130554c0a3aSHans de Goede pmlmeinfo = &(pmlmeext->mlmext_info); 3131554c0a3aSHans de Goede 3132554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3133554c0a3aSHans de Goede if (pmgntframe == NULL) 3134554c0a3aSHans de Goede goto exit; 3135554c0a3aSHans de Goede 3136554c0a3aSHans de Goede /* update attribute */ 3137554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3138554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3139554c0a3aSHans de Goede pattrib->retry_ctrl = false; 3140554c0a3aSHans de Goede 3141554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3142554c0a3aSHans de Goede 3143554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3144554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3145554c0a3aSHans de Goede 3146554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3147554c0a3aSHans de Goede *(fctrl) = 0; 3148554c0a3aSHans de Goede 3149554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) 3150554c0a3aSHans de Goede SetFrDs(fctrl); 3151554c0a3aSHans de Goede else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) 3152554c0a3aSHans de Goede SetToDs(fctrl); 3153554c0a3aSHans de Goede 3154554c0a3aSHans de Goede if (power_mode) 3155554c0a3aSHans de Goede SetPwrMgt(fctrl); 3156554c0a3aSHans de Goede 3157554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3158554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3159554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3160554c0a3aSHans de Goede 3161554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3162554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3163554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_DATA_NULL); 3164554c0a3aSHans de Goede 3165554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3166554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3167554c0a3aSHans de Goede 3168554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3169554c0a3aSHans de Goede 3170554c0a3aSHans de Goede if (wait_ack) { 3171554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3172554c0a3aSHans de Goede } else { 3173554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3174554c0a3aSHans de Goede ret = _SUCCESS; 3175554c0a3aSHans de Goede } 3176554c0a3aSHans de Goede 3177554c0a3aSHans de Goede exit: 3178554c0a3aSHans de Goede return ret; 3179554c0a3aSHans de Goede } 3180554c0a3aSHans de Goede 3181554c0a3aSHans de Goede /* 3182554c0a3aSHans de Goede * [IMPORTANT] Don't call this function in interrupt context 3183554c0a3aSHans de Goede * 318468468503SAndreas Hellmich * When wait_ms > 0, this function should be called at process context 3185554c0a3aSHans de Goede * da == NULL for station mode 3186554c0a3aSHans de Goede */ 3187554c0a3aSHans de Goede int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms) 3188554c0a3aSHans de Goede { 3189554c0a3aSHans de Goede int ret; 3190554c0a3aSHans de Goede int i = 0; 3191554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3192554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3193554c0a3aSHans de Goede struct sta_info *psta; 3194554c0a3aSHans de Goede 3195554c0a3aSHans de Goede 319668468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 31975947e900SNishka Dasgupta if (!da) 3198554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3199554c0a3aSHans de Goede 3200554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, da); 3201554c0a3aSHans de Goede if (psta) { 3202554c0a3aSHans de Goede if (power_mode) 3203554c0a3aSHans de Goede rtw_hal_macid_sleep(padapter, psta->mac_id); 3204554c0a3aSHans de Goede else 3205554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 3206554c0a3aSHans de Goede } else { 3207554c0a3aSHans de Goede rtw_warn_on(1); 3208554c0a3aSHans de Goede } 3209554c0a3aSHans de Goede 3210554c0a3aSHans de Goede do { 32119cdb1928SSaiyam Doshi ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0); 3212554c0a3aSHans de Goede 3213554c0a3aSHans de Goede i++; 3214554c0a3aSHans de Goede 3215554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3216554c0a3aSHans de Goede break; 3217554c0a3aSHans de Goede 3218554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 3219554c0a3aSHans de Goede msleep(wait_ms); 3220554c0a3aSHans de Goede 3221554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3222554c0a3aSHans de Goede 3223554c0a3aSHans de Goede if (ret != _FAIL) { 3224554c0a3aSHans de Goede ret = _SUCCESS; 3225554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3226554c0a3aSHans de Goede goto exit; 3227554c0a3aSHans de Goede #endif 3228554c0a3aSHans de Goede } 3229554c0a3aSHans de Goede 3230554c0a3aSHans de Goede exit: 3231554c0a3aSHans de Goede return ret; 3232554c0a3aSHans de Goede } 3233554c0a3aSHans de Goede 3234554c0a3aSHans de Goede /* 3235554c0a3aSHans de Goede * [IMPORTANT] This function run in interrupt context 3236554c0a3aSHans de Goede * 3237554c0a3aSHans de Goede * The null data packet would be sent without power bit, 3238554c0a3aSHans de Goede * and not guarantee success. 3239554c0a3aSHans de Goede */ 3240554c0a3aSHans de Goede s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da) 3241554c0a3aSHans de Goede { 3242554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 3243554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo; 3244554c0a3aSHans de Goede 3245554c0a3aSHans de Goede 3246554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 3247554c0a3aSHans de Goede pmlmeinfo = &pmlmeext->mlmext_info; 3248554c0a3aSHans de Goede 324968468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 32505947e900SNishka Dasgupta if (!da) 3251554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3252554c0a3aSHans de Goede 325363ff599aSNishka Dasgupta return _issue_nulldata(padapter, da, 0, false); 3254554c0a3aSHans de Goede } 3255554c0a3aSHans de Goede 325668468503SAndreas Hellmich /* when wait_ack is true, this function should be called at process context */ 325742b3b621SAishwarya Pant static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, 325842b3b621SAishwarya Pant u16 tid, bool wait_ack) 3259554c0a3aSHans de Goede { 3260554c0a3aSHans de Goede int ret = _FAIL; 3261554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3262554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3263554c0a3aSHans de Goede unsigned char *pframe; 3264554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3265554c0a3aSHans de Goede __le16 *fctrl; 3266554c0a3aSHans de Goede u16 *qc; 3267554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3268554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3269554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3270554c0a3aSHans de Goede 3271554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3272554c0a3aSHans de Goede if (pmgntframe == NULL) 3273554c0a3aSHans de Goede goto exit; 3274554c0a3aSHans de Goede 3275554c0a3aSHans de Goede /* update attribute */ 3276554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3277554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3278554c0a3aSHans de Goede 3279554c0a3aSHans de Goede pattrib->hdrlen += 2; 3280554c0a3aSHans de Goede pattrib->qos_en = true; 3281554c0a3aSHans de Goede pattrib->eosp = 1; 3282554c0a3aSHans de Goede pattrib->ack_policy = 0; 3283554c0a3aSHans de Goede pattrib->mdata = 0; 3284554c0a3aSHans de Goede 3285554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3286554c0a3aSHans de Goede 3287554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3288554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3289554c0a3aSHans de Goede 3290554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3291554c0a3aSHans de Goede *(fctrl) = 0; 3292554c0a3aSHans de Goede 3293554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) 3294554c0a3aSHans de Goede SetFrDs(fctrl); 3295554c0a3aSHans de Goede else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) 3296554c0a3aSHans de Goede SetToDs(fctrl); 3297554c0a3aSHans de Goede 3298554c0a3aSHans de Goede if (pattrib->mdata) 3299554c0a3aSHans de Goede SetMData(fctrl); 3300554c0a3aSHans de Goede 3301554c0a3aSHans de Goede qc = (unsigned short *)(pframe + pattrib->hdrlen - 2); 3302554c0a3aSHans de Goede 3303554c0a3aSHans de Goede SetPriority(qc, tid); 3304554c0a3aSHans de Goede 3305554c0a3aSHans de Goede SetEOSP(qc, pattrib->eosp); 3306554c0a3aSHans de Goede 3307554c0a3aSHans de Goede SetAckpolicy(qc, pattrib->ack_policy); 3308554c0a3aSHans de Goede 3309554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3310554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3311554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3312554c0a3aSHans de Goede 3313554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3314554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3315554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); 3316554c0a3aSHans de Goede 3317554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_qos_hdr); 3318554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); 3319554c0a3aSHans de Goede 3320554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3321554c0a3aSHans de Goede 3322554c0a3aSHans de Goede if (wait_ack) { 3323554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3324554c0a3aSHans de Goede } else { 3325554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3326554c0a3aSHans de Goede ret = _SUCCESS; 3327554c0a3aSHans de Goede } 3328554c0a3aSHans de Goede 3329554c0a3aSHans de Goede exit: 3330554c0a3aSHans de Goede return ret; 3331554c0a3aSHans de Goede } 3332554c0a3aSHans de Goede 333368468503SAndreas Hellmich /* when wait_ms >0 , this function should be called at process context */ 3334554c0a3aSHans de Goede /* da == NULL for station mode */ 3335554c0a3aSHans de Goede int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms) 3336554c0a3aSHans de Goede { 3337554c0a3aSHans de Goede int ret; 3338554c0a3aSHans de Goede int i = 0; 3339554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3340554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3341554c0a3aSHans de Goede 334268468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 33435947e900SNishka Dasgupta if (!da) 3344554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3345554c0a3aSHans de Goede 3346554c0a3aSHans de Goede do { 33479cdb1928SSaiyam Doshi ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0); 3348554c0a3aSHans de Goede 3349554c0a3aSHans de Goede i++; 3350554c0a3aSHans de Goede 3351554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3352554c0a3aSHans de Goede break; 3353554c0a3aSHans de Goede 3354554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 3355554c0a3aSHans de Goede msleep(wait_ms); 3356554c0a3aSHans de Goede 3357554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3358554c0a3aSHans de Goede 3359554c0a3aSHans de Goede if (ret != _FAIL) { 3360554c0a3aSHans de Goede ret = _SUCCESS; 3361554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3362554c0a3aSHans de Goede goto exit; 3363554c0a3aSHans de Goede #endif 3364554c0a3aSHans de Goede } 3365554c0a3aSHans de Goede 3366554c0a3aSHans de Goede exit: 3367554c0a3aSHans de Goede return ret; 3368554c0a3aSHans de Goede } 3369554c0a3aSHans de Goede 337042b3b621SAishwarya Pant static int _issue_deauth(struct adapter *padapter, unsigned char *da, 337142b3b621SAishwarya Pant unsigned short reason, bool wait_ack) 3372554c0a3aSHans de Goede { 3373554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3374554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3375554c0a3aSHans de Goede unsigned char *pframe; 3376554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3377554c0a3aSHans de Goede __le16 *fctrl; 3378554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3379554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3380554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3381554c0a3aSHans de Goede int ret = _FAIL; 3382554c0a3aSHans de Goede __le16 le_tmp; 3383554c0a3aSHans de Goede 3384554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3385554c0a3aSHans de Goede if (pmgntframe == NULL) { 3386554c0a3aSHans de Goede goto exit; 3387554c0a3aSHans de Goede } 3388554c0a3aSHans de Goede 3389554c0a3aSHans de Goede /* update attribute */ 3390554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3391554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3392554c0a3aSHans de Goede pattrib->retry_ctrl = false; 3393554c0a3aSHans de Goede 3394554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3395554c0a3aSHans de Goede 3396554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3397554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3398554c0a3aSHans de Goede 3399554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3400554c0a3aSHans de Goede *(fctrl) = 0; 3401554c0a3aSHans de Goede 3402554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3403554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3404554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3405554c0a3aSHans de Goede 3406554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3407554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3408554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_DEAUTH); 3409554c0a3aSHans de Goede 3410554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3411554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3412554c0a3aSHans de Goede 3413554c0a3aSHans de Goede le_tmp = cpu_to_le16(reason); 3414554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3415554c0a3aSHans de Goede 3416554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3417554c0a3aSHans de Goede 3418554c0a3aSHans de Goede 3419554c0a3aSHans de Goede if (wait_ack) { 3420554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3421554c0a3aSHans de Goede } else { 3422554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3423554c0a3aSHans de Goede ret = _SUCCESS; 3424554c0a3aSHans de Goede } 3425554c0a3aSHans de Goede 3426554c0a3aSHans de Goede exit: 3427554c0a3aSHans de Goede return ret; 3428554c0a3aSHans de Goede } 3429554c0a3aSHans de Goede 3430554c0a3aSHans de Goede int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason) 3431554c0a3aSHans de Goede { 3432554c0a3aSHans de Goede return _issue_deauth(padapter, da, reason, false); 3433554c0a3aSHans de Goede } 3434554c0a3aSHans de Goede 3435554c0a3aSHans de Goede int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt, 3436554c0a3aSHans de Goede int wait_ms) 3437554c0a3aSHans de Goede { 3438554c0a3aSHans de Goede int ret; 3439554c0a3aSHans de Goede int i = 0; 3440554c0a3aSHans de Goede 3441554c0a3aSHans de Goede do { 34429cdb1928SSaiyam Doshi ret = _issue_deauth(padapter, da, reason, wait_ms > 0); 3443554c0a3aSHans de Goede 3444554c0a3aSHans de Goede i++; 3445554c0a3aSHans de Goede 3446554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3447554c0a3aSHans de Goede break; 3448554c0a3aSHans de Goede 3449554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 34501c8cb89eSJia-Ju Bai mdelay(wait_ms); 3451554c0a3aSHans de Goede 3452554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3453554c0a3aSHans de Goede 3454554c0a3aSHans de Goede if (ret != _FAIL) { 3455554c0a3aSHans de Goede ret = _SUCCESS; 3456554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3457554c0a3aSHans de Goede goto exit; 3458554c0a3aSHans de Goede #endif 3459554c0a3aSHans de Goede } 3460554c0a3aSHans de Goede 3461554c0a3aSHans de Goede exit: 3462554c0a3aSHans de Goede return ret; 3463554c0a3aSHans de Goede } 3464554c0a3aSHans de Goede 3465554c0a3aSHans de Goede void issue_action_SA_Query(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid) 3466554c0a3aSHans de Goede { 3467554c0a3aSHans de Goede u8 category = RTW_WLAN_CATEGORY_SA_QUERY; 3468554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3469554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3470554c0a3aSHans de Goede u8 *pframe; 3471554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3472554c0a3aSHans de Goede __le16 *fctrl; 3473554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3474554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3475554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3476554c0a3aSHans de Goede __le16 le_tmp; 3477554c0a3aSHans de Goede 3478554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3479e427bdd8SFabio Aiuto if (!pmgntframe) 3480554c0a3aSHans de Goede return; 3481554c0a3aSHans de Goede 3482554c0a3aSHans de Goede /* update attribute */ 3483554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3484554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3485554c0a3aSHans de Goede 3486554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3487554c0a3aSHans de Goede 3488554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3489554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3490554c0a3aSHans de Goede 3491554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3492554c0a3aSHans de Goede *(fctrl) = 0; 3493554c0a3aSHans de Goede 3494554c0a3aSHans de Goede if (raddr) 3495554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); 3496554c0a3aSHans de Goede else 3497554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3498554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3499554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3500554c0a3aSHans de Goede 3501554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3502554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3503554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 3504554c0a3aSHans de Goede 3505554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3506554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3507554c0a3aSHans de Goede 3508554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); 3509554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); 3510554c0a3aSHans de Goede 3511554c0a3aSHans de Goede switch (action) { 3512554c0a3aSHans de Goede case 0: /* SA Query req */ 3513554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen); 3514554c0a3aSHans de Goede pmlmeext->sa_query_seq++; 3515554c0a3aSHans de Goede /* send sa query request to AP, AP should reply sa query response in 1 second */ 3516554c0a3aSHans de Goede set_sa_query_timer(pmlmeext, 1000); 3517554c0a3aSHans de Goede break; 3518554c0a3aSHans de Goede 3519554c0a3aSHans de Goede case 1: /* SA Query rsp */ 3520554c0a3aSHans de Goede le_tmp = cpu_to_le16(tid); 3521554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen); 3522554c0a3aSHans de Goede break; 3523554c0a3aSHans de Goede default: 3524554c0a3aSHans de Goede break; 3525554c0a3aSHans de Goede } 3526554c0a3aSHans de Goede 3527554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3528554c0a3aSHans de Goede 3529554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3530554c0a3aSHans de Goede } 3531554c0a3aSHans de Goede 3532554c0a3aSHans de Goede void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status) 3533554c0a3aSHans de Goede { 3534554c0a3aSHans de Goede u8 category = RTW_WLAN_CATEGORY_BACK; 3535554c0a3aSHans de Goede u16 start_seq; 3536554c0a3aSHans de Goede u16 BA_para_set; 3537554c0a3aSHans de Goede u16 reason_code; 3538554c0a3aSHans de Goede u16 BA_timeout_value; 3539554c0a3aSHans de Goede u16 BA_starting_seqctrl = 0; 354098b32c71SRoss Schmidt enum ieee80211_max_ampdu_length_exp max_rx_ampdu_factor; 3541554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3542554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3543554c0a3aSHans de Goede u8 *pframe; 3544554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3545554c0a3aSHans de Goede __le16 *fctrl; 3546554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3547554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3548554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3549554c0a3aSHans de Goede struct sta_info *psta; 3550554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 3551554c0a3aSHans de Goede struct registry_priv *pregpriv = &padapter->registrypriv; 3552554c0a3aSHans de Goede __le16 le_tmp; 3553554c0a3aSHans de Goede 3554554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 355541452327SVatsala Narang if (!pmgntframe) 3556554c0a3aSHans de Goede return; 3557554c0a3aSHans de Goede 3558554c0a3aSHans de Goede /* update attribute */ 3559554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3560554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3561554c0a3aSHans de Goede 3562554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3563554c0a3aSHans de Goede 3564554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3565554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3566554c0a3aSHans de Goede 3567554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3568554c0a3aSHans de Goede *(fctrl) = 0; 3569554c0a3aSHans de Goede 3570554c0a3aSHans de Goede /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */ 3571554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); 3572554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3573554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3574554c0a3aSHans de Goede 3575554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3576554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3577554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 3578554c0a3aSHans de Goede 3579554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3580554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3581554c0a3aSHans de Goede 3582554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); 3583554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); 3584554c0a3aSHans de Goede 3585554c0a3aSHans de Goede if (category == 3) { 3586554c0a3aSHans de Goede switch (action) { 3587554c0a3aSHans de Goede case 0: /* ADDBA req */ 3588554c0a3aSHans de Goede do { 3589554c0a3aSHans de Goede pmlmeinfo->dialogToken++; 3590554c0a3aSHans de Goede } while (pmlmeinfo->dialogToken == 0); 3591554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen)); 3592554c0a3aSHans de Goede 3593d312a47fSNishka Dasgupta if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter)) { 3594554c0a3aSHans de Goede /* A-MSDU NOT Supported */ 3595554c0a3aSHans de Goede BA_para_set = 0; 3596554c0a3aSHans de Goede /* immediate Block Ack */ 3597f36fa2d9SPayal Kshirsagar BA_para_set |= BIT(1) & IEEE80211_ADDBA_PARAM_POLICY_MASK; 3598554c0a3aSHans de Goede /* TID */ 3599554c0a3aSHans de Goede BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK; 3600554c0a3aSHans de Goede /* max buffer size is 8 MSDU */ 3601b3ae8af6SRoss Schmidt BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3602554c0a3aSHans de Goede } else { 3603554c0a3aSHans de Goede BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */ 3604554c0a3aSHans de Goede } 3605554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 3606554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3607554c0a3aSHans de Goede 3608554c0a3aSHans de Goede BA_timeout_value = 5000;/* 5ms */ 3609554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_timeout_value); 3610554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3611554c0a3aSHans de Goede 3612554c0a3aSHans de Goede /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */ 3613554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, raddr); 361434557e23SIzabela Bakollari if (psta) { 3615554c0a3aSHans de Goede start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1; 3616554c0a3aSHans de Goede 3617554c0a3aSHans de Goede psta->BA_starting_seqctrl[status & 0x07] = start_seq; 3618554c0a3aSHans de Goede 3619554c0a3aSHans de Goede BA_starting_seqctrl = start_seq << 4; 3620554c0a3aSHans de Goede } 3621554c0a3aSHans de Goede 3622554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_starting_seqctrl); 3623554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3624554c0a3aSHans de Goede break; 3625554c0a3aSHans de Goede 3626554c0a3aSHans de Goede case 1: /* ADDBA rsp */ 3627554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen)); 3628554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen)); 3629554c0a3aSHans de Goede if (padapter->driver_rx_ampdu_factor != 0xFF) 3630554c0a3aSHans de Goede max_rx_ampdu_factor = 363198b32c71SRoss Schmidt (enum ieee80211_max_ampdu_length_exp)padapter->driver_rx_ampdu_factor; 3632554c0a3aSHans de Goede else 3633554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, 3634554c0a3aSHans de Goede HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); 3635554c0a3aSHans de Goede 363698b32c71SRoss Schmidt if (IEEE80211_HT_MAX_AMPDU_64K == max_rx_ampdu_factor) 3637554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */ 363898b32c71SRoss Schmidt else if (IEEE80211_HT_MAX_AMPDU_32K == max_rx_ampdu_factor) 3639554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */ 364098b32c71SRoss Schmidt else if (IEEE80211_HT_MAX_AMPDU_16K == max_rx_ampdu_factor) 3641554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */ 364298b32c71SRoss Schmidt else if (IEEE80211_HT_MAX_AMPDU_8K == max_rx_ampdu_factor) 3643554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */ 3644554c0a3aSHans de Goede else 3645554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */ 3646554c0a3aSHans de Goede 3647d312a47fSNishka Dasgupta if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter) && 3648554c0a3aSHans de Goede padapter->driver_rx_ampdu_factor == 0xFF) { 3649554c0a3aSHans de Goede /* max buffer size is 8 MSDU */ 3650b3ae8af6SRoss Schmidt BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3651b3ae8af6SRoss Schmidt BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3652554c0a3aSHans de Goede } 3653554c0a3aSHans de Goede 3654554c0a3aSHans de Goede if (pregpriv->ampdu_amsdu == 0)/* disabled */ 3655554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set & ~BIT(0)); 3656554c0a3aSHans de Goede else if (pregpriv->ampdu_amsdu == 1)/* enabled */ 3657554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set | BIT(0)); 3658554c0a3aSHans de Goede else /* auto */ 3659554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 3660554c0a3aSHans de Goede 3661554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3662554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen)); 3663554c0a3aSHans de Goede break; 3664554c0a3aSHans de Goede case 2:/* DELBA */ 3665554c0a3aSHans de Goede BA_para_set = (status & 0x1F) << 3; 3666554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 3667554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3668554c0a3aSHans de Goede 3669554c0a3aSHans de Goede reason_code = 37; 3670554c0a3aSHans de Goede le_tmp = cpu_to_le16(reason_code); 3671554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3672554c0a3aSHans de Goede break; 3673554c0a3aSHans de Goede default: 3674554c0a3aSHans de Goede break; 3675554c0a3aSHans de Goede } 3676554c0a3aSHans de Goede } 3677554c0a3aSHans de Goede 3678554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3679554c0a3aSHans de Goede 3680554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3681554c0a3aSHans de Goede } 3682554c0a3aSHans de Goede 3683554c0a3aSHans de Goede static void issue_action_BSSCoexistPacket(struct adapter *padapter) 3684554c0a3aSHans de Goede { 3685554c0a3aSHans de Goede struct list_head *plist, *phead; 3686554c0a3aSHans de Goede unsigned char category, action; 3687554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3688554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3689554c0a3aSHans de Goede unsigned char *pframe; 3690554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3691554c0a3aSHans de Goede __le16 *fctrl; 3692554c0a3aSHans de Goede struct wlan_network *pnetwork = NULL; 3693554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3694554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3695554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3696554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3697554c0a3aSHans de Goede struct __queue *queue = &(pmlmepriv->scanned_queue); 3698554c0a3aSHans de Goede u8 InfoContent[16] = {0}; 3699554c0a3aSHans de Goede u8 ICS[8][15]; 3700554c0a3aSHans de Goede 3701554c0a3aSHans de Goede if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0)) 3702554c0a3aSHans de Goede return; 3703554c0a3aSHans de Goede 3704554c0a3aSHans de Goede if (true == pmlmeinfo->bwmode_updated) 3705554c0a3aSHans de Goede return; 3706554c0a3aSHans de Goede 3707554c0a3aSHans de Goede category = RTW_WLAN_CATEGORY_PUBLIC; 3708554c0a3aSHans de Goede action = ACT_PUBLIC_BSSCOEXIST; 3709554c0a3aSHans de Goede 3710554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3711554c0a3aSHans de Goede if (pmgntframe == NULL) { 3712554c0a3aSHans de Goede return; 3713554c0a3aSHans de Goede } 3714554c0a3aSHans de Goede 3715554c0a3aSHans de Goede /* update attribute */ 3716554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3717554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3718554c0a3aSHans de Goede 3719554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3720554c0a3aSHans de Goede 3721554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3722554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3723554c0a3aSHans de Goede 3724554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3725554c0a3aSHans de Goede *(fctrl) = 0; 3726554c0a3aSHans de Goede 3727554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3728554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3729554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3730554c0a3aSHans de Goede 3731554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3732554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3733554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 3734554c0a3aSHans de Goede 3735554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3736554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3737554c0a3aSHans de Goede 3738554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); 3739554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); 3740554c0a3aSHans de Goede 3741554c0a3aSHans de Goede 3742554c0a3aSHans de Goede /* */ 3743554c0a3aSHans de Goede if (pmlmepriv->num_FortyMHzIntolerant > 0) { 3744554c0a3aSHans de Goede u8 iedata = 0; 3745554c0a3aSHans de Goede 3746554c0a3aSHans de Goede iedata |= BIT(2);/* 20 MHz BSS Width Request */ 3747554c0a3aSHans de Goede 37489b5d8c1fSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_BSS_COEX_2040, 1, &iedata, &(pattrib->pktlen)); 3749554c0a3aSHans de Goede 3750554c0a3aSHans de Goede } 3751554c0a3aSHans de Goede 3752554c0a3aSHans de Goede 3753554c0a3aSHans de Goede /* */ 3754554c0a3aSHans de Goede memset(ICS, 0, sizeof(ICS)); 3755554c0a3aSHans de Goede if (pmlmepriv->num_sta_no_ht > 0) { 3756554c0a3aSHans de Goede int i; 3757554c0a3aSHans de Goede 3758554c0a3aSHans de Goede spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 3759554c0a3aSHans de Goede 3760554c0a3aSHans de Goede phead = get_list_head(queue); 3761554c0a3aSHans de Goede plist = get_next(phead); 3762554c0a3aSHans de Goede 3763554c0a3aSHans de Goede while (1) { 3764554c0a3aSHans de Goede int len; 3765554c0a3aSHans de Goede u8 *p; 3766554c0a3aSHans de Goede struct wlan_bssid_ex *pbss_network; 3767554c0a3aSHans de Goede 3768554c0a3aSHans de Goede if (phead == plist) 3769554c0a3aSHans de Goede break; 3770554c0a3aSHans de Goede 377119cf9d7aSRoss Schmidt pnetwork = container_of(plist, struct wlan_network, list); 3772554c0a3aSHans de Goede 3773554c0a3aSHans de Goede plist = get_next(plist); 3774554c0a3aSHans de Goede 3775554c0a3aSHans de Goede pbss_network = (struct wlan_bssid_ex *)&pnetwork->network; 3776554c0a3aSHans de Goede 3777fc6a6528SRoss Schmidt p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pbss_network->IELength - _FIXED_IE_LENGTH_); 3778554c0a3aSHans de Goede if ((p == NULL) || (len == 0)) {/* non-HT */ 3779554c0a3aSHans de Goede 3780554c0a3aSHans de Goede if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14)) 3781554c0a3aSHans de Goede continue; 3782554c0a3aSHans de Goede 3783554c0a3aSHans de Goede ICS[0][pbss_network->Configuration.DSConfig] = 1; 3784554c0a3aSHans de Goede 3785554c0a3aSHans de Goede if (ICS[0][0] == 0) 3786554c0a3aSHans de Goede ICS[0][0] = 1; 3787554c0a3aSHans de Goede } 3788554c0a3aSHans de Goede 3789554c0a3aSHans de Goede } 3790554c0a3aSHans de Goede 3791554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 3792554c0a3aSHans de Goede 3793554c0a3aSHans de Goede 3794554c0a3aSHans de Goede for (i = 0; i < 8; i++) { 3795554c0a3aSHans de Goede if (ICS[i][0] == 1) { 3796554c0a3aSHans de Goede int j, k = 0; 3797554c0a3aSHans de Goede 3798554c0a3aSHans de Goede InfoContent[k] = i; 3799554c0a3aSHans de Goede /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */ 3800554c0a3aSHans de Goede k++; 3801554c0a3aSHans de Goede 3802554c0a3aSHans de Goede for (j = 1; j <= 14; j++) { 3803554c0a3aSHans de Goede if (ICS[i][j] == 1) { 3804554c0a3aSHans de Goede if (k < 16) { 3805554c0a3aSHans de Goede InfoContent[k] = j; /* channel number */ 3806554c0a3aSHans de Goede /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */ 3807554c0a3aSHans de Goede k++; 3808554c0a3aSHans de Goede } 3809554c0a3aSHans de Goede } 3810554c0a3aSHans de Goede } 3811554c0a3aSHans de Goede 3812d7ca2c3dSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_BSS_INTOLERANT_CHL_REPORT, k, InfoContent, &(pattrib->pktlen)); 3813554c0a3aSHans de Goede 3814554c0a3aSHans de Goede } 3815554c0a3aSHans de Goede 3816554c0a3aSHans de Goede } 3817554c0a3aSHans de Goede 3818554c0a3aSHans de Goede 3819554c0a3aSHans de Goede } 3820554c0a3aSHans de Goede 3821554c0a3aSHans de Goede 3822554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3823554c0a3aSHans de Goede 3824554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3825554c0a3aSHans de Goede } 3826554c0a3aSHans de Goede 3827554c0a3aSHans de Goede unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr) 3828554c0a3aSHans de Goede { 3829554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 3830554c0a3aSHans de Goede struct sta_info *psta = NULL; 3831554c0a3aSHans de Goede /* struct recv_reorder_ctrl *preorder_ctrl; */ 3832554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 3833554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3834554c0a3aSHans de Goede u16 tid; 3835554c0a3aSHans de Goede 3836554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 3837554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) 3838554c0a3aSHans de Goede return _SUCCESS; 3839554c0a3aSHans de Goede 3840554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, addr); 3841554c0a3aSHans de Goede if (psta == NULL) 3842554c0a3aSHans de Goede return _SUCCESS; 3843554c0a3aSHans de Goede 3844554c0a3aSHans de Goede if (initiator == 0) {/* recipient */ 3845554c0a3aSHans de Goede for (tid = 0; tid < MAXTID; tid++) { 38460ad02fa8SGeorgiana Chelu if (psta->recvreorder_ctrl[tid].enable) { 3847f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F)); 3848554c0a3aSHans de Goede psta->recvreorder_ctrl[tid].enable = false; 3849554c0a3aSHans de Goede psta->recvreorder_ctrl[tid].indicate_seq = 0xffff; 3850554c0a3aSHans de Goede } 3851554c0a3aSHans de Goede } 3852554c0a3aSHans de Goede } else if (initiator == 1) {/* originator */ 3853554c0a3aSHans de Goede for (tid = 0; tid < MAXTID; tid++) { 3854554c0a3aSHans de Goede if (psta->htpriv.agg_enable_bitmap & BIT(tid)) { 3855f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F)); 3856554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 3857554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); 3858554c0a3aSHans de Goede 3859554c0a3aSHans de Goede } 3860554c0a3aSHans de Goede } 3861554c0a3aSHans de Goede } 3862554c0a3aSHans de Goede 3863554c0a3aSHans de Goede return _SUCCESS; 3864554c0a3aSHans de Goede 3865554c0a3aSHans de Goede } 3866554c0a3aSHans de Goede 3867554c0a3aSHans de Goede unsigned int send_beacon(struct adapter *padapter) 3868554c0a3aSHans de Goede { 3869554c0a3aSHans de Goede u8 bxmitok = false; 3870554c0a3aSHans de Goede int issue = 0; 3871554c0a3aSHans de Goede int poll = 0; 3872554c0a3aSHans de Goede 3873554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); 3874554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL); 3875554c0a3aSHans de Goede do { 3876554c0a3aSHans de Goede issue_beacon(padapter, 100); 3877554c0a3aSHans de Goede issue++; 3878554c0a3aSHans de Goede do { 3879c22da34aSThomas Avery cond_resched(); 3880554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok)); 3881554c0a3aSHans de Goede poll++; 3882554c0a3aSHans de Goede } while ((poll%10) != 0 && false == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 3883554c0a3aSHans de Goede 3884554c0a3aSHans de Goede } while (false == bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 3885554c0a3aSHans de Goede 3886554c0a3aSHans de Goede if (padapter->bSurpriseRemoved || padapter->bDriverStopped) { 3887554c0a3aSHans de Goede return _FAIL; 3888554c0a3aSHans de Goede } 3889554c0a3aSHans de Goede 3890554c0a3aSHans de Goede 3891e427bdd8SFabio Aiuto if (!bxmitok) 3892554c0a3aSHans de Goede return _FAIL; 3893709c8e49SFabio Aiuto else 3894554c0a3aSHans de Goede return _SUCCESS; 3895554c0a3aSHans de Goede } 3896554c0a3aSHans de Goede 3897554c0a3aSHans de Goede /**************************************************************************** 3898554c0a3aSHans de Goede 389968468503SAndreas Hellmich Following are some utility functions for WiFi MLME 3900554c0a3aSHans de Goede 3901554c0a3aSHans de Goede *****************************************************************************/ 3902554c0a3aSHans de Goede 3903554c0a3aSHans de Goede void site_survey(struct adapter *padapter) 3904554c0a3aSHans de Goede { 3905554c0a3aSHans de Goede unsigned char survey_channel = 0, val8; 3906c2e0b9a7SMarco Cesati enum rt_scan_type ScanType = SCAN_PASSIVE; 3907554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 3908554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3909554c0a3aSHans de Goede u32 initialgain = 0; 3910554c0a3aSHans de Goede u32 channel_scan_time_ms = 0; 3911554c0a3aSHans de Goede 3912554c0a3aSHans de Goede { 3913554c0a3aSHans de Goede struct rtw_ieee80211_channel *ch; 3914c926f022SSimran Singhal 3915554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) { 3916554c0a3aSHans de Goede ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx]; 3917554c0a3aSHans de Goede survey_channel = ch->hw_value; 3918554c0a3aSHans de Goede ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE; 3919554c0a3aSHans de Goede } 3920554c0a3aSHans de Goede } 3921554c0a3aSHans de Goede 3922554c0a3aSHans de Goede if (survey_channel != 0) { 3923554c0a3aSHans de Goede /* PAUSE 4-AC Queue when site_survey */ 3924554c0a3aSHans de Goede /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 3925554c0a3aSHans de Goede /* val8 |= 0x0f; */ 3926554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 3927554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.channel_idx == 0) { 3928554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 3929554c0a3aSHans de Goede if (pmlmeext->fixed_chan != 0xff) 3930554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 3931554c0a3aSHans de Goede else 3932554c0a3aSHans de Goede #endif 3933554c0a3aSHans de Goede set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 3934554c0a3aSHans de Goede } else { 3935554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 3936554c0a3aSHans de Goede if (pmlmeext->fixed_chan != 0xff) 3937554c0a3aSHans de Goede SelectChannel(padapter, pmlmeext->fixed_chan); 3938554c0a3aSHans de Goede else 3939554c0a3aSHans de Goede #endif 3940554c0a3aSHans de Goede SelectChannel(padapter, survey_channel); 3941554c0a3aSHans de Goede } 3942554c0a3aSHans de Goede 3943554c0a3aSHans de Goede if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */ 3944554c0a3aSHans de Goede { 3945554c0a3aSHans de Goede int i; 3946c926f022SSimran Singhal 3947554c0a3aSHans de Goede for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { 3948554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) { 3949554c0a3aSHans de Goede /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */ 3950554c0a3aSHans de Goede if (padapter->registrypriv.wifi_spec) 3951554c0a3aSHans de Goede issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL); 3952554c0a3aSHans de Goede else 3953554c0a3aSHans de Goede issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0); 3954554c0a3aSHans de Goede issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL); 3955554c0a3aSHans de Goede } 3956554c0a3aSHans de Goede } 3957554c0a3aSHans de Goede 3958554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) { 3959554c0a3aSHans de Goede /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */ 3960554c0a3aSHans de Goede if (padapter->registrypriv.wifi_spec) 3961554c0a3aSHans de Goede issue_probereq(padapter, NULL, NULL); 3962554c0a3aSHans de Goede else 3963554c0a3aSHans de Goede issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0); 3964554c0a3aSHans de Goede issue_probereq(padapter, NULL, NULL); 3965554c0a3aSHans de Goede } 3966554c0a3aSHans de Goede } 3967554c0a3aSHans de Goede } 3968554c0a3aSHans de Goede 3969554c0a3aSHans de Goede channel_scan_time_ms = pmlmeext->chan_scan_time; 3970554c0a3aSHans de Goede 3971554c0a3aSHans de Goede set_survey_timer(pmlmeext, channel_scan_time_ms); 3972554c0a3aSHans de Goede } else { 3973554c0a3aSHans de Goede 3974554c0a3aSHans de Goede /* channel number is 0 or this channel is not valid. */ 3975554c0a3aSHans de Goede 3976554c0a3aSHans de Goede { 3977554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_COMPLETE; 3978554c0a3aSHans de Goede 3979554c0a3aSHans de Goede /* switch back to the original channel */ 3980554c0a3aSHans de Goede /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */ 3981554c0a3aSHans de Goede 3982554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 3983554c0a3aSHans de Goede 3984554c0a3aSHans de Goede /* flush 4-AC Queue after site_survey */ 3985554c0a3aSHans de Goede /* val8 = 0; */ 3986554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 3987554c0a3aSHans de Goede 3988554c0a3aSHans de Goede /* config MSR */ 3989554c0a3aSHans de Goede Set_MSR(padapter, (pmlmeinfo->state & 0x3)); 3990554c0a3aSHans de Goede 3991554c0a3aSHans de Goede initialgain = 0xff; /* restore RX GAIN */ 3992554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 3993554c0a3aSHans de Goede /* turn on dynamic functions */ 3994554c0a3aSHans de Goede Restore_DM_Func_Flag(padapter); 3995554c0a3aSHans de Goede /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */ 3996554c0a3aSHans de Goede 39970ad02fa8SGeorgiana Chelu if (is_client_associated_to_ap(padapter)) 3998554c0a3aSHans de Goede issue_nulldata(padapter, NULL, 0, 3, 500); 3999554c0a3aSHans de Goede 4000554c0a3aSHans de Goede val8 = 0; /* survey done */ 4001554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); 4002554c0a3aSHans de Goede 4003554c0a3aSHans de Goede report_surveydone_event(padapter); 4004554c0a3aSHans de Goede 4005554c0a3aSHans de Goede pmlmeext->chan_scan_time = SURVEY_TO; 4006554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_DISABLE; 4007554c0a3aSHans de Goede 4008554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4009554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4010554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4011554c0a3aSHans de Goede } 4012554c0a3aSHans de Goede } 4013554c0a3aSHans de Goede 4014554c0a3aSHans de Goede return; 4015554c0a3aSHans de Goede 4016554c0a3aSHans de Goede } 4017554c0a3aSHans de Goede 4018554c0a3aSHans de Goede /* collect bss info from Beacon and Probe request/response frames. */ 4019554c0a3aSHans de Goede u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid) 4020554c0a3aSHans de Goede { 4021554c0a3aSHans de Goede int i; 4022554c0a3aSHans de Goede u32 len; 4023554c0a3aSHans de Goede u8 *p; 4024554c0a3aSHans de Goede u16 val16, subtype; 4025554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 4026554c0a3aSHans de Goede u32 packet_len = precv_frame->u.hdr.len; 4027554c0a3aSHans de Goede u8 ie_offset; 4028554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 4029554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4030554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4031554c0a3aSHans de Goede __le32 le32_tmp; 4032554c0a3aSHans de Goede 4033554c0a3aSHans de Goede len = packet_len - sizeof(struct ieee80211_hdr_3addr); 4034554c0a3aSHans de Goede 4035709c8e49SFabio Aiuto if (len > MAX_IE_SZ) 4036554c0a3aSHans de Goede return _FAIL; 4037554c0a3aSHans de Goede 4038554c0a3aSHans de Goede memset(bssid, 0, sizeof(struct wlan_bssid_ex)); 4039554c0a3aSHans de Goede 4040554c0a3aSHans de Goede subtype = GetFrameSubType(pframe); 4041554c0a3aSHans de Goede 4042554c0a3aSHans de Goede if (subtype == WIFI_BEACON) { 4043554c0a3aSHans de Goede bssid->Reserved[0] = 1; 4044554c0a3aSHans de Goede ie_offset = _BEACON_IE_OFFSET_; 4045554c0a3aSHans de Goede } else { 4046554c0a3aSHans de Goede /* FIXME : more type */ 4047554c0a3aSHans de Goede if (subtype == WIFI_PROBERSP) { 4048554c0a3aSHans de Goede ie_offset = _PROBERSP_IE_OFFSET_; 4049554c0a3aSHans de Goede bssid->Reserved[0] = 3; 4050554c0a3aSHans de Goede } else if (subtype == WIFI_PROBEREQ) { 4051554c0a3aSHans de Goede ie_offset = _PROBEREQ_IE_OFFSET_; 4052554c0a3aSHans de Goede bssid->Reserved[0] = 2; 4053554c0a3aSHans de Goede } else { 4054554c0a3aSHans de Goede bssid->Reserved[0] = 0; 4055554c0a3aSHans de Goede ie_offset = _FIXED_IE_LENGTH_; 4056554c0a3aSHans de Goede } 4057554c0a3aSHans de Goede } 4058554c0a3aSHans de Goede 4059554c0a3aSHans de Goede bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len; 4060554c0a3aSHans de Goede 4061554c0a3aSHans de Goede /* below is to copy the information element */ 4062554c0a3aSHans de Goede bssid->IELength = len; 4063554c0a3aSHans de Goede memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength); 4064554c0a3aSHans de Goede 4065554c0a3aSHans de Goede /* get the signal strength */ 4066554c0a3aSHans de Goede bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /* in dBM.raw data */ 4067554c0a3aSHans de Goede bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */ 4068554c0a3aSHans de Goede bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */ 4069554c0a3aSHans de Goede 4070554c0a3aSHans de Goede /* checking SSID */ 40713f15277bSRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_SSID, &len, bssid->IELength - ie_offset); 4072e427bdd8SFabio Aiuto if (!p) 4073554c0a3aSHans de Goede return _FAIL; 4074554c0a3aSHans de Goede 4075554c0a3aSHans de Goede if (*(p + 1)) { 4076709c8e49SFabio Aiuto if (len > NDIS_802_11_LENGTH_SSID) 4077554c0a3aSHans de Goede return _FAIL; 4078709c8e49SFabio Aiuto 4079554c0a3aSHans de Goede memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1)); 4080554c0a3aSHans de Goede bssid->Ssid.SsidLength = *(p + 1); 4081554c0a3aSHans de Goede } else 4082554c0a3aSHans de Goede bssid->Ssid.SsidLength = 0; 4083554c0a3aSHans de Goede 4084554c0a3aSHans de Goede memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); 4085554c0a3aSHans de Goede 4086554c0a3aSHans de Goede /* checking rate info... */ 4087554c0a3aSHans de Goede i = 0; 4088c34c45edSRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_SUPP_RATES, &len, bssid->IELength - ie_offset); 408934557e23SIzabela Bakollari if (p) { 4090709c8e49SFabio Aiuto if (len > NDIS_802_11_LENGTH_RATES_EX) 4091554c0a3aSHans de Goede return _FAIL; 4092709c8e49SFabio Aiuto 4093554c0a3aSHans de Goede memcpy(bssid->SupportedRates, (p + 2), len); 4094554c0a3aSHans de Goede i = len; 4095554c0a3aSHans de Goede } 4096554c0a3aSHans de Goede 409700f0b682SRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_EXT_SUPP_RATES, &len, bssid->IELength - ie_offset); 409834557e23SIzabela Bakollari if (p) { 4099709c8e49SFabio Aiuto if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) 4100554c0a3aSHans de Goede return _FAIL; 4101709c8e49SFabio Aiuto 4102554c0a3aSHans de Goede memcpy(bssid->SupportedRates + i, (p + 2), len); 4103554c0a3aSHans de Goede } 4104554c0a3aSHans de Goede 4105554c0a3aSHans de Goede bssid->NetworkTypeInUse = Ndis802_11OFDM24; 4106554c0a3aSHans de Goede 4107554c0a3aSHans de Goede if (bssid->IELength < 12) 4108554c0a3aSHans de Goede return _FAIL; 4109554c0a3aSHans de Goede 4110554c0a3aSHans de Goede /* Checking for DSConfig */ 41118f6a9446SRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_DS_PARAMS, &len, bssid->IELength - ie_offset); 4112554c0a3aSHans de Goede 4113554c0a3aSHans de Goede bssid->Configuration.DSConfig = 0; 4114554c0a3aSHans de Goede bssid->Configuration.Length = 0; 4115554c0a3aSHans de Goede 4116554c0a3aSHans de Goede if (p) { 4117554c0a3aSHans de Goede bssid->Configuration.DSConfig = *(p + 2); 4118554c0a3aSHans de Goede } else { 4119554c0a3aSHans de Goede /* In 5G, some ap do not have DSSET IE */ 4120554c0a3aSHans de Goede /* checking HT info for channel */ 4121332ec9dbSRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_HT_OPERATION, &len, bssid->IELength - ie_offset); 4122554c0a3aSHans de Goede if (p) { 4123554c0a3aSHans de Goede struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2); 4124c926f022SSimran Singhal 4125554c0a3aSHans de Goede bssid->Configuration.DSConfig = HT_info->primary_channel; 4126554c0a3aSHans de Goede } else { /* use current channel */ 4127554c0a3aSHans de Goede bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter); 4128554c0a3aSHans de Goede } 4129554c0a3aSHans de Goede } 4130554c0a3aSHans de Goede 4131554c0a3aSHans de Goede memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2); 4132554c0a3aSHans de Goede bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp); 4133554c0a3aSHans de Goede 4134554c0a3aSHans de Goede val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid); 4135554c0a3aSHans de Goede 4136554c0a3aSHans de Goede if (val16 & BIT(0)) { 4137554c0a3aSHans de Goede bssid->InfrastructureMode = Ndis802_11Infrastructure; 4138554c0a3aSHans de Goede memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); 4139554c0a3aSHans de Goede } else { 4140554c0a3aSHans de Goede bssid->InfrastructureMode = Ndis802_11IBSS; 4141554c0a3aSHans de Goede memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN); 4142554c0a3aSHans de Goede } 4143554c0a3aSHans de Goede 4144554c0a3aSHans de Goede if (val16 & BIT(4)) 4145554c0a3aSHans de Goede bssid->Privacy = 1; 4146554c0a3aSHans de Goede else 4147554c0a3aSHans de Goede bssid->Privacy = 0; 4148554c0a3aSHans de Goede 4149554c0a3aSHans de Goede bssid->Configuration.ATIMWindow = 0; 4150554c0a3aSHans de Goede 4151554c0a3aSHans de Goede /* 20/40 BSS Coexistence check */ 4152554c0a3aSHans de Goede if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) { 4153554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 4154554c0a3aSHans de Goede 4155fc6a6528SRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_HT_CAPABILITY, &len, bssid->IELength - ie_offset); 4156554c0a3aSHans de Goede if (p && len > 0) { 4157554c0a3aSHans de Goede struct HT_caps_element *pHT_caps; 4158c926f022SSimran Singhal 4159554c0a3aSHans de Goede pHT_caps = (struct HT_caps_element *)(p + 2); 4160554c0a3aSHans de Goede 4161554c0a3aSHans de Goede if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14)) 4162554c0a3aSHans de Goede pmlmepriv->num_FortyMHzIntolerant++; 4163554c0a3aSHans de Goede } else 4164554c0a3aSHans de Goede pmlmepriv->num_sta_no_ht++; 4165554c0a3aSHans de Goede } 4166554c0a3aSHans de Goede 416768468503SAndreas Hellmich /* mark bss info receiving from nearby channel as SignalQuality 101 */ 4168554c0a3aSHans de Goede if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter)) 4169554c0a3aSHans de Goede bssid->PhyInfo.SignalQuality = 101; 4170554c0a3aSHans de Goede 4171554c0a3aSHans de Goede return _SUCCESS; 4172554c0a3aSHans de Goede } 4173554c0a3aSHans de Goede 4174554c0a3aSHans de Goede void start_create_ibss(struct adapter *padapter) 4175554c0a3aSHans de Goede { 4176554c0a3aSHans de Goede unsigned short caps; 4177554c0a3aSHans de Goede u8 val8; 4178554c0a3aSHans de Goede u8 join_type; 4179554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4180554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4181554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 4182c926f022SSimran Singhal 4183554c0a3aSHans de Goede pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; 4184554c0a3aSHans de Goede pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); 4185554c0a3aSHans de Goede 4186554c0a3aSHans de Goede /* update wireless mode */ 4187554c0a3aSHans de Goede update_wireless_mode(padapter); 4188554c0a3aSHans de Goede 418968468503SAndreas Hellmich /* update capability */ 4190554c0a3aSHans de Goede caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); 4191554c0a3aSHans de Goede update_capinfo(padapter, caps); 41922415ae7fSRoss Schmidt if (caps&WLAN_CAPABILITY_IBSS) {/* adhoc master */ 4193554c0a3aSHans de Goede val8 = 0xcf; 4194554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4195554c0a3aSHans de Goede 4196554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL); 4197554c0a3aSHans de Goede 4198554c0a3aSHans de Goede /* switch channel */ 4199554c0a3aSHans de Goede /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */ 4200554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 4201554c0a3aSHans de Goede 4202554c0a3aSHans de Goede beacon_timing_control(padapter); 4203554c0a3aSHans de Goede 4204554c0a3aSHans de Goede /* set msr to WIFI_FW_ADHOC_STATE */ 4205554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_ADHOC_STATE; 4206554c0a3aSHans de Goede Set_MSR(padapter, (pmlmeinfo->state & 0x3)); 4207554c0a3aSHans de Goede 4208554c0a3aSHans de Goede /* issue beacon */ 4209554c0a3aSHans de Goede if (send_beacon(padapter) == _FAIL) { 4210554c0a3aSHans de Goede report_join_res(padapter, -1); 4211554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4212554c0a3aSHans de Goede } else { 4213554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress); 4214554c0a3aSHans de Goede join_type = 0; 4215554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 4216554c0a3aSHans de Goede 4217554c0a3aSHans de Goede report_join_res(padapter, 1); 4218554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 4219554c0a3aSHans de Goede rtw_indicate_connect(padapter); 4220554c0a3aSHans de Goede } 4221554c0a3aSHans de Goede } else { 4222554c0a3aSHans de Goede return; 4223554c0a3aSHans de Goede } 4224554c0a3aSHans de Goede /* update bc/mc sta_info */ 4225554c0a3aSHans de Goede update_bmc_sta(padapter); 4226554c0a3aSHans de Goede 4227554c0a3aSHans de Goede } 4228554c0a3aSHans de Goede 4229554c0a3aSHans de Goede void start_clnt_join(struct adapter *padapter) 4230554c0a3aSHans de Goede { 4231554c0a3aSHans de Goede unsigned short caps; 4232554c0a3aSHans de Goede u8 val8; 4233554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4234554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4235554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 4236554c0a3aSHans de Goede int beacon_timeout; 4237554c0a3aSHans de Goede 4238554c0a3aSHans de Goede /* update wireless mode */ 4239554c0a3aSHans de Goede update_wireless_mode(padapter); 4240554c0a3aSHans de Goede 424168468503SAndreas Hellmich /* update capability */ 4242554c0a3aSHans de Goede caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); 4243554c0a3aSHans de Goede update_capinfo(padapter, caps); 42442415ae7fSRoss Schmidt if (caps&WLAN_CAPABILITY_ESS) { 4245554c0a3aSHans de Goede Set_MSR(padapter, WIFI_FW_STATION_STATE); 4246554c0a3aSHans de Goede 4247554c0a3aSHans de Goede val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf; 4248554c0a3aSHans de Goede 4249554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4250554c0a3aSHans de Goede 4251554c0a3aSHans de Goede /* Because of AP's not receiving deauth before */ 4252554c0a3aSHans de Goede /* AP may: 1)not response auth or 2)deauth us after link is complete */ 4253554c0a3aSHans de Goede /* issue deauth before issuing auth to deal with the situation */ 4254554c0a3aSHans de Goede 4255554c0a3aSHans de Goede /* Commented by Albert 2012/07/21 */ 4256554c0a3aSHans 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. */ 4257554c0a3aSHans de Goede { 4258554c0a3aSHans de Goede /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */ 4259554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); 4260554c0a3aSHans de Goede } 4261554c0a3aSHans de Goede 4262554c0a3aSHans de Goede /* here wait for receiving the beacon to start auth */ 4263554c0a3aSHans de Goede /* and enable a timer */ 4264554c0a3aSHans de Goede beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval); 4265554c0a3aSHans de Goede set_link_timer(pmlmeext, beacon_timeout); 4266554c0a3aSHans de Goede _set_timer(&padapter->mlmepriv.assoc_timer, 4267554c0a3aSHans de Goede (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout); 4268554c0a3aSHans de Goede 4269554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE; 42702415ae7fSRoss Schmidt } else if (caps&WLAN_CAPABILITY_IBSS) { /* adhoc client */ 4271554c0a3aSHans de Goede Set_MSR(padapter, WIFI_FW_ADHOC_STATE); 4272554c0a3aSHans de Goede 4273554c0a3aSHans de Goede val8 = 0xcf; 4274554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4275554c0a3aSHans de Goede 4276554c0a3aSHans de Goede beacon_timing_control(padapter); 4277554c0a3aSHans de Goede 4278554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_ADHOC_STATE; 4279554c0a3aSHans de Goede 4280554c0a3aSHans de Goede report_join_res(padapter, 1); 4281554c0a3aSHans de Goede } else { 4282554c0a3aSHans de Goede return; 4283554c0a3aSHans de Goede } 4284554c0a3aSHans de Goede 4285554c0a3aSHans de Goede } 4286554c0a3aSHans de Goede 4287554c0a3aSHans de Goede void start_clnt_auth(struct adapter *padapter) 4288554c0a3aSHans de Goede { 4289554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4290554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4291554c0a3aSHans de Goede 4292554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 4293554c0a3aSHans de Goede 4294554c0a3aSHans de Goede pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL); 4295554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_AUTH_STATE; 4296554c0a3aSHans de Goede 4297554c0a3aSHans de Goede pmlmeinfo->auth_seq = 1; 4298554c0a3aSHans de Goede pmlmeinfo->reauth_count = 0; 4299554c0a3aSHans de Goede pmlmeinfo->reassoc_count = 0; 4300554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 4301554c0a3aSHans de Goede pmlmeext->retry = 0; 4302554c0a3aSHans de Goede 4303554c0a3aSHans de Goede 4304554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "start auth\n"); 4305554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 4306554c0a3aSHans de Goede 4307554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 4308554c0a3aSHans de Goede 4309554c0a3aSHans de Goede } 4310554c0a3aSHans de Goede 4311554c0a3aSHans de Goede 4312554c0a3aSHans de Goede void start_clnt_assoc(struct adapter *padapter) 4313554c0a3aSHans de Goede { 4314554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4315554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4316554c0a3aSHans de Goede 4317554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 4318554c0a3aSHans de Goede 4319554c0a3aSHans de Goede pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE)); 4320554c0a3aSHans de Goede pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE); 4321554c0a3aSHans de Goede 4322554c0a3aSHans de Goede issue_assocreq(padapter); 4323554c0a3aSHans de Goede 4324554c0a3aSHans de Goede set_link_timer(pmlmeext, REASSOC_TO); 4325554c0a3aSHans de Goede } 4326554c0a3aSHans de Goede 4327554c0a3aSHans de Goede unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) 4328554c0a3aSHans de Goede { 4329554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4330554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4331554c0a3aSHans de Goede 4332554c0a3aSHans de Goede /* check A3 */ 4333554c0a3aSHans de Goede if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN))) 4334554c0a3aSHans de Goede return _SUCCESS; 4335554c0a3aSHans de Goede 4336554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 4337554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { 4338554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4339554c0a3aSHans de Goede report_del_sta_event(padapter, MacAddr, reason); 4340554c0a3aSHans de Goede 4341554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) { 4342554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4343554c0a3aSHans de Goede report_join_res(padapter, -2); 4344554c0a3aSHans de Goede } 4345554c0a3aSHans de Goede } 4346554c0a3aSHans de Goede 4347554c0a3aSHans de Goede return _SUCCESS; 4348554c0a3aSHans de Goede } 4349554c0a3aSHans de Goede 4350554c0a3aSHans de Goede static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid) 4351554c0a3aSHans de Goede { 4352554c0a3aSHans de Goede struct registry_priv *pregistrypriv; 4353554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 4354f0e46c47SMarco Cesati struct rt_channel_info *chplan_new; 4355554c0a3aSHans de Goede u8 channel; 4356554c0a3aSHans de Goede u8 i; 4357554c0a3aSHans de Goede 4358554c0a3aSHans de Goede 4359554c0a3aSHans de Goede pregistrypriv = &padapter->registrypriv; 4360554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 4361554c0a3aSHans de Goede 4362554c0a3aSHans de Goede /* Adjust channel plan by AP Country IE */ 4363554c0a3aSHans de Goede if (pregistrypriv->enable80211d && 4364554c0a3aSHans de Goede (!pmlmeext->update_channel_plan_by_ap_done)) { 4365554c0a3aSHans de Goede u8 *ie, *p; 4366554c0a3aSHans de Goede u32 len; 4367f0e46c47SMarco Cesati struct rt_channel_plan chplan_ap; 4368f0e46c47SMarco Cesati struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM]; 4369554c0a3aSHans de Goede u8 country[4]; 4370554c0a3aSHans de Goede u8 fcn; /* first channel number */ 4371554c0a3aSHans de Goede u8 noc; /* number of channel */ 4372554c0a3aSHans de Goede u8 j, k; 4373554c0a3aSHans de Goede 43740b44fca9SRoss Schmidt ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_COUNTRY, &len, bssid->IELength - _FIXED_IE_LENGTH_); 4375554c0a3aSHans de Goede if (!ie) 4376554c0a3aSHans de Goede return; 4377554c0a3aSHans de Goede if (len < 6) 4378554c0a3aSHans de Goede return; 4379554c0a3aSHans de Goede 4380554c0a3aSHans de Goede ie += 2; 4381554c0a3aSHans de Goede p = ie; 4382554c0a3aSHans de Goede ie += len; 4383554c0a3aSHans de Goede 4384554c0a3aSHans de Goede memset(country, 0, 4); 4385554c0a3aSHans de Goede memcpy(country, p, 3); 4386554c0a3aSHans de Goede p += 3; 4387554c0a3aSHans de Goede 4388554c0a3aSHans de Goede i = 0; 4389554c0a3aSHans de Goede while ((ie - p) >= 3) { 4390554c0a3aSHans de Goede fcn = *(p++); 4391554c0a3aSHans de Goede noc = *(p++); 4392554c0a3aSHans de Goede p++; 4393554c0a3aSHans de Goede 4394554c0a3aSHans de Goede for (j = 0; j < noc; j++) { 4395554c0a3aSHans de Goede if (fcn <= 14) 4396554c0a3aSHans de Goede channel = fcn + j; /* 2.4 GHz */ 4397554c0a3aSHans de Goede else 4398554c0a3aSHans de Goede channel = fcn + j*4; /* 5 GHz */ 4399554c0a3aSHans de Goede 4400554c0a3aSHans de Goede chplan_ap.Channel[i++] = channel; 4401554c0a3aSHans de Goede } 4402554c0a3aSHans de Goede } 4403554c0a3aSHans de Goede chplan_ap.Len = i; 4404554c0a3aSHans de Goede 4405f55a6d45SArnd Bergmann #ifdef DEBUG_RTL871X 4406554c0a3aSHans de Goede i = 0; 4407554c0a3aSHans de Goede while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0)) { 4408554c0a3aSHans de Goede DBG_8192C("%02d,", chplan_ap.Channel[i]); 4409554c0a3aSHans de Goede i++; 4410554c0a3aSHans de Goede } 4411554c0a3aSHans de Goede #endif 4412554c0a3aSHans de Goede 4413554c0a3aSHans de Goede memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta)); 4414f55a6d45SArnd Bergmann #ifdef DEBUG_RTL871X 4415554c0a3aSHans de Goede i = 0; 4416554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4417554c0a3aSHans de Goede i++; 4418554c0a3aSHans de Goede } 4419554c0a3aSHans de Goede #endif 4420554c0a3aSHans de Goede 4421554c0a3aSHans de Goede memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set)); 4422554c0a3aSHans de Goede chplan_new = pmlmeext->channel_set; 4423554c0a3aSHans de Goede 4424554c0a3aSHans de Goede i = j = k = 0; 4425554c0a3aSHans de Goede if (pregistrypriv->wireless_mode & WIRELESS_11G) { 4426554c0a3aSHans de Goede do { 4427554c0a3aSHans de Goede if ((i == MAX_CHANNEL_NUM) || 4428554c0a3aSHans de Goede (chplan_sta[i].ChannelNum == 0) || 4429554c0a3aSHans de Goede (chplan_sta[i].ChannelNum > 14)) 4430554c0a3aSHans de Goede break; 4431554c0a3aSHans de Goede 4432554c0a3aSHans de Goede if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14)) 4433554c0a3aSHans de Goede break; 4434554c0a3aSHans de Goede 4435554c0a3aSHans de Goede if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { 4436554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4437554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4438554c0a3aSHans de Goede i++; 4439554c0a3aSHans de Goede j++; 4440554c0a3aSHans de Goede k++; 4441554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { 4442554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4443554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4444554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4445554c0a3aSHans de Goede i++; 4446554c0a3aSHans de Goede k++; 4447554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { 4448554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4449554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4450554c0a3aSHans de Goede j++; 4451554c0a3aSHans de Goede k++; 4452554c0a3aSHans de Goede } 4453554c0a3aSHans de Goede } while (1); 4454554c0a3aSHans de Goede 4455554c0a3aSHans de Goede /* change AP not support channel to Passive scan */ 4456554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && 4457554c0a3aSHans de Goede (chplan_sta[i].ChannelNum != 0) && 4458554c0a3aSHans de Goede (chplan_sta[i].ChannelNum <= 14)) { 4459554c0a3aSHans de Goede 4460554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4461554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4462554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4463554c0a3aSHans de Goede i++; 4464554c0a3aSHans de Goede k++; 4465554c0a3aSHans de Goede } 4466554c0a3aSHans de Goede 4467554c0a3aSHans de Goede /* add channel AP supported */ 4468554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) { 4469554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4470554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4471554c0a3aSHans de Goede j++; 4472554c0a3aSHans de Goede k++; 4473554c0a3aSHans de Goede } 4474554c0a3aSHans de Goede } else { 4475554c0a3aSHans de Goede /* keep original STA 2.4G channel plan */ 4476554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && 4477554c0a3aSHans de Goede (chplan_sta[i].ChannelNum != 0) && 4478554c0a3aSHans de Goede (chplan_sta[i].ChannelNum <= 14)) { 4479554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4480554c0a3aSHans de Goede chplan_new[k].ScanType = chplan_sta[i].ScanType; 4481554c0a3aSHans de Goede i++; 4482554c0a3aSHans de Goede k++; 4483554c0a3aSHans de Goede } 4484554c0a3aSHans de Goede 4485554c0a3aSHans de Goede /* skip AP 2.4G channel plan */ 4486554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) { 4487554c0a3aSHans de Goede j++; 4488554c0a3aSHans de Goede } 4489554c0a3aSHans de Goede } 4490554c0a3aSHans de Goede 4491554c0a3aSHans de Goede if (pregistrypriv->wireless_mode & WIRELESS_11A) { 4492554c0a3aSHans de Goede do { 4493554c0a3aSHans de Goede if ((i == MAX_CHANNEL_NUM) || 4494554c0a3aSHans de Goede (chplan_sta[i].ChannelNum == 0)) 4495554c0a3aSHans de Goede break; 4496554c0a3aSHans de Goede 4497554c0a3aSHans de Goede if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0)) 4498554c0a3aSHans de Goede break; 4499554c0a3aSHans de Goede 4500554c0a3aSHans de Goede if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { 4501554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4502554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4503554c0a3aSHans de Goede i++; 4504554c0a3aSHans de Goede j++; 4505554c0a3aSHans de Goede k++; 4506554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { 4507554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4508554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4509554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4510554c0a3aSHans de Goede i++; 4511554c0a3aSHans de Goede k++; 4512554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { 4513554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4514554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4515554c0a3aSHans de Goede j++; 4516554c0a3aSHans de Goede k++; 4517554c0a3aSHans de Goede } 4518554c0a3aSHans de Goede } while (1); 4519554c0a3aSHans de Goede 4520554c0a3aSHans de Goede /* change AP not support channel to Passive scan */ 4521554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4522554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4523554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4524554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4525554c0a3aSHans de Goede i++; 4526554c0a3aSHans de Goede k++; 4527554c0a3aSHans de Goede } 4528554c0a3aSHans de Goede 4529554c0a3aSHans de Goede /* add channel AP supported */ 4530554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) { 4531554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4532554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4533554c0a3aSHans de Goede j++; 4534554c0a3aSHans de Goede k++; 4535554c0a3aSHans de Goede } 4536554c0a3aSHans de Goede } else { 4537554c0a3aSHans de Goede /* keep original STA 5G channel plan */ 4538554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4539554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4540554c0a3aSHans de Goede chplan_new[k].ScanType = chplan_sta[i].ScanType; 4541554c0a3aSHans de Goede i++; 4542554c0a3aSHans de Goede k++; 4543554c0a3aSHans de Goede } 4544554c0a3aSHans de Goede } 4545554c0a3aSHans de Goede 4546554c0a3aSHans de Goede pmlmeext->update_channel_plan_by_ap_done = 1; 4547554c0a3aSHans de Goede 4548f55a6d45SArnd Bergmann #ifdef DEBUG_RTL871X 4549554c0a3aSHans de Goede k = 0; 4550554c0a3aSHans de Goede while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0)) { 4551554c0a3aSHans de Goede k++; 4552554c0a3aSHans de Goede } 4553554c0a3aSHans de Goede #endif 4554554c0a3aSHans de Goede } 4555554c0a3aSHans de Goede 4556554c0a3aSHans de Goede /* If channel is used by AP, set channel scan type to active */ 4557554c0a3aSHans de Goede channel = bssid->Configuration.DSConfig; 4558554c0a3aSHans de Goede chplan_new = pmlmeext->channel_set; 4559554c0a3aSHans de Goede i = 0; 4560554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) { 4561554c0a3aSHans de Goede if (chplan_new[i].ChannelNum == channel) { 4562554c0a3aSHans de Goede if (chplan_new[i].ScanType == SCAN_PASSIVE) { 4563554c0a3aSHans de Goede /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */ 4564554c0a3aSHans de Goede if (channel >= 52 && channel <= 144) 4565554c0a3aSHans de Goede break; 4566554c0a3aSHans de Goede 4567554c0a3aSHans de Goede chplan_new[i].ScanType = SCAN_ACTIVE; 4568554c0a3aSHans de Goede } 4569554c0a3aSHans de Goede break; 4570554c0a3aSHans de Goede } 4571554c0a3aSHans de Goede i++; 4572554c0a3aSHans de Goede } 4573554c0a3aSHans de Goede } 4574554c0a3aSHans de Goede 4575554c0a3aSHans de Goede /**************************************************************************** 4576554c0a3aSHans de Goede 4577554c0a3aSHans de Goede Following are the functions to report events 4578554c0a3aSHans de Goede 4579554c0a3aSHans de Goede *****************************************************************************/ 4580554c0a3aSHans de Goede 4581554c0a3aSHans de Goede void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame) 4582554c0a3aSHans de Goede { 4583554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4584554c0a3aSHans de Goede u8 *pevtcmd; 4585554c0a3aSHans de Goede u32 cmdsz; 4586554c0a3aSHans de Goede struct survey_event *psurvey_evt; 4587554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4588554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 4589554c0a3aSHans de Goede struct cmd_priv *pcmdpriv; 4590554c0a3aSHans de Goede /* u8 *pframe = precv_frame->u.hdr.rx_data; */ 4591554c0a3aSHans de Goede /* uint len = precv_frame->u.hdr.len; */ 4592554c0a3aSHans de Goede 4593554c0a3aSHans de Goede if (!padapter) 4594554c0a3aSHans de Goede return; 4595554c0a3aSHans de Goede 4596554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 4597554c0a3aSHans de Goede pcmdpriv = &padapter->cmdpriv; 4598554c0a3aSHans de Goede 45992ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 460041452327SVatsala Narang if (!pcmd_obj) 4601554c0a3aSHans de Goede return; 4602554c0a3aSHans de Goede 4603554c0a3aSHans de Goede cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header)); 46042ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 460541452327SVatsala Narang if (!pevtcmd) { 46068f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4607554c0a3aSHans de Goede return; 4608554c0a3aSHans de Goede } 4609554c0a3aSHans de Goede 4610554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4611554c0a3aSHans de Goede 4612554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4613554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4614554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4615554c0a3aSHans de Goede 4616554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4617554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4618554c0a3aSHans de Goede 4619554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4620554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct survey_event); 4621554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); 4622554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4623554c0a3aSHans de Goede 4624554c0a3aSHans de Goede psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4625554c0a3aSHans de Goede 4626554c0a3aSHans de Goede if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) { 46278f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 46288f24f505SMadhumitha Prabakaran kfree(pevtcmd); 4629554c0a3aSHans de Goede return; 4630554c0a3aSHans de Goede } 4631554c0a3aSHans de Goede 4632554c0a3aSHans de Goede process_80211d(padapter, &psurvey_evt->bss); 4633554c0a3aSHans de Goede 4634554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4635554c0a3aSHans de Goede 4636554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt++; 4637554c0a3aSHans de Goede 4638554c0a3aSHans de Goede return; 4639554c0a3aSHans de Goede 4640554c0a3aSHans de Goede } 4641554c0a3aSHans de Goede 4642554c0a3aSHans de Goede void report_surveydone_event(struct adapter *padapter) 4643554c0a3aSHans de Goede { 4644554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4645554c0a3aSHans de Goede u8 *pevtcmd; 4646554c0a3aSHans de Goede u32 cmdsz; 4647554c0a3aSHans de Goede struct surveydone_event *psurveydone_evt; 4648554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4649554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4650554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4651554c0a3aSHans de Goede 46522ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 465341452327SVatsala Narang if (!pcmd_obj) 4654554c0a3aSHans de Goede return; 4655554c0a3aSHans de Goede 4656554c0a3aSHans de Goede cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header)); 46572ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 465841452327SVatsala Narang if (!pevtcmd) { 46598f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4660554c0a3aSHans de Goede return; 4661554c0a3aSHans de Goede } 4662554c0a3aSHans de Goede 4663554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4664554c0a3aSHans de Goede 4665554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4666554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4667554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4668554c0a3aSHans de Goede 4669554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4670554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4671554c0a3aSHans de Goede 4672554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4673554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct surveydone_event); 4674554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); 4675554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4676554c0a3aSHans de Goede 4677554c0a3aSHans de Goede psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4678554c0a3aSHans de Goede psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt; 4679554c0a3aSHans de Goede 4680554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4681554c0a3aSHans de Goede 4682554c0a3aSHans de Goede return; 4683554c0a3aSHans de Goede 4684554c0a3aSHans de Goede } 4685554c0a3aSHans de Goede 4686554c0a3aSHans de Goede void report_join_res(struct adapter *padapter, int res) 4687554c0a3aSHans de Goede { 4688554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4689554c0a3aSHans de Goede u8 *pevtcmd; 4690554c0a3aSHans de Goede u32 cmdsz; 4691554c0a3aSHans de Goede struct joinbss_event *pjoinbss_evt; 4692554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4693554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4694554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4695554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4696554c0a3aSHans de Goede 46972ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 469841452327SVatsala Narang if (!pcmd_obj) 4699554c0a3aSHans de Goede return; 4700554c0a3aSHans de Goede 4701554c0a3aSHans de Goede cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header)); 47022ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 470341452327SVatsala Narang if (!pevtcmd) { 47048f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4705554c0a3aSHans de Goede return; 4706554c0a3aSHans de Goede } 4707554c0a3aSHans de Goede 4708554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4709554c0a3aSHans de Goede 4710554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4711554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4712554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4713554c0a3aSHans de Goede 4714554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4715554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4716554c0a3aSHans de Goede 4717554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4718554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct joinbss_event); 4719554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); 4720554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4721554c0a3aSHans de Goede 4722554c0a3aSHans de Goede pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4723554c0a3aSHans de Goede memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex)); 4724554c0a3aSHans de Goede pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = res; 4725554c0a3aSHans de Goede 4726554c0a3aSHans de Goede 4727554c0a3aSHans de Goede rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network); 4728554c0a3aSHans de Goede 4729554c0a3aSHans de Goede 4730554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4731554c0a3aSHans de Goede 4732554c0a3aSHans de Goede return; 4733554c0a3aSHans de Goede 4734554c0a3aSHans de Goede } 4735554c0a3aSHans de Goede 4736554c0a3aSHans de Goede void report_wmm_edca_update(struct adapter *padapter) 4737554c0a3aSHans de Goede { 4738554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4739554c0a3aSHans de Goede u8 *pevtcmd; 4740554c0a3aSHans de Goede u32 cmdsz; 4741554c0a3aSHans de Goede struct wmm_event *pwmm_event; 4742554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4743554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4744554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4745554c0a3aSHans de Goede 47462ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 474741452327SVatsala Narang if (!pcmd_obj) 4748554c0a3aSHans de Goede return; 4749554c0a3aSHans de Goede 4750554c0a3aSHans de Goede cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header)); 47512ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 475241452327SVatsala Narang if (!pevtcmd) { 47538f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4754554c0a3aSHans de Goede return; 4755554c0a3aSHans de Goede } 4756554c0a3aSHans de Goede 4757554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4758554c0a3aSHans de Goede 4759554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4760554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4761554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4762554c0a3aSHans de Goede 4763554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4764554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4765554c0a3aSHans de Goede 4766554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4767554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct wmm_event); 4768554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM); 4769554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4770554c0a3aSHans de Goede 4771554c0a3aSHans de Goede pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4772554c0a3aSHans de Goede pwmm_event->wmm = 0; 4773554c0a3aSHans de Goede 4774554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4775554c0a3aSHans de Goede 4776554c0a3aSHans de Goede return; 4777554c0a3aSHans de Goede 4778554c0a3aSHans de Goede } 4779554c0a3aSHans de Goede 4780554c0a3aSHans de Goede void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) 4781554c0a3aSHans de Goede { 4782554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4783554c0a3aSHans de Goede u8 *pevtcmd; 4784554c0a3aSHans de Goede u32 cmdsz; 4785554c0a3aSHans de Goede struct sta_info *psta; 4786554c0a3aSHans de Goede int mac_id; 4787554c0a3aSHans de Goede struct stadel_event *pdel_sta_evt; 4788554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4789554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4790554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4791554c0a3aSHans de Goede 47922ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 4793554c0a3aSHans de Goede if (pcmd_obj == NULL) { 4794554c0a3aSHans de Goede return; 4795554c0a3aSHans de Goede } 4796554c0a3aSHans de Goede 4797554c0a3aSHans de Goede cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header)); 47982ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 4799554c0a3aSHans de Goede if (pevtcmd == NULL) { 48008f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4801554c0a3aSHans de Goede return; 4802554c0a3aSHans de Goede } 4803554c0a3aSHans de Goede 4804554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4805554c0a3aSHans de Goede 4806554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4807554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4808554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4809554c0a3aSHans de Goede 4810554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4811554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4812554c0a3aSHans de Goede 4813554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4814554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct stadel_event); 4815554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); 4816554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4817554c0a3aSHans de Goede 4818554c0a3aSHans de Goede pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4819554c0a3aSHans de Goede memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN); 4820554c0a3aSHans de Goede memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2); 4821554c0a3aSHans de Goede 4822554c0a3aSHans de Goede 4823554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, MacAddr); 4824554c0a3aSHans de Goede if (psta) 4825554c0a3aSHans de Goede mac_id = (int)psta->mac_id; 4826554c0a3aSHans de Goede else 4827554c0a3aSHans de Goede mac_id = (-1); 4828554c0a3aSHans de Goede 4829554c0a3aSHans de Goede pdel_sta_evt->mac_id = mac_id; 4830554c0a3aSHans de Goede 4831554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4832554c0a3aSHans de Goede } 4833554c0a3aSHans de Goede 4834554c0a3aSHans de Goede void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx) 4835554c0a3aSHans de Goede { 4836554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4837554c0a3aSHans de Goede u8 *pevtcmd; 4838554c0a3aSHans de Goede u32 cmdsz; 4839554c0a3aSHans de Goede struct stassoc_event *padd_sta_evt; 4840554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4841554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4842554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4843554c0a3aSHans de Goede 48442ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 4845554c0a3aSHans de Goede if (pcmd_obj == NULL) 4846554c0a3aSHans de Goede return; 4847554c0a3aSHans de Goede 4848554c0a3aSHans de Goede cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header)); 48492ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 4850554c0a3aSHans de Goede if (pevtcmd == NULL) { 48518f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4852554c0a3aSHans de Goede return; 4853554c0a3aSHans de Goede } 4854554c0a3aSHans de Goede 4855554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4856554c0a3aSHans de Goede 4857554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4858554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4859554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4860554c0a3aSHans de Goede 4861554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4862554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4863554c0a3aSHans de Goede 4864554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4865554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct stassoc_event); 4866554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); 4867554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4868554c0a3aSHans de Goede 4869554c0a3aSHans de Goede padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4870554c0a3aSHans de Goede memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN); 4871554c0a3aSHans de Goede padd_sta_evt->cam_id = cam_idx; 4872554c0a3aSHans de Goede 4873554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4874554c0a3aSHans de Goede } 4875554c0a3aSHans de Goede 4876554c0a3aSHans de Goede /**************************************************************************** 4877554c0a3aSHans de Goede 4878554c0a3aSHans de Goede Following are the event callback functions 4879554c0a3aSHans de Goede 4880554c0a3aSHans de Goede *****************************************************************************/ 4881554c0a3aSHans de Goede 4882554c0a3aSHans de Goede /* for sta/adhoc mode */ 4883554c0a3aSHans de Goede void update_sta_info(struct adapter *padapter, struct sta_info *psta) 4884554c0a3aSHans de Goede { 4885554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4886554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4887554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4888554c0a3aSHans de Goede 4889554c0a3aSHans de Goede /* ERP */ 4890554c0a3aSHans de Goede VCS_update(padapter, psta); 4891554c0a3aSHans de Goede 4892554c0a3aSHans de Goede /* HT */ 4893554c0a3aSHans de Goede if (pmlmepriv->htpriv.ht_option) { 4894554c0a3aSHans de Goede psta->htpriv.ht_option = true; 4895554c0a3aSHans de Goede 4896554c0a3aSHans de Goede psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; 4897554c0a3aSHans de Goede 4898554c0a3aSHans de Goede psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2; 4899554c0a3aSHans de Goede 4900554c0a3aSHans de Goede if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20)) 4901554c0a3aSHans de Goede psta->htpriv.sgi_20m = true; 4902554c0a3aSHans de Goede 4903554c0a3aSHans de Goede if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40)) 4904554c0a3aSHans de Goede psta->htpriv.sgi_40m = true; 4905554c0a3aSHans de Goede 4906554c0a3aSHans de Goede psta->qos_option = true; 4907554c0a3aSHans de Goede 4908554c0a3aSHans de Goede psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap; 4909554c0a3aSHans de Goede psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap; 4910554c0a3aSHans de Goede psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap; 4911554c0a3aSHans de Goede 4912c25d8a7dSRoss Schmidt memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct ieee80211_ht_cap)); 4913554c0a3aSHans de Goede } else { 4914554c0a3aSHans de Goede psta->htpriv.ht_option = false; 4915554c0a3aSHans de Goede 4916554c0a3aSHans de Goede psta->htpriv.ampdu_enable = false; 4917554c0a3aSHans de Goede 4918554c0a3aSHans de Goede psta->htpriv.sgi_20m = false; 4919554c0a3aSHans de Goede psta->htpriv.sgi_40m = false; 4920554c0a3aSHans de Goede psta->qos_option = false; 4921554c0a3aSHans de Goede 4922554c0a3aSHans de Goede } 4923554c0a3aSHans de Goede 4924554c0a3aSHans de Goede psta->htpriv.ch_offset = pmlmeext->cur_ch_offset; 4925554c0a3aSHans de Goede 4926554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ 4927554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ 4928554c0a3aSHans de Goede 4929554c0a3aSHans de Goede psta->bw_mode = pmlmeext->cur_bwmode; 4930554c0a3aSHans de Goede 4931554c0a3aSHans de Goede /* QoS */ 4932554c0a3aSHans de Goede if (pmlmepriv->qospriv.qos_option) 4933554c0a3aSHans de Goede psta->qos_option = true; 4934554c0a3aSHans de Goede 4935554c0a3aSHans de Goede update_ldpc_stbc_cap(psta); 4936554c0a3aSHans de Goede 4937554c0a3aSHans de Goede spin_lock_bh(&psta->lock); 4938554c0a3aSHans de Goede psta->state = _FW_LINKED; 4939554c0a3aSHans de Goede spin_unlock_bh(&psta->lock); 4940554c0a3aSHans de Goede 4941554c0a3aSHans de Goede } 4942554c0a3aSHans de Goede 4943554c0a3aSHans de Goede static void rtw_mlmeext_disconnect(struct adapter *padapter) 4944554c0a3aSHans de Goede { 4945554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 4946554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4947554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4948554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 4949554c0a3aSHans de Goede 4950554c0a3aSHans de Goede /* set_opmode_cmd(padapter, infra_client_with_mlme); */ 4951554c0a3aSHans de Goede 49524d17363dSAndreas Hellmich /* For safety, prevent from keeping macid sleep. 4953554c0a3aSHans de Goede * If we can sure all power mode enter/leave are paired, 4954554c0a3aSHans de Goede * this check can be removed. 4955554c0a3aSHans de Goede * Lucas@20131113 4956554c0a3aSHans de Goede */ 4957554c0a3aSHans de Goede /* wakeup macid after disconnect. */ 4958554c0a3aSHans de Goede { 4959554c0a3aSHans de Goede struct sta_info *psta; 4960c926f022SSimran Singhal 4961554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork)); 4962554c0a3aSHans de Goede if (psta) 4963554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 4964554c0a3aSHans de Goede } 4965554c0a3aSHans de Goede 4966554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL); 4967554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); 4968554c0a3aSHans de Goede 4969554c0a3aSHans de Goede /* set MSR to no link state -> infra. mode */ 4970554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_STATION_); 4971554c0a3aSHans de Goede 4972554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4973554c0a3aSHans de Goede 4974554c0a3aSHans de Goede /* switch to the 20M Hz mode after disconnect */ 4975554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 4976554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 4977554c0a3aSHans de Goede 4978554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 4979554c0a3aSHans de Goede 4980554c0a3aSHans de Goede flush_all_cam_entry(padapter); 4981554c0a3aSHans de Goede 4982554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 4983554c0a3aSHans de Goede 4984554c0a3aSHans de Goede /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */ 4985554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0; 4986554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0; 4987554c0a3aSHans de Goede 4988554c0a3aSHans de Goede } 4989554c0a3aSHans de Goede 4990554c0a3aSHans de Goede void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) 4991554c0a3aSHans de Goede { 4992554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4993554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4994554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 4995554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 4996554c0a3aSHans de Goede u8 join_type; 4997554c0a3aSHans de Goede struct sta_info *psta; 4998c926f022SSimran Singhal 4999554c0a3aSHans de Goede if (join_res < 0) { 5000554c0a3aSHans de Goede join_type = 1; 5001554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5002554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); 5003554c0a3aSHans de Goede 500481ff14a3SFabio Aiuto return; 5005554c0a3aSHans de Goede } 5006554c0a3aSHans de Goede 5007554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) 5008554c0a3aSHans de Goede /* update bc/mc sta_info */ 5009554c0a3aSHans de Goede update_bmc_sta(padapter); 5010554c0a3aSHans de Goede 5011554c0a3aSHans de Goede 5012554c0a3aSHans de Goede /* turn on dynamic functions */ 5013554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); 5014554c0a3aSHans de Goede 501568468503SAndreas Hellmich /* update IOT-related issue */ 5016554c0a3aSHans de Goede update_IOT_info(padapter); 5017554c0a3aSHans de Goede 5018554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates); 5019554c0a3aSHans de Goede 5020554c0a3aSHans de Goede /* BCN interval */ 5021554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval)); 5022554c0a3aSHans de Goede 502368468503SAndreas Hellmich /* update capability */ 5024554c0a3aSHans de Goede update_capinfo(padapter, pmlmeinfo->capability); 5025554c0a3aSHans de Goede 5026554c0a3aSHans de Goede /* WMM, Update EDCA param */ 5027554c0a3aSHans de Goede WMMOnAssocRsp(padapter); 5028554c0a3aSHans de Goede 5029554c0a3aSHans de Goede /* HT */ 5030554c0a3aSHans de Goede HTOnAssocRsp(padapter); 5031554c0a3aSHans de Goede 5032554c0a3aSHans de Goede /* Set cur_channel&cur_bwmode&cur_ch_offset */ 5033554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 5034554c0a3aSHans de Goede 5035554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress); 5036554c0a3aSHans de Goede if (psta) { /* only for infra. mode */ 5037554c0a3aSHans de Goede 5038554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; 5039554c0a3aSHans de Goede 5040554c0a3aSHans de Goede psta->wireless_mode = pmlmeext->cur_wireless_mode; 5041554c0a3aSHans de Goede 5042554c0a3aSHans de Goede /* set per sta rate after updating HT cap. */ 5043554c0a3aSHans de Goede set_sta_rate(padapter, psta); 5044554c0a3aSHans de Goede 5045554c0a3aSHans de Goede rtw_sta_media_status_rpt(padapter, psta, 1); 5046554c0a3aSHans de Goede 5047554c0a3aSHans de Goede /* wakeup macid after join bss successfully to ensure 5048554c0a3aSHans de Goede the subsequent data frames can be sent out normally */ 5049554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 5050554c0a3aSHans de Goede } 5051554c0a3aSHans de Goede 5052554c0a3aSHans de Goede join_type = 2; 5053554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5054554c0a3aSHans de Goede 5055554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 5056554c0a3aSHans de Goede /* correcting TSF */ 5057554c0a3aSHans de Goede correct_TSF(padapter, pmlmeext); 5058554c0a3aSHans de Goede 5059554c0a3aSHans de Goede /* set_link_timer(pmlmeext, DISCONNECT_TO); */ 5060554c0a3aSHans de Goede } 5061554c0a3aSHans de Goede 5062554c0a3aSHans de Goede if (get_iface_type(padapter) == IFACE_PORT0) 5063554c0a3aSHans de Goede rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0); 5064554c0a3aSHans de Goede } 5065554c0a3aSHans de Goede 5066554c0a3aSHans de Goede /* currently only adhoc mode will go here */ 5067554c0a3aSHans de Goede void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta) 5068554c0a3aSHans de Goede { 5069554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 5070554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5071554c0a3aSHans de Goede u8 join_type; 5072554c0a3aSHans de Goede 5073554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 5074554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */ 5075554c0a3aSHans de Goede 5076554c0a3aSHans de Goede /* nothing to do */ 5077554c0a3aSHans de Goede } else { /* adhoc client */ 5078554c0a3aSHans de Goede /* update TSF Value */ 5079554c0a3aSHans de Goede /* update_TSF(pmlmeext, pframe, len); */ 5080554c0a3aSHans de Goede 5081554c0a3aSHans de Goede /* correcting TSF */ 5082554c0a3aSHans de Goede correct_TSF(padapter, pmlmeext); 5083554c0a3aSHans de Goede 5084554c0a3aSHans de Goede /* start beacon */ 5085554c0a3aSHans de Goede if (send_beacon(padapter) == _FAIL) { 5086554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].status = 0; 5087554c0a3aSHans de Goede 5088554c0a3aSHans de Goede pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE; 5089554c0a3aSHans de Goede 5090554c0a3aSHans de Goede return; 5091554c0a3aSHans de Goede } 5092554c0a3aSHans de Goede 5093554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 5094554c0a3aSHans de Goede 5095554c0a3aSHans de Goede } 5096554c0a3aSHans de Goede 5097554c0a3aSHans de Goede join_type = 2; 5098554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5099554c0a3aSHans de Goede } 5100554c0a3aSHans de Goede 5101554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; 5102554c0a3aSHans de Goede 5103554c0a3aSHans de Goede psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates); 5104554c0a3aSHans de Goede memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen); 5105554c0a3aSHans de Goede 5106554c0a3aSHans de Goede /* update adhoc sta_info */ 5107554c0a3aSHans de Goede update_sta_info(padapter, psta); 5108554c0a3aSHans de Goede 5109554c0a3aSHans de Goede rtw_hal_update_sta_rate_mask(padapter, psta); 5110554c0a3aSHans de Goede 5111554c0a3aSHans de Goede /* ToDo: HT for Ad-hoc */ 5112554c0a3aSHans de Goede psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel); 5113777a4334SNishka Dasgupta psta->raid = networktype_to_raid_ex(padapter, psta); 5114554c0a3aSHans de Goede 5115554c0a3aSHans de Goede /* rate radaptive */ 5116554c0a3aSHans de Goede Update_RA_Entry(padapter, psta); 5117554c0a3aSHans de Goede } 5118554c0a3aSHans de Goede 5119554c0a3aSHans de Goede void mlmeext_sta_del_event_callback(struct adapter *padapter) 5120554c0a3aSHans de Goede { 5121554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) 5122554c0a3aSHans de Goede rtw_mlmeext_disconnect(padapter); 5123554c0a3aSHans de Goede } 5124554c0a3aSHans de Goede 5125554c0a3aSHans de Goede /**************************************************************************** 5126554c0a3aSHans de Goede 5127554c0a3aSHans de Goede Following are the functions for the timer handlers 5128554c0a3aSHans de Goede 5129554c0a3aSHans de Goede *****************************************************************************/ 5130554c0a3aSHans de Goede void _linked_info_dump(struct adapter *padapter) 5131554c0a3aSHans de Goede { 5132554c0a3aSHans de Goede int i; 5133554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5134554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5135554c0a3aSHans de Goede int UndecoratedSmoothedPWDB; 5136554c0a3aSHans de Goede struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); 5137554c0a3aSHans de Goede 5138554c0a3aSHans de Goede if (padapter->bLinkInfoDump) { 5139554c0a3aSHans de Goede 5140554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 5141554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB); 5142554c0a3aSHans de Goede } else if ((pmlmeinfo->state&0x03) == _HW_STATE_AP_) { 5143554c0a3aSHans de Goede struct list_head *phead, *plist; 5144554c0a3aSHans de Goede 5145554c0a3aSHans de Goede struct sta_info *psta = NULL; 5146554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5147554c0a3aSHans de Goede 5148554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 5149554c0a3aSHans de Goede phead = &pstapriv->asoc_list; 5150554c0a3aSHans de Goede plist = get_next(phead); 5151554c0a3aSHans de Goede while (phead != plist) { 515219cf9d7aSRoss Schmidt psta = container_of(plist, struct sta_info, asoc_list); 5153554c0a3aSHans de Goede plist = get_next(plist); 5154554c0a3aSHans de Goede } 5155554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 5156554c0a3aSHans de Goede 5157554c0a3aSHans de Goede } 5158554c0a3aSHans de Goede for (i = 0; i < NUM_STA; i++) { 51590ad02fa8SGeorgiana Chelu if (pdvobj->macid[i]) { 5160554c0a3aSHans de Goede if (i != 1) /* skip bc/mc sta */ 5161554c0a3aSHans de Goede /* tx info ============ */ 5162554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i); 5163554c0a3aSHans de Goede } 5164554c0a3aSHans de Goede } 5165554c0a3aSHans de Goede rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL); 5166554c0a3aSHans de Goede 5167554c0a3aSHans de Goede 5168554c0a3aSHans de Goede } 5169554c0a3aSHans de Goede 5170554c0a3aSHans de Goede 5171554c0a3aSHans de Goede } 5172554c0a3aSHans de Goede 5173554c0a3aSHans de Goede static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta) 5174554c0a3aSHans de Goede { 5175554c0a3aSHans de Goede u8 ret = false; 5176554c0a3aSHans de Goede 5177554c0a3aSHans de Goede if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) 5178554c0a3aSHans de Goede && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) 5179554c0a3aSHans de Goede && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta) 5180554c0a3aSHans de Goede ) { 5181554c0a3aSHans de Goede ret = false; 5182554c0a3aSHans de Goede } else { 5183554c0a3aSHans de Goede ret = true; 5184554c0a3aSHans de Goede } 5185554c0a3aSHans de Goede 5186554c0a3aSHans de Goede sta_update_last_rx_pkts(psta); 5187554c0a3aSHans de Goede 5188554c0a3aSHans de Goede return ret; 5189554c0a3aSHans de Goede } 5190554c0a3aSHans de Goede 5191554c0a3aSHans de Goede void linked_status_chk(struct adapter *padapter) 5192554c0a3aSHans de Goede { 5193554c0a3aSHans de Goede u32 i; 5194554c0a3aSHans de Goede struct sta_info *psta; 5195554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 5196554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5197554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5198554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5199554c0a3aSHans de Goede 5200554c0a3aSHans de Goede 5201554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter)) { 5202554c0a3aSHans de Goede /* linked infrastructure client mode */ 5203554c0a3aSHans de Goede 5204554c0a3aSHans de Goede int tx_chk = _SUCCESS, rx_chk = _SUCCESS; 5205554c0a3aSHans de Goede int rx_chk_limit; 5206554c0a3aSHans de Goede int link_count_limit; 5207554c0a3aSHans de Goede 5208554c0a3aSHans de Goede #if defined(DBG_ROAMING_TEST) 5209554c0a3aSHans de Goede rx_chk_limit = 1; 5210554c0a3aSHans de Goede #else 5211554c0a3aSHans de Goede rx_chk_limit = 8; 5212554c0a3aSHans de Goede #endif 5213554c0a3aSHans de Goede link_count_limit = 7; /* 16 sec */ 5214554c0a3aSHans de Goede 5215554c0a3aSHans de Goede /* Marked by Kurt 20130715 */ 5216554c0a3aSHans 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. */ 5217554c0a3aSHans de Goede /* todo: To check why we under miracast session, rx_chk would be false */ 5218554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress); 521934557e23SIzabela Bakollari if (psta) { 5220554c0a3aSHans de Goede if (chk_ap_is_alive(padapter, psta) == false) 5221554c0a3aSHans de Goede rx_chk = _FAIL; 5222554c0a3aSHans de Goede 5223554c0a3aSHans de Goede if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts) 5224554c0a3aSHans de Goede tx_chk = _FAIL; 5225554c0a3aSHans de Goede 5226554c0a3aSHans de Goede { 5227554c0a3aSHans de Goede if (rx_chk != _SUCCESS) { 5228554c0a3aSHans de Goede if (pmlmeext->retry == 0) { 5229554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5230554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5231554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5232554c0a3aSHans de Goede } 5233554c0a3aSHans de Goede } 5234554c0a3aSHans de Goede 5235*af6afdb6SFabio Aiuto if (tx_chk != _SUCCESS && 5236*af6afdb6SFabio Aiuto pmlmeinfo->link_count++ == link_count_limit) 5237554c0a3aSHans de Goede tx_chk = issue_nulldata_in_interrupt(padapter, NULL); 5238554c0a3aSHans de Goede } 5239554c0a3aSHans de Goede 5240554c0a3aSHans de Goede if (rx_chk == _FAIL) { 5241554c0a3aSHans de Goede pmlmeext->retry++; 5242554c0a3aSHans de Goede if (pmlmeext->retry > rx_chk_limit) { 5243554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n", 5244554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter)); 5245554c0a3aSHans de Goede receive_disconnect(padapter, pmlmeinfo->network.MacAddress 5246554c0a3aSHans de Goede , WLAN_REASON_EXPIRATION_CHK); 5247554c0a3aSHans de Goede return; 5248554c0a3aSHans de Goede } 5249554c0a3aSHans de Goede } else { 5250554c0a3aSHans de Goede pmlmeext->retry = 0; 5251554c0a3aSHans de Goede } 5252554c0a3aSHans de Goede 5253554c0a3aSHans de Goede if (tx_chk == _FAIL) { 5254554c0a3aSHans de Goede pmlmeinfo->link_count %= (link_count_limit+1); 5255554c0a3aSHans de Goede } else { 5256554c0a3aSHans de Goede pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts; 5257554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 5258554c0a3aSHans de Goede } 5259554c0a3aSHans de Goede 5260554c0a3aSHans de Goede } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */ 5261554c0a3aSHans de Goede } else if (is_client_associated_to_ibss(padapter)) { 5262554c0a3aSHans de Goede /* linked IBSS mode */ 5263554c0a3aSHans de Goede /* for each assoc list entry to check the rx pkt counter */ 5264554c0a3aSHans de Goede for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { 5265554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].status == 1) { 5266554c0a3aSHans de Goede psta = pmlmeinfo->FW_sta_info[i].psta; 5267554c0a3aSHans de Goede 5268554c0a3aSHans de Goede if (NULL == psta) 5269554c0a3aSHans de Goede continue; 5270554c0a3aSHans de Goede 5271554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) { 5272554c0a3aSHans de Goede 5273554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].retry < 3) { 5274554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry++; 5275554c0a3aSHans de Goede } else { 5276554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry = 0; 5277554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].status = 0; 5278554c0a3aSHans de Goede report_del_sta_event(padapter, psta->hwaddr 5279554c0a3aSHans de Goede , 65535/* indicate disconnect caused by no rx */ 5280554c0a3aSHans de Goede ); 5281554c0a3aSHans de Goede } 5282554c0a3aSHans de Goede } else { 5283554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry = 0; 5284554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta); 5285554c0a3aSHans de Goede } 5286554c0a3aSHans de Goede } 5287554c0a3aSHans de Goede } 5288554c0a3aSHans de Goede 5289554c0a3aSHans de Goede /* set_link_timer(pmlmeext, DISCONNECT_TO); */ 5290554c0a3aSHans de Goede 5291554c0a3aSHans de Goede } 5292554c0a3aSHans de Goede 5293554c0a3aSHans de Goede } 5294554c0a3aSHans de Goede 5295e8b1844aSKees Cook void survey_timer_hdl(struct timer_list *t) 5296554c0a3aSHans de Goede { 5297e8b1844aSKees Cook struct adapter *padapter = 5298e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.survey_timer); 5299554c0a3aSHans de Goede struct cmd_obj *ph2c; 5300554c0a3aSHans de Goede struct sitesurvey_parm *psurveyPara; 5301554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5302554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5303554c0a3aSHans de Goede 5304554c0a3aSHans de Goede /* issue rtw_sitesurvey_cmd */ 5305554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state > SCAN_START) { 5306554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 5307554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx++; 5308554c0a3aSHans de Goede } 5309554c0a3aSHans de Goede 53100ad02fa8SGeorgiana Chelu if (pmlmeext->scan_abort) { 5311554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num; 5312554c0a3aSHans de Goede 5313554c0a3aSHans de Goede pmlmeext->scan_abort = false;/* reset */ 5314554c0a3aSHans de Goede } 5315554c0a3aSHans de Goede 53162ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 5317554c0a3aSHans de Goede if (ph2c == NULL) { 5318554c0a3aSHans de Goede goto exit_survey_timer_hdl; 5319554c0a3aSHans de Goede } 5320554c0a3aSHans de Goede 53212ef2b7c2SJoe Perches psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm)); 5322554c0a3aSHans de Goede if (psurveyPara == NULL) { 53238f24f505SMadhumitha Prabakaran kfree(ph2c); 5324554c0a3aSHans de Goede goto exit_survey_timer_hdl; 5325554c0a3aSHans de Goede } 5326554c0a3aSHans de Goede 5327554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); 5328554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, ph2c); 5329554c0a3aSHans de Goede } 5330554c0a3aSHans de Goede 5331554c0a3aSHans de Goede 5332554c0a3aSHans de Goede exit_survey_timer_hdl: 5333554c0a3aSHans de Goede 5334554c0a3aSHans de Goede return; 5335554c0a3aSHans de Goede } 5336554c0a3aSHans de Goede 5337e8b1844aSKees Cook void link_timer_hdl(struct timer_list *t) 5338554c0a3aSHans de Goede { 5339e8b1844aSKees Cook struct adapter *padapter = 5340e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.link_timer); 5341554c0a3aSHans de Goede /* static unsigned int rx_pkt = 0; */ 5342554c0a3aSHans de Goede /* static u64 tx_cnt = 0; */ 5343554c0a3aSHans de Goede /* struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); */ 5344554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5345554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5346554c0a3aSHans de Goede /* struct sta_priv *pstapriv = &padapter->stapriv; */ 5347554c0a3aSHans de Goede 5348554c0a3aSHans de Goede 5349554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { 5350554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5351554c0a3aSHans de Goede report_join_res(padapter, -3); 5352554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) { 5353554c0a3aSHans de Goede /* re-auth timer */ 5354554c0a3aSHans de Goede if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) { 5355554c0a3aSHans de Goede /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */ 5356554c0a3aSHans de Goede /* */ 5357554c0a3aSHans de Goede pmlmeinfo->state = 0; 5358554c0a3aSHans de Goede report_join_res(padapter, -1); 5359554c0a3aSHans de Goede return; 5360554c0a3aSHans de Goede /* */ 5361554c0a3aSHans de Goede /* else */ 5362554c0a3aSHans de Goede /* */ 5363554c0a3aSHans de Goede /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */ 5364554c0a3aSHans de Goede /* pmlmeinfo->reauth_count = 0; */ 5365554c0a3aSHans de Goede /* */ 5366554c0a3aSHans de Goede } 5367554c0a3aSHans de Goede 5368554c0a3aSHans de Goede pmlmeinfo->auth_seq = 1; 5369554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 5370554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 5371554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) { 5372554c0a3aSHans de Goede /* re-assoc timer */ 5373554c0a3aSHans de Goede if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) { 5374554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5375554c0a3aSHans de Goede report_join_res(padapter, -2); 5376554c0a3aSHans de Goede return; 5377554c0a3aSHans de Goede } 5378554c0a3aSHans de Goede 5379554c0a3aSHans de Goede issue_assocreq(padapter); 5380554c0a3aSHans de Goede set_link_timer(pmlmeext, REASSOC_TO); 5381554c0a3aSHans de Goede } 5382554c0a3aSHans de Goede } 5383554c0a3aSHans de Goede 5384e8b1844aSKees Cook void addba_timer_hdl(struct timer_list *t) 5385554c0a3aSHans de Goede { 5386e8b1844aSKees Cook struct sta_info *psta = from_timer(psta, t, addba_retry_timer); 5387554c0a3aSHans de Goede struct ht_priv *phtpriv; 5388554c0a3aSHans de Goede 5389554c0a3aSHans de Goede if (!psta) 5390554c0a3aSHans de Goede return; 5391554c0a3aSHans de Goede 5392554c0a3aSHans de Goede phtpriv = &psta->htpriv; 5393554c0a3aSHans de Goede 53940ad02fa8SGeorgiana Chelu if (phtpriv->ht_option && phtpriv->ampdu_enable) { 5395554c0a3aSHans de Goede if (phtpriv->candidate_tid_bitmap) 5396554c0a3aSHans de Goede phtpriv->candidate_tid_bitmap = 0x0; 5397554c0a3aSHans de Goede 5398554c0a3aSHans de Goede } 5399554c0a3aSHans de Goede } 5400554c0a3aSHans de Goede 5401e8b1844aSKees Cook void sa_query_timer_hdl(struct timer_list *t) 5402554c0a3aSHans de Goede { 5403e8b1844aSKees Cook struct adapter *padapter = 5404e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.sa_query_timer); 5405554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 5406554c0a3aSHans de Goede /* disconnect */ 5407554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 5408554c0a3aSHans de Goede 54090ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, _FW_LINKED)) { 5410554c0a3aSHans de Goede rtw_disassoc_cmd(padapter, 0, true); 5411554c0a3aSHans de Goede rtw_indicate_disconnect(padapter); 5412554c0a3aSHans de Goede rtw_free_assoc_resources(padapter, 1); 5413554c0a3aSHans de Goede } 5414554c0a3aSHans de Goede 5415554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 5416554c0a3aSHans de Goede } 5417554c0a3aSHans de Goede 5418554c0a3aSHans de Goede u8 NULL_hdl(struct adapter *padapter, u8 *pbuf) 5419554c0a3aSHans de Goede { 5420554c0a3aSHans de Goede return H2C_SUCCESS; 5421554c0a3aSHans de Goede } 5422554c0a3aSHans de Goede 5423554c0a3aSHans de Goede u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) 5424554c0a3aSHans de Goede { 5425554c0a3aSHans de Goede u8 type; 5426554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5427554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5428554c0a3aSHans de Goede struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf; 5429554c0a3aSHans de Goede 5430554c0a3aSHans de Goede if (psetop->mode == Ndis802_11APMode) { 5431554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_AP_STATE; 5432554c0a3aSHans de Goede type = _HW_STATE_AP_; 5433554c0a3aSHans de Goede /* start_ap_mode(padapter); */ 5434554c0a3aSHans de Goede } else if (psetop->mode == Ndis802_11Infrastructure) { 5435554c0a3aSHans de Goede pmlmeinfo->state &= ~(BIT(0)|BIT(1));/* clear state */ 5436554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */ 5437554c0a3aSHans de Goede type = _HW_STATE_STATION_; 5438554c0a3aSHans de Goede } else if (psetop->mode == Ndis802_11IBSS) { 5439554c0a3aSHans de Goede type = _HW_STATE_ADHOC_; 5440554c0a3aSHans de Goede } else { 5441554c0a3aSHans de Goede type = _HW_STATE_NOLINK_; 5442554c0a3aSHans de Goede } 5443554c0a3aSHans de Goede 5444554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type)); 5445eb569cc0SNishka Dasgupta /* Set_MSR(padapter, type); */ 5446554c0a3aSHans de Goede 5447554c0a3aSHans de Goede if (psetop->mode == Ndis802_11APMode) { 5448554c0a3aSHans de Goede /* Do this after port switch to */ 5449554c0a3aSHans de Goede /* prevent from downloading rsvd page to wrong port */ 5450554c0a3aSHans de Goede rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */ 5451554c0a3aSHans de Goede } 5452554c0a3aSHans de Goede 5453554c0a3aSHans de Goede return H2C_SUCCESS; 5454554c0a3aSHans de Goede 5455554c0a3aSHans de Goede } 5456554c0a3aSHans de Goede 5457554c0a3aSHans de Goede u8 createbss_hdl(struct adapter *padapter, u8 *pbuf) 5458554c0a3aSHans de Goede { 5459554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5460554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5461554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 5462554c0a3aSHans de Goede struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf; 5463554c0a3aSHans de Goede /* u32 initialgain; */ 5464554c0a3aSHans de Goede 5465554c0a3aSHans de Goede if (pmlmeinfo->state == WIFI_FW_AP_STATE) { 5466554c0a3aSHans de Goede struct wlan_bssid_ex *network = &padapter->mlmepriv.cur_network.network; 5467c926f022SSimran Singhal 5468554c0a3aSHans de Goede start_bss_network(padapter, (u8 *)network); 5469554c0a3aSHans de Goede return H2C_SUCCESS; 5470554c0a3aSHans de Goede } 5471554c0a3aSHans de Goede 5472554c0a3aSHans de Goede /* below is for ad-hoc master */ 5473554c0a3aSHans de Goede if (pparm->network.InfrastructureMode == Ndis802_11IBSS) { 5474554c0a3aSHans de Goede rtw_joinbss_reset(padapter); 5475554c0a3aSHans de Goede 5476554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 5477554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 5478554c0a3aSHans de Goede pmlmeinfo->ERP_enable = 0; 5479554c0a3aSHans de Goede pmlmeinfo->WMM_enable = 0; 5480554c0a3aSHans de Goede pmlmeinfo->HT_enable = 0; 5481554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 0; 5482554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 0; 5483554c0a3aSHans de Goede pmlmeinfo->agg_enable_bitmap = 0; 5484554c0a3aSHans de Goede pmlmeinfo->candidate_tid_bitmap = 0; 5485554c0a3aSHans de Goede 5486554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 5487554c0a3aSHans de Goede Save_DM_Func_Flag(padapter); 5488554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); 5489554c0a3aSHans de Goede 5490554c0a3aSHans de Goede /* config the initial gain under linking, need to write the BB registers */ 5491554c0a3aSHans de Goede /* initialgain = 0x1E; */ 5492554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */ 5493554c0a3aSHans de Goede 5494554c0a3aSHans de Goede /* cancel link timer */ 5495554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 5496554c0a3aSHans de Goede 5497554c0a3aSHans de Goede /* clear CAM */ 5498554c0a3aSHans de Goede flush_all_cam_entry(padapter); 5499554c0a3aSHans de Goede 5500554c0a3aSHans de Goede memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength)); 5501554c0a3aSHans de Goede pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength; 5502554c0a3aSHans de Goede 5503554c0a3aSHans de Goede if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ 5504554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 5505554c0a3aSHans de Goede 5506554c0a3aSHans de Goede memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength); 5507554c0a3aSHans de Goede 5508554c0a3aSHans de Goede start_create_ibss(padapter); 5509554c0a3aSHans de Goede 5510554c0a3aSHans de Goede } 5511554c0a3aSHans de Goede 5512554c0a3aSHans de Goede return H2C_SUCCESS; 5513554c0a3aSHans de Goede 5514554c0a3aSHans de Goede } 5515554c0a3aSHans de Goede 5516554c0a3aSHans de Goede u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf) 5517554c0a3aSHans de Goede { 5518554c0a3aSHans de Goede u8 join_type; 5519554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 5520554c0a3aSHans de Goede struct registry_priv *pregpriv = &padapter->registrypriv; 5521554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5522554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5523554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 5524554c0a3aSHans de Goede u32 i; 5525554c0a3aSHans de Goede u8 cbw40_enable = 0; 5526554c0a3aSHans de Goede /* u32 initialgain; */ 5527554c0a3aSHans de Goede /* u32 acparm; */ 5528554c0a3aSHans de Goede u8 ch, bw, offset; 5529554c0a3aSHans de Goede 5530554c0a3aSHans de Goede /* check already connecting to AP or not */ 5531554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { 5532554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_STATION_STATE) { 5533554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); 5534554c0a3aSHans de Goede } 5535554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5536554c0a3aSHans de Goede 5537554c0a3aSHans de Goede /* clear CAM */ 5538554c0a3aSHans de Goede flush_all_cam_entry(padapter); 5539554c0a3aSHans de Goede 5540554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 5541554c0a3aSHans de Goede 5542554c0a3aSHans de Goede /* set MSR to nolink -> infra. mode */ 5543554c0a3aSHans de Goede /* Set_MSR(padapter, _HW_STATE_NOLINK_); */ 5544554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_STATION_); 5545554c0a3aSHans de Goede 5546554c0a3aSHans de Goede 5547554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL); 5548554c0a3aSHans de Goede } 5549554c0a3aSHans de Goede 5550554c0a3aSHans de Goede rtw_joinbss_reset(padapter); 5551554c0a3aSHans de Goede 5552554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 5553554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 5554554c0a3aSHans de Goede pmlmeinfo->ERP_enable = 0; 5555554c0a3aSHans de Goede pmlmeinfo->WMM_enable = 0; 5556554c0a3aSHans de Goede pmlmeinfo->HT_enable = 0; 5557554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 0; 5558554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 0; 5559554c0a3aSHans de Goede pmlmeinfo->agg_enable_bitmap = 0; 5560554c0a3aSHans de Goede pmlmeinfo->candidate_tid_bitmap = 0; 5561554c0a3aSHans de Goede pmlmeinfo->bwmode_updated = false; 5562554c0a3aSHans de Goede /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */ 5563554c0a3aSHans de Goede pmlmeinfo->VHT_enable = 0; 5564554c0a3aSHans de Goede 5565554c0a3aSHans de Goede memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength)); 5566554c0a3aSHans de Goede pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength; 5567554c0a3aSHans de Goede 5568554c0a3aSHans de Goede if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ 5569554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 5570554c0a3aSHans de Goede 5571554c0a3aSHans de Goede memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength); 5572554c0a3aSHans de Goede 5573554c0a3aSHans de Goede pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; 5574554c0a3aSHans de Goede pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); 5575554c0a3aSHans de Goede 5576554c0a3aSHans de Goede /* Check AP vendor to move rtw_joinbss_cmd() */ 5577554c0a3aSHans de Goede /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */ 5578554c0a3aSHans de Goede 5579554c0a3aSHans de Goede /* sizeof(struct ndis_802_11_fix_ie) */ 5580554c0a3aSHans de Goede for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) { 5581554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pnetwork->IEs + i); 5582554c0a3aSHans de Goede 5583554c0a3aSHans de Goede switch (pIE->ElementID) { 5584b05cc3a9SRoss Schmidt case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */ 5585554c0a3aSHans de Goede if (!memcmp(pIE->data, WMM_OUI, 4)) 5586554c0a3aSHans de Goede WMM_param_handler(padapter, pIE); 5587554c0a3aSHans de Goede break; 5588554c0a3aSHans de Goede 5589fc6a6528SRoss Schmidt case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */ 5590554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 1; 5591554c0a3aSHans de Goede break; 5592554c0a3aSHans de Goede 5593332ec9dbSRoss Schmidt case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */ 5594554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 1; 5595554c0a3aSHans de Goede 5596554c0a3aSHans de Goede /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */ 5597554c0a3aSHans de Goede { 5598554c0a3aSHans de Goede struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data); 5599554c0a3aSHans de Goede 5600554c0a3aSHans de Goede if (pnetwork->Configuration.DSConfig > 14) { 5601554c0a3aSHans de Goede if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20) 5602554c0a3aSHans de Goede cbw40_enable = 1; 5603554c0a3aSHans de Goede } else { 5604554c0a3aSHans de Goede if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20) 5605554c0a3aSHans de Goede cbw40_enable = 1; 5606554c0a3aSHans de Goede } 5607554c0a3aSHans de Goede 5608554c0a3aSHans de Goede if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) { 5609554c0a3aSHans de Goede /* switch to the 40M Hz mode according to the AP */ 5610554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_40; 5611554c0a3aSHans de Goede switch (pht_info->infos[0] & 0x3) { 5612554c0a3aSHans de Goede case 1: 5613554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; 5614554c0a3aSHans de Goede break; 5615554c0a3aSHans de Goede 5616554c0a3aSHans de Goede case 3: 5617554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; 5618554c0a3aSHans de Goede break; 5619554c0a3aSHans de Goede 5620554c0a3aSHans de Goede default: 5621554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 5622554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 5623554c0a3aSHans de Goede break; 5624554c0a3aSHans de Goede } 5625554c0a3aSHans de Goede } 5626554c0a3aSHans de Goede } 5627554c0a3aSHans de Goede break; 5628554c0a3aSHans de Goede default: 5629554c0a3aSHans de Goede break; 5630554c0a3aSHans de Goede } 5631554c0a3aSHans de Goede 5632554c0a3aSHans de Goede i += (pIE->Length + 2); 5633554c0a3aSHans de Goede } 5634554c0a3aSHans de Goede 5635554c0a3aSHans de Goede /* check channel, bandwidth, offset and switch */ 5636554c0a3aSHans de Goede if (rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) { 5637554c0a3aSHans de Goede report_join_res(padapter, (-4)); 5638554c0a3aSHans de Goede return H2C_SUCCESS; 5639554c0a3aSHans de Goede } 5640554c0a3aSHans de Goede 5641554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 5642554c0a3aSHans de Goede /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */ 5643554c0a3aSHans de Goede 5644554c0a3aSHans de Goede /* config the initial gain under linking, need to write the BB registers */ 5645554c0a3aSHans de Goede /* initialgain = 0x1E; */ 5646554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */ 5647554c0a3aSHans de Goede 5648554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress); 5649554c0a3aSHans de Goede join_type = 0; 5650554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5651554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL); 5652554c0a3aSHans de Goede 5653554c0a3aSHans de Goede set_channel_bwmode(padapter, ch, offset, bw); 5654554c0a3aSHans de Goede 5655554c0a3aSHans de Goede /* cancel link timer */ 5656554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 5657554c0a3aSHans de Goede 5658554c0a3aSHans de Goede start_clnt_join(padapter); 5659554c0a3aSHans de Goede 5660554c0a3aSHans de Goede return H2C_SUCCESS; 5661554c0a3aSHans de Goede 5662554c0a3aSHans de Goede } 5663554c0a3aSHans de Goede 5664554c0a3aSHans de Goede u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf) 5665554c0a3aSHans de Goede { 5666554c0a3aSHans de Goede struct disconnect_parm *param = (struct disconnect_parm *)pbuf; 5667554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5668554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5669554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 5670554c0a3aSHans de Goede u8 val8; 5671554c0a3aSHans de Goede 5672554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter)) { 5673554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100); 5674554c0a3aSHans de Goede } 5675554c0a3aSHans de Goede 5676554c0a3aSHans de Goede if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) { 5677554c0a3aSHans de Goede /* Stop BCN */ 5678554c0a3aSHans de Goede val8 = 0; 5679554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8)); 5680554c0a3aSHans de Goede } 5681554c0a3aSHans de Goede 5682554c0a3aSHans de Goede rtw_mlmeext_disconnect(padapter); 5683554c0a3aSHans de Goede 5684554c0a3aSHans de Goede rtw_free_uc_swdec_pending_queue(padapter); 5685554c0a3aSHans de Goede 5686554c0a3aSHans de Goede return H2C_SUCCESS; 5687554c0a3aSHans de Goede } 5688554c0a3aSHans de Goede 5689554c0a3aSHans de Goede static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out, 5690554c0a3aSHans de Goede u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num) 5691554c0a3aSHans de Goede { 5692554c0a3aSHans de Goede int i, j; 5693554c0a3aSHans de Goede int set_idx; 5694554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5695554c0a3aSHans de Goede 5696554c0a3aSHans de Goede /* clear first */ 5697554c0a3aSHans de Goede memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num); 5698554c0a3aSHans de Goede 5699554c0a3aSHans de Goede /* acquire channels from in */ 5700554c0a3aSHans de Goede j = 0; 5701554c0a3aSHans de Goede for (i = 0; i < in_num; i++) { 5702554c0a3aSHans de Goede 5703554c0a3aSHans de Goede set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value); 5704554c0a3aSHans de Goede if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) 5705554c0a3aSHans de Goede && set_idx >= 0 57060ad02fa8SGeorgiana Chelu && rtw_mlme_band_check(padapter, in[i].hw_value) 5707554c0a3aSHans de Goede ) { 5708554c0a3aSHans de Goede if (j >= out_num) { 5709554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n", 5710554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), out_num); 5711554c0a3aSHans de Goede break; 5712554c0a3aSHans de Goede } 5713554c0a3aSHans de Goede 5714554c0a3aSHans de Goede memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel)); 5715554c0a3aSHans de Goede 5716554c0a3aSHans de Goede if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE) 5717554c0a3aSHans de Goede out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; 5718554c0a3aSHans de Goede 5719554c0a3aSHans de Goede j++; 5720554c0a3aSHans de Goede } 5721554c0a3aSHans de Goede if (j >= out_num) 5722554c0a3aSHans de Goede break; 5723554c0a3aSHans de Goede } 5724554c0a3aSHans de Goede 5725554c0a3aSHans de Goede /* if out is empty, use channel_set as default */ 5726554c0a3aSHans de Goede if (j == 0) { 5727554c0a3aSHans de Goede for (i = 0; i < pmlmeext->max_chan_nums; i++) { 5728554c0a3aSHans de Goede 57290ad02fa8SGeorgiana Chelu if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum)) { 5730554c0a3aSHans de Goede 5731554c0a3aSHans de Goede if (j >= out_num) { 5732554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n", 5733554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), out_num); 5734554c0a3aSHans de Goede break; 5735554c0a3aSHans de Goede } 5736554c0a3aSHans de Goede 5737554c0a3aSHans de Goede out[j].hw_value = pmlmeext->channel_set[i].ChannelNum; 5738554c0a3aSHans de Goede 5739554c0a3aSHans de Goede if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) 5740554c0a3aSHans de Goede out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; 5741554c0a3aSHans de Goede 5742554c0a3aSHans de Goede j++; 5743554c0a3aSHans de Goede } 5744554c0a3aSHans de Goede } 5745554c0a3aSHans de Goede } 5746554c0a3aSHans de Goede 5747554c0a3aSHans de Goede return j; 5748554c0a3aSHans de Goede } 5749554c0a3aSHans de Goede 5750554c0a3aSHans de Goede u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf) 5751554c0a3aSHans de Goede { 5752554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5753554c0a3aSHans de Goede struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf; 5754554c0a3aSHans de Goede u8 bdelayscan = false; 5755554c0a3aSHans de Goede u8 val8; 5756554c0a3aSHans de Goede u32 initialgain; 5757554c0a3aSHans de Goede u32 i; 5758554c0a3aSHans de Goede 5759554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) { 5760554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_START; 5761554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt = 0; 5762554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = 0; 5763554c0a3aSHans de Goede 5764554c0a3aSHans de Goede for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { 5765554c0a3aSHans de Goede if (pparm->ssid[i].SsidLength) { 5766554c0a3aSHans de Goede memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE); 5767554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength; 5768554c0a3aSHans de Goede } else { 5769554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0; 5770554c0a3aSHans de Goede } 5771554c0a3aSHans de Goede } 5772554c0a3aSHans de Goede 5773554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter 5774554c0a3aSHans de Goede , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT 5775554c0a3aSHans de Goede , pparm->ch, pparm->ch_num 5776554c0a3aSHans de Goede ); 5777554c0a3aSHans de Goede 5778554c0a3aSHans de Goede pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode; 5779554c0a3aSHans de Goede 5780554c0a3aSHans de Goede /* issue null data if associating to the AP */ 57810ad02fa8SGeorgiana Chelu if (is_client_associated_to_ap(padapter)) { 5782554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_TXNULL; 5783554c0a3aSHans de Goede 5784554c0a3aSHans de Goede issue_nulldata(padapter, NULL, 1, 3, 500); 5785554c0a3aSHans de Goede 5786554c0a3aSHans de Goede bdelayscan = true; 5787554c0a3aSHans de Goede } 5788554c0a3aSHans de Goede if (bdelayscan) { 5789554c0a3aSHans de Goede /* delay 50ms to protect nulldata(1). */ 5790554c0a3aSHans de Goede set_survey_timer(pmlmeext, 50); 5791554c0a3aSHans de Goede return H2C_SUCCESS; 5792554c0a3aSHans de Goede } 5793554c0a3aSHans de Goede } 5794554c0a3aSHans de Goede 5795554c0a3aSHans de Goede if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) { 5796554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 5797554c0a3aSHans de Goede Save_DM_Func_Flag(padapter); 5798554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); 5799554c0a3aSHans de Goede 58004d17363dSAndreas Hellmich /* config the initial gain under scanning, need to write the BB 58014d17363dSAndreas Hellmich * registers 58024d17363dSAndreas Hellmich */ 5803554c0a3aSHans de Goede initialgain = 0x1e; 5804554c0a3aSHans de Goede 5805554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 5806554c0a3aSHans de Goede 5807554c0a3aSHans de Goede /* set MSR to no link state */ 5808554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_NOLINK_); 5809554c0a3aSHans de Goede 5810554c0a3aSHans de Goede val8 = 1; /* under site survey */ 5811554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); 5812554c0a3aSHans de Goede 5813554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_PROCESS; 5814554c0a3aSHans de Goede } 5815554c0a3aSHans de Goede 5816554c0a3aSHans de Goede site_survey(padapter); 5817554c0a3aSHans de Goede 5818554c0a3aSHans de Goede return H2C_SUCCESS; 5819554c0a3aSHans de Goede 5820554c0a3aSHans de Goede } 5821554c0a3aSHans de Goede 5822554c0a3aSHans de Goede u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf) 5823554c0a3aSHans de Goede { 5824554c0a3aSHans de Goede struct setauth_parm *pparm = (struct setauth_parm *)pbuf; 5825554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5826554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5827554c0a3aSHans de Goede 5828a65f0d18SVatsala Narang if (pparm->mode < 4) 5829554c0a3aSHans de Goede pmlmeinfo->auth_algo = pparm->mode; 5830554c0a3aSHans de Goede 5831554c0a3aSHans de Goede return H2C_SUCCESS; 5832554c0a3aSHans de Goede } 5833554c0a3aSHans de Goede 5834554c0a3aSHans de Goede u8 setkey_hdl(struct adapter *padapter, u8 *pbuf) 5835554c0a3aSHans de Goede { 5836554c0a3aSHans de Goede u16 ctrl = 0; 5837554c0a3aSHans de Goede s16 cam_id = 0; 5838554c0a3aSHans de Goede struct setkey_parm *pparm = (struct setkey_parm *)pbuf; 5839554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5840554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5841554c0a3aSHans de Goede unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 5842554c0a3aSHans de Goede u8 *addr; 5843554c0a3aSHans de Goede 5844554c0a3aSHans de Goede /* main tx key for wep. */ 5845554c0a3aSHans de Goede if (pparm->set_tx) 5846554c0a3aSHans de Goede pmlmeinfo->key_index = pparm->keyid; 5847554c0a3aSHans de Goede 5848554c0a3aSHans de Goede cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid); 5849554c0a3aSHans de Goede 5850554c0a3aSHans de Goede if (cam_id < 0) { 5851554c0a3aSHans de Goede } else { 5852554c0a3aSHans de Goede if (cam_id > 3) /* not default key, searched by A2 */ 5853554c0a3aSHans de Goede addr = get_bssid(&padapter->mlmepriv); 5854554c0a3aSHans de Goede else 5855554c0a3aSHans de Goede addr = null_addr; 5856554c0a3aSHans de Goede 5857554c0a3aSHans de Goede ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid; 5858554c0a3aSHans de Goede write_cam(padapter, cam_id, ctrl, addr, pparm->key); 5859bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "set group key camid:%d, addr:%pM, kid:%d, type:%s\n" 5860554c0a3aSHans de Goede , cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm)); 5861554c0a3aSHans de Goede } 5862554c0a3aSHans de Goede 5863554c0a3aSHans de Goede if (cam_id >= 0 && cam_id <= 3) 5864554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true); 5865554c0a3aSHans de Goede 5866554c0a3aSHans de Goede /* allow multicast packets to driver */ 5867554c0a3aSHans de Goede padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr); 5868554c0a3aSHans de Goede 5869554c0a3aSHans de Goede return H2C_SUCCESS; 5870554c0a3aSHans de Goede } 5871554c0a3aSHans de Goede 5872554c0a3aSHans de Goede u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf) 5873554c0a3aSHans de Goede { 5874554c0a3aSHans de Goede u16 ctrl = 0; 5875554c0a3aSHans de Goede s16 cam_id = 0; 5876554c0a3aSHans de Goede u8 ret = H2C_SUCCESS; 5877554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5878554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5879554c0a3aSHans de Goede struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf; 5880554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5881554c0a3aSHans de Goede struct sta_info *psta; 5882554c0a3aSHans de Goede 5883554c0a3aSHans de Goede if (pparm->algorithm == _NO_PRIVACY_) 5884554c0a3aSHans de Goede goto write_to_cam; 5885554c0a3aSHans de Goede 5886554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, pparm->addr); 5887554c0a3aSHans de Goede if (!psta) { 5888bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "%s sta:%pM not found\n", __func__, MAC_ARG(pparm->addr)); 5889554c0a3aSHans de Goede ret = H2C_REJECTED; 5890554c0a3aSHans de Goede goto exit; 5891554c0a3aSHans de Goede } 5892554c0a3aSHans de Goede 5893554c0a3aSHans de Goede pmlmeinfo->enc_algo = pparm->algorithm; 5894554c0a3aSHans de Goede cam_id = rtw_camid_alloc(padapter, psta, 0); 5895554c0a3aSHans de Goede if (cam_id < 0) 5896554c0a3aSHans de Goede goto exit; 5897554c0a3aSHans de Goede 5898554c0a3aSHans de Goede write_to_cam: 5899554c0a3aSHans de Goede if (pparm->algorithm == _NO_PRIVACY_) { 5900554c0a3aSHans de Goede while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) { 5901bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "clear key for addr:%pM, camid:%d\n", MAC_ARG(pparm->addr), cam_id); 5902554c0a3aSHans de Goede clear_cam_entry(padapter, cam_id); 5903554c0a3aSHans de Goede rtw_camid_free(padapter, cam_id); 5904554c0a3aSHans de Goede } 5905554c0a3aSHans de Goede } else { 5906bbda3ac4SRoss Schmidt DBG_871X_LEVEL(_drv_always_, "set pairwise key camid:%d, addr:%pM, kid:%d, type:%s\n", 5907554c0a3aSHans de Goede cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm)); 5908554c0a3aSHans de Goede ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid; 5909554c0a3aSHans de Goede write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key); 5910554c0a3aSHans de Goede } 5911554c0a3aSHans de Goede ret = H2C_SUCCESS_RSP; 5912554c0a3aSHans de Goede 5913554c0a3aSHans de Goede exit: 5914554c0a3aSHans de Goede return ret; 5915554c0a3aSHans de Goede } 5916554c0a3aSHans de Goede 5917554c0a3aSHans de Goede u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf) 5918554c0a3aSHans de Goede { 5919554c0a3aSHans de Goede struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf; 5920554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5921554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5922554c0a3aSHans de Goede 5923554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr); 5924554c0a3aSHans de Goede 5925554c0a3aSHans de Goede if (!psta) 5926554c0a3aSHans de Goede return H2C_SUCCESS; 5927554c0a3aSHans de Goede 5928554c0a3aSHans de Goede if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) || 5929554c0a3aSHans de Goede ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) { 5930554c0a3aSHans de Goede /* pmlmeinfo->ADDBA_retry_count = 0; */ 5931554c0a3aSHans de Goede /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */ 5932554c0a3aSHans de Goede /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */ 5933f4acd33cSRoss Schmidt issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid); 5934554c0a3aSHans de Goede /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */ 5935554c0a3aSHans de Goede _set_timer(&psta->addba_retry_timer, ADDBA_TO); 5936554c0a3aSHans de Goede } else { 5937554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid); 5938554c0a3aSHans de Goede } 5939554c0a3aSHans de Goede return H2C_SUCCESS; 5940554c0a3aSHans de Goede } 5941554c0a3aSHans de Goede 5942554c0a3aSHans de Goede 5943554c0a3aSHans de Goede u8 chk_bmc_sleepq_cmd(struct adapter *padapter) 5944554c0a3aSHans de Goede { 5945554c0a3aSHans de Goede struct cmd_obj *ph2c; 5946554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 5947554c0a3aSHans de Goede u8 res = _SUCCESS; 5948554c0a3aSHans de Goede 59492ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 5950554c0a3aSHans de Goede if (ph2c == NULL) { 5951554c0a3aSHans de Goede res = _FAIL; 5952554c0a3aSHans de Goede goto exit; 5953554c0a3aSHans de Goede } 5954554c0a3aSHans de Goede 5955554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq)); 5956554c0a3aSHans de Goede 5957554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 5958554c0a3aSHans de Goede 5959554c0a3aSHans de Goede exit: 5960554c0a3aSHans de Goede return res; 5961554c0a3aSHans de Goede } 5962554c0a3aSHans de Goede 5963554c0a3aSHans de Goede u8 set_tx_beacon_cmd(struct adapter *padapter) 5964554c0a3aSHans de Goede { 5965554c0a3aSHans de Goede struct cmd_obj *ph2c; 5966554c0a3aSHans de Goede struct Tx_Beacon_param *ptxBeacon_parm; 5967554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 5968554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5969554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5970554c0a3aSHans de Goede u8 res = _SUCCESS; 5971554c0a3aSHans de Goede int len_diff = 0; 5972554c0a3aSHans de Goede 59732ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 5974554c0a3aSHans de Goede if (ph2c == NULL) { 5975554c0a3aSHans de Goede res = _FAIL; 5976554c0a3aSHans de Goede goto exit; 5977554c0a3aSHans de Goede } 5978554c0a3aSHans de Goede 59792ef2b7c2SJoe Perches ptxBeacon_parm = rtw_zmalloc(sizeof(struct Tx_Beacon_param)); 5980554c0a3aSHans de Goede if (ptxBeacon_parm == NULL) { 59818f24f505SMadhumitha Prabakaran kfree(ph2c); 5982554c0a3aSHans de Goede res = _FAIL; 5983554c0a3aSHans de Goede goto exit; 5984554c0a3aSHans de Goede } 5985554c0a3aSHans de Goede 5986554c0a3aSHans de Goede memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex)); 5987554c0a3aSHans de Goede 59885641eeecSRoss Schmidt len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_, 59895641eeecSRoss Schmidt ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_, 59905641eeecSRoss Schmidt pmlmeinfo->hidden_ssid_mode); 5991554c0a3aSHans de Goede ptxBeacon_parm->network.IELength += len_diff; 5992554c0a3aSHans de Goede 5993554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon)); 5994554c0a3aSHans de Goede 5995554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 5996554c0a3aSHans de Goede 5997554c0a3aSHans de Goede exit: 5998554c0a3aSHans de Goede return res; 5999554c0a3aSHans de Goede } 6000554c0a3aSHans de Goede 6001554c0a3aSHans de Goede 6002554c0a3aSHans de Goede u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf) 6003554c0a3aSHans de Goede { 6004554c0a3aSHans de Goede u8 evt_code, evt_seq; 6005554c0a3aSHans de Goede u16 evt_sz; 6006554c0a3aSHans de Goede uint *peventbuf; 6007554c0a3aSHans de Goede void (*event_callback)(struct adapter *dev, u8 *pbuf); 6008554c0a3aSHans de Goede struct evt_priv *pevt_priv = &(padapter->evtpriv); 6009554c0a3aSHans de Goede 6010554c0a3aSHans de Goede if (pbuf == NULL) 6011554c0a3aSHans de Goede goto _abort_event_; 6012554c0a3aSHans de Goede 6013554c0a3aSHans de Goede peventbuf = (uint *)pbuf; 6014554c0a3aSHans de Goede evt_sz = (u16)(*peventbuf&0xffff); 6015554c0a3aSHans de Goede evt_seq = (u8)((*peventbuf>>24)&0x7f); 6016554c0a3aSHans de Goede evt_code = (u8)((*peventbuf>>16)&0xff); 6017554c0a3aSHans de Goede 6018554c0a3aSHans de Goede 6019554c0a3aSHans de Goede #ifdef CHECK_EVENT_SEQ 6020554c0a3aSHans de Goede /* checking event sequence... */ 6021554c0a3aSHans de Goede if (evt_seq != (atomic_read(&pevt_priv->event_seq) & 0x7f)) { 6022554c0a3aSHans de Goede pevt_priv->event_seq = (evt_seq+1)&0x7f; 6023554c0a3aSHans de Goede 6024554c0a3aSHans de Goede goto _abort_event_; 6025554c0a3aSHans de Goede } 6026554c0a3aSHans de Goede #endif 6027554c0a3aSHans de Goede 6028554c0a3aSHans de Goede /* checking if event code is valid */ 60290ac666f8SFabio Aiuto if (evt_code >= MAX_C2HEVT) 6030554c0a3aSHans de Goede goto _abort_event_; 6031554c0a3aSHans de Goede 6032554c0a3aSHans de Goede /* checking if event size match the event parm size */ 6033554c0a3aSHans de Goede if ((wlanevents[evt_code].parmsize != 0) && 60340ac666f8SFabio Aiuto (wlanevents[evt_code].parmsize != evt_sz)) 6035554c0a3aSHans de Goede goto _abort_event_; 6036554c0a3aSHans de Goede 6037554c0a3aSHans de Goede atomic_inc(&pevt_priv->event_seq); 6038554c0a3aSHans de Goede 6039554c0a3aSHans de Goede peventbuf += 2; 6040554c0a3aSHans de Goede 6041554c0a3aSHans de Goede if (peventbuf) { 6042554c0a3aSHans de Goede event_callback = wlanevents[evt_code].event_callback; 6043554c0a3aSHans de Goede event_callback(padapter, (u8 *)peventbuf); 6044554c0a3aSHans de Goede 6045554c0a3aSHans de Goede pevt_priv->evt_done_cnt++; 6046554c0a3aSHans de Goede } 6047554c0a3aSHans de Goede 6048554c0a3aSHans de Goede 6049554c0a3aSHans de Goede _abort_event_: 6050554c0a3aSHans de Goede 6051554c0a3aSHans de Goede 6052554c0a3aSHans de Goede return H2C_SUCCESS; 6053554c0a3aSHans de Goede 6054554c0a3aSHans de Goede } 6055554c0a3aSHans de Goede 6056554c0a3aSHans de Goede u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf) 6057554c0a3aSHans de Goede { 6058554c0a3aSHans de Goede if (!pbuf) 6059554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6060554c0a3aSHans de Goede 6061554c0a3aSHans de Goede return H2C_SUCCESS; 6062554c0a3aSHans de Goede } 6063554c0a3aSHans de Goede 6064554c0a3aSHans de Goede u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) 6065554c0a3aSHans de Goede { 6066554c0a3aSHans de Goede struct sta_info *psta_bmc; 6067554c0a3aSHans de Goede struct list_head *xmitframe_plist, *xmitframe_phead; 6068554c0a3aSHans de Goede struct xmit_frame *pxmitframe = NULL; 6069554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 6070554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 6071554c0a3aSHans de Goede 6072554c0a3aSHans de Goede /* for BC/MC Frames */ 6073554c0a3aSHans de Goede psta_bmc = rtw_get_bcmc_stainfo(padapter); 6074554c0a3aSHans de Goede if (!psta_bmc) 6075554c0a3aSHans de Goede return H2C_SUCCESS; 6076554c0a3aSHans de Goede 6077554c0a3aSHans de Goede if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) { 6078554c0a3aSHans de Goede msleep(10);/* 10ms, ATIM(HIQ) Windows */ 6079554c0a3aSHans de Goede 6080554c0a3aSHans de Goede /* spin_lock_bh(&psta_bmc->sleep_q.lock); */ 6081554c0a3aSHans de Goede spin_lock_bh(&pxmitpriv->lock); 6082554c0a3aSHans de Goede 6083554c0a3aSHans de Goede xmitframe_phead = get_list_head(&psta_bmc->sleep_q); 6084554c0a3aSHans de Goede xmitframe_plist = get_next(xmitframe_phead); 6085554c0a3aSHans de Goede 6086554c0a3aSHans de Goede while (xmitframe_phead != xmitframe_plist) { 608719cf9d7aSRoss Schmidt pxmitframe = container_of(xmitframe_plist, struct xmit_frame, list); 6088554c0a3aSHans de Goede 6089554c0a3aSHans de Goede xmitframe_plist = get_next(xmitframe_plist); 6090554c0a3aSHans de Goede 6091554c0a3aSHans de Goede list_del_init(&pxmitframe->list); 6092554c0a3aSHans de Goede 6093554c0a3aSHans de Goede psta_bmc->sleepq_len--; 6094554c0a3aSHans de Goede if (psta_bmc->sleepq_len > 0) 6095554c0a3aSHans de Goede pxmitframe->attrib.mdata = 1; 6096554c0a3aSHans de Goede else 6097554c0a3aSHans de Goede pxmitframe->attrib.mdata = 0; 6098554c0a3aSHans de Goede 6099554c0a3aSHans de Goede pxmitframe->attrib.triggered = 1; 6100554c0a3aSHans de Goede 61010ad02fa8SGeorgiana Chelu if (xmitframe_hiq_filter(pxmitframe)) 6102554c0a3aSHans de Goede pxmitframe->attrib.qsel = 0x11;/* HIQ */ 6103554c0a3aSHans de Goede 6104554c0a3aSHans de Goede rtw_hal_xmitframe_enqueue(padapter, pxmitframe); 6105554c0a3aSHans de Goede } 6106554c0a3aSHans de Goede 6107554c0a3aSHans de Goede /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ 6108554c0a3aSHans de Goede spin_unlock_bh(&pxmitpriv->lock); 6109554c0a3aSHans de Goede 6110554c0a3aSHans de Goede /* check hi queue and bmc_sleepq */ 6111554c0a3aSHans de Goede rtw_chk_hi_queue_cmd(padapter); 6112554c0a3aSHans de Goede } 6113554c0a3aSHans de Goede 6114554c0a3aSHans de Goede return H2C_SUCCESS; 6115554c0a3aSHans de Goede } 6116554c0a3aSHans de Goede 6117554c0a3aSHans de Goede u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf) 6118554c0a3aSHans de Goede { 6119709c8e49SFabio Aiuto if (send_beacon(padapter) == _FAIL) 6120554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6121554c0a3aSHans de Goede 6122554c0a3aSHans de Goede /* tx bc/mc frames after update TIM */ 6123554c0a3aSHans de Goede chk_bmc_sleepq_hdl(padapter, NULL); 6124554c0a3aSHans de Goede 6125554c0a3aSHans de Goede return H2C_SUCCESS; 6126554c0a3aSHans de Goede } 6127554c0a3aSHans de Goede 6128554c0a3aSHans de Goede int rtw_chk_start_clnt_join(struct adapter *padapter, u8 *ch, u8 *bw, u8 *offset) 6129554c0a3aSHans de Goede { 6130554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6131554c0a3aSHans de Goede unsigned char cur_ch = pmlmeext->cur_channel; 6132554c0a3aSHans de Goede unsigned char cur_bw = pmlmeext->cur_bwmode; 6133554c0a3aSHans de Goede unsigned char cur_ch_offset = pmlmeext->cur_ch_offset; 6134554c0a3aSHans de Goede bool connect_allow = true; 6135554c0a3aSHans de Goede 6136554c0a3aSHans de Goede if (!ch || !bw || !offset) { 6137554c0a3aSHans de Goede rtw_warn_on(1); 6138554c0a3aSHans de Goede connect_allow = false; 6139554c0a3aSHans de Goede } 6140554c0a3aSHans de Goede 61410ad02fa8SGeorgiana Chelu if (connect_allow) { 6142554c0a3aSHans de Goede *ch = cur_ch; 6143554c0a3aSHans de Goede *bw = cur_bw; 6144554c0a3aSHans de Goede *offset = cur_ch_offset; 6145554c0a3aSHans de Goede } 6146554c0a3aSHans de Goede 614763a9c3edSJeeeun Evans return connect_allow ? _SUCCESS : _FAIL; 6148554c0a3aSHans de Goede } 6149554c0a3aSHans de Goede 6150554c0a3aSHans de Goede /* Find union about ch, bw, ch_offset of all linked/linking interfaces */ 6151554c0a3aSHans de Goede int rtw_get_ch_setting_union(struct adapter *adapter, u8 *ch, u8 *bw, u8 *offset) 6152554c0a3aSHans de Goede { 6153554c0a3aSHans de Goede struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); 6154554c0a3aSHans de Goede struct adapter *iface; 6155554c0a3aSHans de Goede 6156554c0a3aSHans de Goede if (ch) 6157554c0a3aSHans de Goede *ch = 0; 6158554c0a3aSHans de Goede if (bw) 6159554c0a3aSHans de Goede *bw = CHANNEL_WIDTH_20; 6160554c0a3aSHans de Goede if (offset) 6161554c0a3aSHans de Goede *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 6162554c0a3aSHans de Goede 6163554c0a3aSHans de Goede iface = dvobj->padapters; 6164554c0a3aSHans de Goede 6165554c0a3aSHans de Goede if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING)) 6166554c0a3aSHans de Goede return 0; 6167554c0a3aSHans de Goede 6168554c0a3aSHans de Goede return 1; 6169554c0a3aSHans de Goede } 6170554c0a3aSHans de Goede 6171554c0a3aSHans de Goede u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf) 6172554c0a3aSHans de Goede { 6173554c0a3aSHans de Goede struct set_ch_parm *set_ch_parm; 6174554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6175554c0a3aSHans de Goede 6176554c0a3aSHans de Goede if (!pbuf) 6177554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6178554c0a3aSHans de Goede 6179554c0a3aSHans de Goede set_ch_parm = (struct set_ch_parm *)pbuf; 6180554c0a3aSHans de Goede 6181554c0a3aSHans de Goede pmlmeext->cur_channel = set_ch_parm->ch; 6182554c0a3aSHans de Goede pmlmeext->cur_ch_offset = set_ch_parm->ch_offset; 6183554c0a3aSHans de Goede pmlmeext->cur_bwmode = set_ch_parm->bw; 6184554c0a3aSHans de Goede 6185554c0a3aSHans de Goede set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw); 6186554c0a3aSHans de Goede 6187554c0a3aSHans de Goede return H2C_SUCCESS; 6188554c0a3aSHans de Goede } 6189554c0a3aSHans de Goede 6190554c0a3aSHans de Goede u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf) 6191554c0a3aSHans de Goede { 6192554c0a3aSHans de Goede struct SetChannelPlan_param *setChannelPlan_param; 6193554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6194554c0a3aSHans de Goede 6195554c0a3aSHans de Goede if (!pbuf) 6196554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6197554c0a3aSHans de Goede 6198554c0a3aSHans de Goede setChannelPlan_param = (struct SetChannelPlan_param *)pbuf; 6199554c0a3aSHans de Goede 6200554c0a3aSHans de Goede pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set); 6201554c0a3aSHans de Goede init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); 6202554c0a3aSHans de Goede 620334557e23SIzabela Bakollari if (padapter->rtw_wdev && padapter->rtw_wdev->wiphy) { 6204554c0a3aSHans de Goede struct regulatory_request request; 6205c926f022SSimran Singhal 6206554c0a3aSHans de Goede request.initiator = NL80211_REGDOM_SET_BY_DRIVER; 6207554c0a3aSHans de Goede rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request); 6208554c0a3aSHans de Goede } 6209554c0a3aSHans de Goede 6210554c0a3aSHans de Goede return H2C_SUCCESS; 6211554c0a3aSHans de Goede } 6212554c0a3aSHans de Goede 6213554c0a3aSHans de Goede u8 led_blink_hdl(struct adapter *padapter, unsigned char *pbuf) 6214554c0a3aSHans de Goede { 6215554c0a3aSHans de Goede struct LedBlink_param *ledBlink_param; 6216554c0a3aSHans de Goede 6217554c0a3aSHans de Goede if (!pbuf) 6218554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6219554c0a3aSHans de Goede 6220554c0a3aSHans de Goede ledBlink_param = (struct LedBlink_param *)pbuf; 6221554c0a3aSHans de Goede return H2C_SUCCESS; 6222554c0a3aSHans de Goede } 6223554c0a3aSHans de Goede 6224554c0a3aSHans de Goede u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf) 6225554c0a3aSHans de Goede { 6226554c0a3aSHans de Goede return H2C_REJECTED; 6227554c0a3aSHans de Goede } 6228554c0a3aSHans de Goede 6229554c0a3aSHans de Goede /* TDLS_ESTABLISHED : write RCR DATA BIT */ 6230554c0a3aSHans de Goede /* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */ 6231554c0a3aSHans de Goede /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */ 6232554c0a3aSHans de Goede /* TDLS_DONE_CH_SEN: channel sensing and report candidate channel */ 6233554c0a3aSHans de Goede /* TDLS_OFF_CH : first time set channel to off channel */ 6234554c0a3aSHans de Goede /* TDLS_BASE_CH : go back tp the channel linked with AP when set base channel as target channel */ 6235554c0a3aSHans de Goede /* TDLS_P_OFF_CH : periodically go to off channel */ 6236554c0a3aSHans de Goede /* TDLS_P_BASE_CH : periodically go back to base channel */ 6237554c0a3aSHans de Goede /* TDLS_RS_RCR : restore RCR */ 6238554c0a3aSHans de Goede /* TDLS_TEAR_STA : free tdls sta */ 6239554c0a3aSHans de Goede u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf) 6240554c0a3aSHans de Goede { 6241554c0a3aSHans de Goede return H2C_REJECTED; 6242554c0a3aSHans de Goede } 6243554c0a3aSHans de Goede 6244554c0a3aSHans de Goede u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf) 6245554c0a3aSHans de Goede { 6246554c0a3aSHans de Goede struct RunInThread_param *p; 6247554c0a3aSHans de Goede 6248554c0a3aSHans de Goede 6249554c0a3aSHans de Goede if (NULL == pbuf) 6250554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6251554c0a3aSHans de Goede p = (struct RunInThread_param *)pbuf; 6252554c0a3aSHans de Goede 6253554c0a3aSHans de Goede if (p->func) 6254554c0a3aSHans de Goede p->func(p->context); 6255554c0a3aSHans de Goede 6256554c0a3aSHans de Goede return H2C_SUCCESS; 6257554c0a3aSHans de Goede } 6258