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 #include <drv_types.h> 8554c0a3aSHans de Goede #include <rtw_debug.h> 9554c0a3aSHans de Goede #include <rtw_wifi_regd.h> 10d312a47fSNishka Dasgupta #include <hal_btcoex.h> 1160db8d10SJérémy Lefaure #include <linux/kernel.h> 12d48603afSRoss Schmidt #include <asm/unaligned.h> 13554c0a3aSHans de Goede 14554c0a3aSHans de Goede static struct mlme_handler mlme_sta_tbl[] = { 15554c0a3aSHans de Goede {WIFI_ASSOCREQ, "OnAssocReq", &OnAssocReq}, 16554c0a3aSHans de Goede {WIFI_ASSOCRSP, "OnAssocRsp", &OnAssocRsp}, 17554c0a3aSHans de Goede {WIFI_REASSOCREQ, "OnReAssocReq", &OnAssocReq}, 18554c0a3aSHans de Goede {WIFI_REASSOCRSP, "OnReAssocRsp", &OnAssocRsp}, 19554c0a3aSHans de Goede {WIFI_PROBEREQ, "OnProbeReq", &OnProbeReq}, 20554c0a3aSHans de Goede {WIFI_PROBERSP, "OnProbeRsp", &OnProbeRsp}, 21554c0a3aSHans de Goede 22554c0a3aSHans de Goede /*---------------------------------------------------------- 23554c0a3aSHans de Goede below 2 are reserved 24554c0a3aSHans de Goede -----------------------------------------------------------*/ 25554c0a3aSHans de Goede {0, "DoReserved", &DoReserved}, 26554c0a3aSHans de Goede {0, "DoReserved", &DoReserved}, 27554c0a3aSHans de Goede {WIFI_BEACON, "OnBeacon", &OnBeacon}, 28554c0a3aSHans de Goede {WIFI_ATIM, "OnATIM", &OnAtim}, 29554c0a3aSHans de Goede {WIFI_DISASSOC, "OnDisassoc", &OnDisassoc}, 30554c0a3aSHans de Goede {WIFI_AUTH, "OnAuth", &OnAuthClient}, 31554c0a3aSHans de Goede {WIFI_DEAUTH, "OnDeAuth", &OnDeAuth}, 32554c0a3aSHans de Goede {WIFI_ACTION, "OnAction", &OnAction}, 33554c0a3aSHans de Goede {WIFI_ACTION_NOACK, "OnActionNoAck", &OnAction}, 34554c0a3aSHans de Goede }; 35554c0a3aSHans de Goede 36554c0a3aSHans de Goede static struct action_handler OnAction_tbl[] = { 37554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_SPECTRUM_MGMT, "ACTION_SPECTRUM_MGMT", on_action_spct}, 38554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &DoReserved}, 39554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &DoReserved}, 40554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back}, 41554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public}, 42554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved}, 43554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_FT, "ACTION_FT", &DoReserved}, 44554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_HT, "ACTION_HT", &OnAction_ht}, 45554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query}, 46554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved}, 47554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved}, 48554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &DoReserved}, 49554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &DoReserved}, 50554c0a3aSHans de Goede {RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &DoReserved}, 51554c0a3aSHans de Goede }; 52554c0a3aSHans de Goede 53554c0a3aSHans de Goede static u8 null_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; 54554c0a3aSHans de Goede 55554c0a3aSHans de Goede /************************************************** 56554c0a3aSHans de Goede OUI definitions for the vendor specific IE 57554c0a3aSHans de Goede ***************************************************/ 58554c0a3aSHans de Goede unsigned char RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01}; 59554c0a3aSHans de Goede unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02}; 60554c0a3aSHans de Goede unsigned char WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04}; 61554c0a3aSHans de Goede unsigned char P2P_OUI[] = {0x50, 0x6F, 0x9A, 0x09}; 62554c0a3aSHans de Goede unsigned char WFD_OUI[] = {0x50, 0x6F, 0x9A, 0x0A}; 63554c0a3aSHans de Goede 64554c0a3aSHans de Goede unsigned char WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01}; 65554c0a3aSHans de Goede unsigned char WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; 66554c0a3aSHans de Goede 67554c0a3aSHans de Goede static unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20}; 68554c0a3aSHans de Goede 69554c0a3aSHans de Goede /******************************************************** 70554c0a3aSHans de Goede ChannelPlan definitions 71554c0a3aSHans de Goede *********************************************************/ 72f0e46c47SMarco Cesati static struct rt_channel_plan_2g RTW_ChannelPlan2G[RT_CHANNEL_DOMAIN_2G_MAX] = { 73554c0a3aSHans 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 */ 74554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, /* 0x01, RT_CHANNEL_DOMAIN_2G_ETSI1 */ 75554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* 0x02, RT_CHANNEL_DOMAIN_2G_FCC1 */ 76554c0a3aSHans de Goede {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, /* 0x03, RT_CHANNEL_DOMAIN_2G_MIKK1 */ 77554c0a3aSHans de Goede {{10, 11, 12, 13}, 4}, /* 0x04, RT_CHANNEL_DOMAIN_2G_ETSI2 */ 78554c0a3aSHans 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 */ 79554c0a3aSHans de Goede {{}, 0}, /* 0x06, RT_CHANNEL_DOMAIN_2G_NULL */ 80554c0a3aSHans de Goede }; 81554c0a3aSHans de Goede 82f0e46c47SMarco Cesati static struct rt_channel_plan_5g RTW_ChannelPlan5G[RT_CHANNEL_DOMAIN_5G_MAX] = { 83554c0a3aSHans de Goede {{}, 0}, /* 0x00, RT_CHANNEL_DOMAIN_5G_NULL */ 84554c0a3aSHans 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 */ 85554c0a3aSHans 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 */ 86554c0a3aSHans 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 */ 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}, /* 0x04, RT_CHANNEL_DOMAIN_5G_FCC1 */ 88554c0a3aSHans de Goede {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x05, RT_CHANNEL_DOMAIN_5G_FCC2 */ 89554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x06, RT_CHANNEL_DOMAIN_5G_FCC3 */ 90554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12}, /* 0x07, RT_CHANNEL_DOMAIN_5G_FCC4 */ 91554c0a3aSHans de Goede {{149, 153, 157, 161, 165}, 5}, /* 0x08, RT_CHANNEL_DOMAIN_5G_FCC5 */ 92554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x09, RT_CHANNEL_DOMAIN_5G_FCC6 */ 93554c0a3aSHans 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 */ 94554c0a3aSHans 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 */ 95554c0a3aSHans 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 */ 96554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x0D, RT_CHANNEL_DOMAIN_5G_MKK2 */ 97554c0a3aSHans de Goede {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x0E, RT_CHANNEL_DOMAIN_5G_MKK3 */ 98554c0a3aSHans de Goede {{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15}, /* 0x0F, RT_CHANNEL_DOMAIN_5G_NCC1 */ 99554c0a3aSHans de Goede {{56, 60, 64, 149, 153, 157, 161, 165}, 8}, /* 0x10, RT_CHANNEL_DOMAIN_5G_NCC2 */ 100554c0a3aSHans de Goede {{149, 153, 157, 161, 165}, 5}, /* 0x11, RT_CHANNEL_DOMAIN_5G_NCC3 */ 101554c0a3aSHans de Goede {{36, 40, 44, 48}, 4}, /* 0x12, RT_CHANNEL_DOMAIN_5G_ETSI4 */ 102554c0a3aSHans 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 */ 103554c0a3aSHans de Goede {{149, 153, 157, 161}, 4}, /* 0x14, RT_CHANNEL_DOMAIN_5G_FCC8 */ 104554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64}, 8}, /* 0x15, RT_CHANNEL_DOMAIN_5G_ETSI6 */ 105554c0a3aSHans de Goede {{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13}, /* 0x16, RT_CHANNEL_DOMAIN_5G_ETSI7 */ 106554c0a3aSHans de Goede {{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9}, /* 0x17, RT_CHANNEL_DOMAIN_5G_ETSI8 */ 107554c0a3aSHans de Goede {{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11}, /* 0x18, RT_CHANNEL_DOMAIN_5G_ETSI9 */ 108554c0a3aSHans de Goede {{149, 153, 157, 161, 165}, 5}, /* 0x19, RT_CHANNEL_DOMAIN_5G_ETSI10 */ 109554c0a3aSHans 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 */ 110554c0a3aSHans 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 */ 111554c0a3aSHans de Goede {{149, 153, 157, 161}, 4}, /* 0x1C, RT_CHANNEL_DOMAIN_5G_ETSI12 */ 112554c0a3aSHans 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 */ 113554c0a3aSHans de Goede {{36, 40, 44, 48, 100, 104, 108, 112, 116, 132, 136, 140}, 12}, /* 0x1E, RT_CHANNEL_DOMAIN_5G_ETSI13 */ 114554c0a3aSHans 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 */ 115554c0a3aSHans de Goede 116554c0a3aSHans de Goede /* Driver self defined for old channel plan Compatible , Remember to modify if have new channel plan definition ===== */ 117554c0a3aSHans 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 */ 118554c0a3aSHans de Goede {{36, 40, 44, 48}, 4}, /* 0x21, RT_CHANNEL_DOMAIN_5G_JAPAN_NO_DFS */ 119554c0a3aSHans de Goede {{36, 40, 44, 48, 149, 153, 157, 161}, 8}, /* 0x22, RT_CHANNEL_DOMAIN_5G_FCC4_NO_DFS */ 120554c0a3aSHans de Goede }; 121554c0a3aSHans de Goede 122f0e46c47SMarco Cesati static struct rt_channel_plan_map RTW_ChannelPlanMap[RT_CHANNEL_DOMAIN_MAX] = { 123554c0a3aSHans de Goede /* 0x00 ~ 0x1F , Old Define ===== */ 124554c0a3aSHans de Goede {0x02, 0x20}, /* 0x00, RT_CHANNEL_DOMAIN_FCC */ 125554c0a3aSHans de Goede {0x02, 0x0A}, /* 0x01, RT_CHANNEL_DOMAIN_IC */ 126554c0a3aSHans de Goede {0x01, 0x01}, /* 0x02, RT_CHANNEL_DOMAIN_ETSI */ 127554c0a3aSHans de Goede {0x01, 0x00}, /* 0x03, RT_CHANNEL_DOMAIN_SPAIN */ 128554c0a3aSHans de Goede {0x01, 0x00}, /* 0x04, RT_CHANNEL_DOMAIN_FRANCE */ 129554c0a3aSHans de Goede {0x03, 0x00}, /* 0x05, RT_CHANNEL_DOMAIN_MKK */ 130554c0a3aSHans de Goede {0x03, 0x00}, /* 0x06, RT_CHANNEL_DOMAIN_MKK1 */ 131554c0a3aSHans de Goede {0x01, 0x09}, /* 0x07, RT_CHANNEL_DOMAIN_ISRAEL */ 132554c0a3aSHans de Goede {0x03, 0x09}, /* 0x08, RT_CHANNEL_DOMAIN_TELEC */ 133554c0a3aSHans de Goede {0x03, 0x00}, /* 0x09, RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN */ 134554c0a3aSHans de Goede {0x00, 0x00}, /* 0x0A, RT_CHANNEL_DOMAIN_WORLD_WIDE_13 */ 135554c0a3aSHans de Goede {0x02, 0x0F}, /* 0x0B, RT_CHANNEL_DOMAIN_TAIWAN */ 136554c0a3aSHans de Goede {0x01, 0x08}, /* 0x0C, RT_CHANNEL_DOMAIN_CHINA */ 137554c0a3aSHans de Goede {0x02, 0x06}, /* 0x0D, RT_CHANNEL_DOMAIN_SINGAPORE_INDIA_MEXICO */ 138554c0a3aSHans de Goede {0x02, 0x0B}, /* 0x0E, RT_CHANNEL_DOMAIN_KOREA */ 139554c0a3aSHans de Goede {0x02, 0x09}, /* 0x0F, RT_CHANNEL_DOMAIN_TURKEY */ 140554c0a3aSHans de Goede {0x01, 0x01}, /* 0x10, RT_CHANNEL_DOMAIN_JAPAN */ 141554c0a3aSHans de Goede {0x02, 0x05}, /* 0x11, RT_CHANNEL_DOMAIN_FCC_NO_DFS */ 142554c0a3aSHans de Goede {0x01, 0x21}, /* 0x12, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ 143554c0a3aSHans de Goede {0x00, 0x04}, /* 0x13, RT_CHANNEL_DOMAIN_WORLD_WIDE_5G */ 144554c0a3aSHans de Goede {0x02, 0x10}, /* 0x14, RT_CHANNEL_DOMAIN_TAIWAN_NO_DFS */ 145554c0a3aSHans de Goede {0x00, 0x21}, /* 0x15, RT_CHANNEL_DOMAIN_ETSI_NO_DFS */ 146554c0a3aSHans de Goede {0x00, 0x22}, /* 0x16, RT_CHANNEL_DOMAIN_KOREA_NO_DFS */ 147554c0a3aSHans de Goede {0x03, 0x21}, /* 0x17, RT_CHANNEL_DOMAIN_JAPAN_NO_DFS */ 148554c0a3aSHans de Goede {0x06, 0x08}, /* 0x18, RT_CHANNEL_DOMAIN_PAKISTAN_NO_DFS */ 149554c0a3aSHans de Goede {0x02, 0x08}, /* 0x19, RT_CHANNEL_DOMAIN_TAIWAN2_NO_DFS */ 150554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1A, */ 151554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1B, */ 152554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1C, */ 153554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1D, */ 154554c0a3aSHans de Goede {0x00, 0x00}, /* 0x1E, */ 155554c0a3aSHans de Goede {0x06, 0x04}, /* 0x1F, RT_CHANNEL_DOMAIN_WORLD_WIDE_ONLY_5G */ 156554c0a3aSHans de Goede /* 0x20 ~ 0x7F , New Define ===== */ 157554c0a3aSHans de Goede {0x00, 0x00}, /* 0x20, RT_CHANNEL_DOMAIN_WORLD_NULL */ 158554c0a3aSHans de Goede {0x01, 0x00}, /* 0x21, RT_CHANNEL_DOMAIN_ETSI1_NULL */ 159554c0a3aSHans de Goede {0x02, 0x00}, /* 0x22, RT_CHANNEL_DOMAIN_FCC1_NULL */ 160554c0a3aSHans de Goede {0x03, 0x00}, /* 0x23, RT_CHANNEL_DOMAIN_MKK1_NULL */ 161554c0a3aSHans de Goede {0x04, 0x00}, /* 0x24, RT_CHANNEL_DOMAIN_ETSI2_NULL */ 162554c0a3aSHans de Goede {0x02, 0x04}, /* 0x25, RT_CHANNEL_DOMAIN_FCC1_FCC1 */ 163554c0a3aSHans de Goede {0x00, 0x01}, /* 0x26, RT_CHANNEL_DOMAIN_WORLD_ETSI1 */ 164554c0a3aSHans de Goede {0x03, 0x0C}, /* 0x27, RT_CHANNEL_DOMAIN_MKK1_MKK1 */ 165554c0a3aSHans de Goede {0x00, 0x0B}, /* 0x28, RT_CHANNEL_DOMAIN_WORLD_KCC1 */ 166554c0a3aSHans de Goede {0x00, 0x05}, /* 0x29, RT_CHANNEL_DOMAIN_WORLD_FCC2 */ 167554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2A, */ 168554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2B, */ 169554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2C, */ 170554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2D, */ 171554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2E, */ 172554c0a3aSHans de Goede {0x00, 0x00}, /* 0x2F, */ 173554c0a3aSHans de Goede {0x00, 0x06}, /* 0x30, RT_CHANNEL_DOMAIN_WORLD_FCC3 */ 174554c0a3aSHans de Goede {0x00, 0x07}, /* 0x31, RT_CHANNEL_DOMAIN_WORLD_FCC4 */ 175554c0a3aSHans de Goede {0x00, 0x08}, /* 0x32, RT_CHANNEL_DOMAIN_WORLD_FCC5 */ 176554c0a3aSHans de Goede {0x00, 0x09}, /* 0x33, RT_CHANNEL_DOMAIN_WORLD_FCC6 */ 177554c0a3aSHans de Goede {0x02, 0x0A}, /* 0x34, RT_CHANNEL_DOMAIN_FCC1_FCC7 */ 178554c0a3aSHans de Goede {0x00, 0x02}, /* 0x35, RT_CHANNEL_DOMAIN_WORLD_ETSI2 */ 179554c0a3aSHans de Goede {0x00, 0x03}, /* 0x36, RT_CHANNEL_DOMAIN_WORLD_ETSI3 */ 180554c0a3aSHans de Goede {0x03, 0x0D}, /* 0x37, RT_CHANNEL_DOMAIN_MKK1_MKK2 */ 181554c0a3aSHans de Goede {0x03, 0x0E}, /* 0x38, RT_CHANNEL_DOMAIN_MKK1_MKK3 */ 182554c0a3aSHans de Goede {0x02, 0x0F}, /* 0x39, RT_CHANNEL_DOMAIN_FCC1_NCC1 */ 183554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3A, */ 184554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3B, */ 185554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3C, */ 186554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3D, */ 187554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3E, */ 188554c0a3aSHans de Goede {0x00, 0x00}, /* 0x3F, */ 189554c0a3aSHans de Goede {0x02, 0x10}, /* 0x40, RT_CHANNEL_DOMAIN_FCC1_NCC2 */ 190554c0a3aSHans de Goede {0x05, 0x00}, /* 0x41, RT_CHANNEL_DOMAIN_GLOBAL_NULL */ 191554c0a3aSHans de Goede {0x01, 0x12}, /* 0x42, RT_CHANNEL_DOMAIN_ETSI1_ETSI4 */ 192554c0a3aSHans de Goede {0x02, 0x05}, /* 0x43, RT_CHANNEL_DOMAIN_FCC1_FCC2 */ 193554c0a3aSHans de Goede {0x02, 0x11}, /* 0x44, RT_CHANNEL_DOMAIN_FCC1_NCC3 */ 194554c0a3aSHans de Goede {0x00, 0x13}, /* 0x45, RT_CHANNEL_DOMAIN_WORLD_ETSI5 */ 195554c0a3aSHans de Goede {0x02, 0x14}, /* 0x46, RT_CHANNEL_DOMAIN_FCC1_FCC8 */ 196554c0a3aSHans de Goede {0x00, 0x15}, /* 0x47, RT_CHANNEL_DOMAIN_WORLD_ETSI6 */ 197554c0a3aSHans de Goede {0x00, 0x16}, /* 0x48, RT_CHANNEL_DOMAIN_WORLD_ETSI7 */ 198554c0a3aSHans de Goede {0x00, 0x17}, /* 0x49, RT_CHANNEL_DOMAIN_WORLD_ETSI8 */ 199554c0a3aSHans de Goede {0x00, 0x18}, /* 0x50, RT_CHANNEL_DOMAIN_WORLD_ETSI9 */ 200554c0a3aSHans de Goede {0x00, 0x19}, /* 0x51, RT_CHANNEL_DOMAIN_WORLD_ETSI10 */ 201554c0a3aSHans de Goede {0x00, 0x1A}, /* 0x52, RT_CHANNEL_DOMAIN_WORLD_ETSI11 */ 202554c0a3aSHans de Goede {0x02, 0x1B}, /* 0x53, RT_CHANNEL_DOMAIN_FCC1_NCC4 */ 203554c0a3aSHans de Goede {0x00, 0x1C}, /* 0x54, RT_CHANNEL_DOMAIN_WORLD_ETSI12 */ 204554c0a3aSHans de Goede {0x02, 0x1D}, /* 0x55, RT_CHANNEL_DOMAIN_FCC1_FCC9 */ 205554c0a3aSHans de Goede {0x00, 0x1E}, /* 0x56, RT_CHANNEL_DOMAIN_WORLD_ETSI13 */ 206554c0a3aSHans de Goede {0x02, 0x1F}, /* 0x57, RT_CHANNEL_DOMAIN_FCC1_FCC10 */ 207554c0a3aSHans de Goede }; 208554c0a3aSHans de Goede 2094d17363dSAndreas Hellmich /* use the combination for max channel numbers */ 210f0e46c47SMarco Cesati static struct rt_channel_plan_map RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {0x03, 0x02}; 211554c0a3aSHans de Goede 2124d17363dSAndreas Hellmich /* Search the @param ch in given @param ch_set 213554c0a3aSHans de Goede * @ch_set: the given channel set 214554c0a3aSHans de Goede * @ch: the given channel number 215554c0a3aSHans de Goede * 216554c0a3aSHans de Goede * return the index of channel_num in channel_set, -1 if not found 217554c0a3aSHans de Goede */ 218f0e46c47SMarco Cesati int rtw_ch_set_search_ch(struct rt_channel_info *ch_set, const u32 ch) 219554c0a3aSHans de Goede { 220554c0a3aSHans de Goede int i; 221c926f022SSimran Singhal 222554c0a3aSHans de Goede for (i = 0; ch_set[i].ChannelNum != 0; i++) { 223554c0a3aSHans de Goede if (ch == ch_set[i].ChannelNum) 224554c0a3aSHans de Goede break; 225554c0a3aSHans de Goede } 226554c0a3aSHans de Goede 227554c0a3aSHans de Goede if (i >= ch_set[i].ChannelNum) 228554c0a3aSHans de Goede return -1; 229554c0a3aSHans de Goede return i; 230554c0a3aSHans de Goede } 231554c0a3aSHans de Goede 2324d17363dSAndreas Hellmich /* Check the @param ch is fit with setband setting of @param adapter 233554c0a3aSHans de Goede * @adapter: the given adapter 234554c0a3aSHans de Goede * @ch: the given channel number 235554c0a3aSHans de Goede * 236554c0a3aSHans de Goede * return true when check valid, false not valid 237554c0a3aSHans de Goede */ 238554c0a3aSHans de Goede bool rtw_mlme_band_check(struct adapter *adapter, const u32 ch) 239554c0a3aSHans de Goede { 240554c0a3aSHans de Goede if (adapter->setband == GHZ24_50 /* 2.4G and 5G */ 241554c0a3aSHans de Goede || (adapter->setband == GHZ_24 && ch < 35) /* 2.4G only */ 242554c0a3aSHans de Goede || (adapter->setband == GHZ_50 && ch > 35) /* 5G only */ 243554c0a3aSHans de Goede ) { 244554c0a3aSHans de Goede return true; 245554c0a3aSHans de Goede } 246554c0a3aSHans de Goede return false; 247554c0a3aSHans de Goede } 248554c0a3aSHans de Goede 249554c0a3aSHans de Goede /**************************************************************************** 250554c0a3aSHans de Goede 251554c0a3aSHans de Goede Following are the initialization functions for WiFi MLME 252554c0a3aSHans de Goede 253554c0a3aSHans de Goede *****************************************************************************/ 254554c0a3aSHans de Goede 255554c0a3aSHans de Goede int init_hw_mlme_ext(struct adapter *padapter) 256554c0a3aSHans de Goede { 257554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 258554c0a3aSHans de Goede 259554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 260554c0a3aSHans de Goede return _SUCCESS; 261554c0a3aSHans de Goede } 262554c0a3aSHans de Goede 263554c0a3aSHans de Goede void init_mlme_default_rate_set(struct adapter *padapter) 264554c0a3aSHans de Goede { 265554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 266554c0a3aSHans de Goede 267554c0a3aSHans 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}; 268554c0a3aSHans de Goede unsigned char mixed_basicrate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,}; 269554c0a3aSHans de Goede unsigned char supported_mcs_set[16] = {0xff, 0xff, 0x00, 0x00, 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; 270554c0a3aSHans de Goede 271554c0a3aSHans de Goede memcpy(pmlmeext->datarate, mixed_datarate, NumRates); 272554c0a3aSHans de Goede memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates); 273554c0a3aSHans de Goede 274554c0a3aSHans de Goede memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set)); 275554c0a3aSHans de Goede } 276554c0a3aSHans de Goede 277554c0a3aSHans de Goede static void init_mlme_ext_priv_value(struct adapter *padapter) 278554c0a3aSHans de Goede { 279554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 280c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 281554c0a3aSHans de Goede 282554c0a3aSHans de Goede atomic_set(&pmlmeext->event_seq, 0); 283554c0a3aSHans de Goede pmlmeext->mgnt_seq = 0;/* reset to zero when disconnect at client mode */ 284554c0a3aSHans de Goede pmlmeext->sa_query_seq = 0; 285554c0a3aSHans de Goede pmlmeext->mgnt_80211w_IPN = 0; 286554c0a3aSHans de Goede pmlmeext->mgnt_80211w_IPN_rx = 0; 287554c0a3aSHans de Goede pmlmeext->cur_channel = padapter->registrypriv.channel; 288554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 289554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 290554c0a3aSHans de Goede 291554c0a3aSHans de Goede pmlmeext->retry = 0; 292554c0a3aSHans de Goede 293554c0a3aSHans de Goede pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode; 294554c0a3aSHans de Goede 295554c0a3aSHans de Goede init_mlme_default_rate_set(padapter); 296554c0a3aSHans de Goede 297554c0a3aSHans de Goede pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB; 298554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_DISABLE; 299554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = 0; 300554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt = 0; 301554c0a3aSHans de Goede pmlmeext->scan_abort = false; 302554c0a3aSHans de Goede 303554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 304554c0a3aSHans de Goede pmlmeinfo->reauth_count = 0; 305554c0a3aSHans de Goede pmlmeinfo->reassoc_count = 0; 306554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 307554c0a3aSHans de Goede pmlmeinfo->auth_seq = 0; 308554c0a3aSHans de Goede pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open; 309554c0a3aSHans de Goede pmlmeinfo->key_index = 0; 310554c0a3aSHans de Goede pmlmeinfo->iv = 0; 311554c0a3aSHans de Goede 312554c0a3aSHans de Goede pmlmeinfo->enc_algo = _NO_PRIVACY_; 313554c0a3aSHans de Goede pmlmeinfo->authModeToggle = 0; 314554c0a3aSHans de Goede 315554c0a3aSHans de Goede memset(pmlmeinfo->chg_txt, 0, 128); 316554c0a3aSHans de Goede 317554c0a3aSHans de Goede pmlmeinfo->slotTime = SHORT_SLOT_TIME; 318554c0a3aSHans de Goede pmlmeinfo->preamble_mode = PREAMBLE_AUTO; 319554c0a3aSHans de Goede 320554c0a3aSHans de Goede pmlmeinfo->dialogToken = 0; 321554c0a3aSHans de Goede 322554c0a3aSHans de Goede pmlmeext->action_public_rxseq = 0xffff; 323554c0a3aSHans de Goede pmlmeext->action_public_dialog_token = 0xff; 324554c0a3aSHans de Goede } 325554c0a3aSHans de Goede 326f0e46c47SMarco Cesati static int has_channel(struct rt_channel_info *channel_set, 327554c0a3aSHans de Goede u8 chanset_size, 3283520c7a4SHenriette Hofmeier u8 chan) 3293520c7a4SHenriette Hofmeier { 330554c0a3aSHans de Goede int i; 331554c0a3aSHans de Goede 332554c0a3aSHans de Goede for (i = 0; i < chanset_size; i++) { 333554c0a3aSHans de Goede if (channel_set[i].ChannelNum == chan) { 334554c0a3aSHans de Goede return 1; 335554c0a3aSHans de Goede } 336554c0a3aSHans de Goede } 337554c0a3aSHans de Goede 338554c0a3aSHans de Goede return 0; 339554c0a3aSHans de Goede } 340554c0a3aSHans de Goede 341f0e46c47SMarco Cesati static void init_channel_list(struct adapter *padapter, struct rt_channel_info *channel_set, 342554c0a3aSHans de Goede u8 chanset_size, 3433520c7a4SHenriette Hofmeier struct p2p_channels *channel_list) 3443520c7a4SHenriette Hofmeier { 345554c0a3aSHans de Goede 34653e3a7e1SColin Ian King static const struct p2p_oper_class_map op_class[] = { 347554c0a3aSHans de Goede { IEEE80211G, 81, 1, 13, 1, BW20 }, 348554c0a3aSHans de Goede { IEEE80211G, 82, 14, 14, 1, BW20 }, 349554c0a3aSHans de Goede { IEEE80211A, 115, 36, 48, 4, BW20 }, 350554c0a3aSHans de Goede { IEEE80211A, 116, 36, 44, 8, BW40PLUS }, 351554c0a3aSHans de Goede { IEEE80211A, 117, 40, 48, 8, BW40MINUS }, 352554c0a3aSHans de Goede { IEEE80211A, 124, 149, 161, 4, BW20 }, 353554c0a3aSHans de Goede { IEEE80211A, 125, 149, 169, 4, BW20 }, 354554c0a3aSHans de Goede { IEEE80211A, 126, 149, 157, 8, BW40PLUS }, 355554c0a3aSHans de Goede { IEEE80211A, 127, 153, 161, 8, BW40MINUS }, 356554c0a3aSHans de Goede { -1, 0, 0, 0, 0, BW20 } 357554c0a3aSHans de Goede }; 358554c0a3aSHans de Goede 359554c0a3aSHans de Goede int cla, op; 360554c0a3aSHans de Goede 361554c0a3aSHans de Goede cla = 0; 362554c0a3aSHans de Goede 363554c0a3aSHans de Goede for (op = 0; op_class[op].op_class; op++) { 364554c0a3aSHans de Goede u8 ch; 36553e3a7e1SColin Ian King const struct p2p_oper_class_map *o = &op_class[op]; 366554c0a3aSHans de Goede struct p2p_reg_class *reg = NULL; 367554c0a3aSHans de Goede 368554c0a3aSHans de Goede for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { 369a65f0d18SVatsala Narang if (!has_channel(channel_set, chanset_size, ch)) 370554c0a3aSHans de Goede continue; 371554c0a3aSHans de Goede 372554c0a3aSHans de Goede if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc)) 373554c0a3aSHans de Goede continue; 374554c0a3aSHans de Goede 375554c0a3aSHans de Goede if ((0 < (padapter->registrypriv.bw_mode & 0xf0)) && 376554c0a3aSHans de Goede ((BW40MINUS == o->bw) || (BW40PLUS == o->bw))) 377554c0a3aSHans de Goede continue; 378554c0a3aSHans de Goede 37941452327SVatsala Narang if (!reg) { 380554c0a3aSHans de Goede reg = &channel_list->reg_class[cla]; 381554c0a3aSHans de Goede cla++; 382554c0a3aSHans de Goede reg->reg_class = o->op_class; 383554c0a3aSHans de Goede reg->channels = 0; 384554c0a3aSHans de Goede } 385554c0a3aSHans de Goede reg->channel[reg->channels] = ch; 386554c0a3aSHans de Goede reg->channels++; 387554c0a3aSHans de Goede } 388554c0a3aSHans de Goede } 389554c0a3aSHans de Goede channel_list->reg_classes = cla; 390554c0a3aSHans de Goede 391554c0a3aSHans de Goede } 392554c0a3aSHans de Goede 393f0e46c47SMarco Cesati static u8 init_channel_set(struct adapter *padapter, u8 ChannelPlan, struct rt_channel_info *channel_set) 394554c0a3aSHans de Goede { 395554c0a3aSHans de Goede u8 index, chanset_size = 0; 396554c0a3aSHans de Goede u8 b5GBand = false, b2_4GBand = false; 397554c0a3aSHans de Goede u8 Index2G = 0, Index5G = 0; 398554c0a3aSHans de Goede 399f0e46c47SMarco Cesati memset(channel_set, 0, sizeof(struct rt_channel_info)*MAX_CHANNEL_NUM); 400554c0a3aSHans de Goede 401709c8e49SFabio Aiuto if (ChannelPlan >= RT_CHANNEL_DOMAIN_MAX && ChannelPlan != RT_CHANNEL_DOMAIN_REALTEK_DEFINE) 402554c0a3aSHans de Goede return chanset_size; 403554c0a3aSHans de Goede 404554c0a3aSHans de Goede if (IsSupported24G(padapter->registrypriv.wireless_mode)) { 405554c0a3aSHans de Goede b2_4GBand = true; 406554c0a3aSHans de Goede if (RT_CHANNEL_DOMAIN_REALTEK_DEFINE == ChannelPlan) 407554c0a3aSHans de Goede Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G; 408554c0a3aSHans de Goede else 409554c0a3aSHans de Goede Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G; 410554c0a3aSHans de Goede } 411554c0a3aSHans de Goede 412554c0a3aSHans de Goede if (b2_4GBand) { 413554c0a3aSHans de Goede for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) { 414554c0a3aSHans de Goede channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index]; 415554c0a3aSHans de Goede 416554c0a3aSHans de Goede if ((RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN == ChannelPlan) ||/* Channel 1~11 is active, and 12~14 is passive */ 417554c0a3aSHans de Goede (RT_CHANNEL_DOMAIN_GLOBAL_NULL == ChannelPlan)) { 418554c0a3aSHans de Goede if (channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11) 419554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 420554c0a3aSHans de Goede else if ((channel_set[chanset_size].ChannelNum >= 12 && channel_set[chanset_size].ChannelNum <= 14)) 421554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 422554c0a3aSHans de Goede } else if (RT_CHANNEL_DOMAIN_WORLD_WIDE_13 == ChannelPlan || 423554c0a3aSHans de Goede RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan || 424554c0a3aSHans de Goede RT_CHANNEL_DOMAIN_2G_WORLD == Index2G) { /* channel 12~13, passive scan */ 425554c0a3aSHans de Goede if (channel_set[chanset_size].ChannelNum <= 11) 426554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 427554c0a3aSHans de Goede else 428554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 429554c0a3aSHans de Goede } else 430554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 431554c0a3aSHans de Goede 432554c0a3aSHans de Goede chanset_size++; 433554c0a3aSHans de Goede } 434554c0a3aSHans de Goede } 435554c0a3aSHans de Goede 436554c0a3aSHans de Goede if (b5GBand) { 437554c0a3aSHans de Goede for (index = 0; index < RTW_ChannelPlan5G[Index5G].Len; index++) { 438554c0a3aSHans de Goede if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48 439554c0a3aSHans de Goede || RTW_ChannelPlan5G[Index5G].Channel[index] >= 149) { 440554c0a3aSHans de Goede channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index]; 441554c0a3aSHans de Goede if (RT_CHANNEL_DOMAIN_WORLD_WIDE_5G == ChannelPlan)/* passive scan for all 5G channels */ 442554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_PASSIVE; 443554c0a3aSHans de Goede else 444554c0a3aSHans de Goede channel_set[chanset_size].ScanType = SCAN_ACTIVE; 445554c0a3aSHans de Goede chanset_size++; 446554c0a3aSHans de Goede } 447554c0a3aSHans de Goede } 448554c0a3aSHans de Goede } 449554c0a3aSHans de Goede 450554c0a3aSHans de Goede return chanset_size; 451554c0a3aSHans de Goede } 452554c0a3aSHans de Goede 453067756acSHariprasad Kelam void init_mlme_ext_priv(struct adapter *padapter) 454554c0a3aSHans de Goede { 455554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 456554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 457c872ed07SVatsala Narang struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 458c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 459554c0a3aSHans de Goede 460554c0a3aSHans de Goede pmlmeext->padapter = padapter; 461554c0a3aSHans de Goede 462554c0a3aSHans de Goede /* fill_fwpriv(padapter, &(pmlmeext->fwpriv)); */ 463554c0a3aSHans de Goede 464554c0a3aSHans de Goede init_mlme_ext_priv_value(padapter); 4652646633fSAastha Gupta pmlmeinfo->accept_addba_req = pregistrypriv->accept_addba_req; 466554c0a3aSHans de Goede 467554c0a3aSHans de Goede init_mlme_ext_timer(padapter); 468554c0a3aSHans de Goede 469554c0a3aSHans de Goede init_mlme_ap_info(padapter); 470554c0a3aSHans de Goede 471554c0a3aSHans de Goede pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan, pmlmeext->channel_set); 472554c0a3aSHans de Goede init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); 473554c0a3aSHans de Goede pmlmeext->last_scan_time = 0; 474554c0a3aSHans de Goede pmlmeext->chan_scan_time = SURVEY_TO; 475554c0a3aSHans de Goede pmlmeext->mlmeext_init = true; 476554c0a3aSHans de Goede pmlmeext->active_keep_alive_check = true; 477554c0a3aSHans de Goede 478554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 479554c0a3aSHans de Goede pmlmeext->fixed_chan = 0xFF; 480554c0a3aSHans de Goede #endif 481554c0a3aSHans de Goede } 482554c0a3aSHans de Goede 483554c0a3aSHans de Goede void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext) 484554c0a3aSHans de Goede { 485554c0a3aSHans de Goede struct adapter *padapter = pmlmeext->padapter; 486554c0a3aSHans de Goede 487554c0a3aSHans de Goede if (!padapter) 488554c0a3aSHans de Goede return; 489554c0a3aSHans de Goede 4900ad02fa8SGeorgiana Chelu if (padapter->bDriverStopped) { 491554c0a3aSHans de Goede del_timer_sync(&pmlmeext->survey_timer); 492554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 493554c0a3aSHans de Goede /* del_timer_sync(&pmlmeext->ADDBA_timer); */ 494554c0a3aSHans de Goede } 495554c0a3aSHans de Goede } 496554c0a3aSHans de Goede 497554c0a3aSHans de Goede static void _mgt_dispatcher(struct adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame) 498554c0a3aSHans de Goede { 499554c0a3aSHans de Goede u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 500554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 501554c0a3aSHans de Goede 502554c0a3aSHans de Goede if (ptable->func) { 503554c0a3aSHans de Goede /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ 504554c0a3aSHans de Goede if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && 505554c0a3aSHans de Goede memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) 506554c0a3aSHans de Goede return; 507554c0a3aSHans de Goede 508554c0a3aSHans de Goede ptable->func(padapter, precv_frame); 509554c0a3aSHans de Goede } 510554c0a3aSHans de Goede } 511554c0a3aSHans de Goede 512554c0a3aSHans de Goede void mgt_dispatcher(struct adapter *padapter, union recv_frame *precv_frame) 513554c0a3aSHans de Goede { 514554c0a3aSHans de Goede int index; 515554c0a3aSHans de Goede struct mlme_handler *ptable; 516554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 517554c0a3aSHans de Goede u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 518554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 519554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe)); 520554c0a3aSHans de Goede struct dvobj_priv *psdpriv = padapter->dvobj; 521554c0a3aSHans de Goede struct debug_priv *pdbgpriv = &psdpriv->drv_dbg; 522554c0a3aSHans de Goede 5230ac666f8SFabio Aiuto if (GetFrameType(pframe) != WIFI_MGT_TYPE) 524554c0a3aSHans de Goede return; 525554c0a3aSHans de Goede 526554c0a3aSHans de Goede /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */ 527554c0a3aSHans de Goede if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) && 528554c0a3aSHans de Goede memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) { 529554c0a3aSHans de Goede return; 530554c0a3aSHans de Goede } 531554c0a3aSHans de Goede 532554c0a3aSHans de Goede ptable = mlme_sta_tbl; 533554c0a3aSHans de Goede 534554c0a3aSHans de Goede index = GetFrameSubType(pframe) >> 4; 535554c0a3aSHans de Goede 5360ac666f8SFabio Aiuto if (index >= ARRAY_SIZE(mlme_sta_tbl)) 537554c0a3aSHans de Goede return; 5380ac666f8SFabio Aiuto 539554c0a3aSHans de Goede ptable += index; 540554c0a3aSHans de Goede 54134557e23SIzabela Bakollari if (psta) { 542554c0a3aSHans de Goede if (GetRetry(pframe)) { 543554c0a3aSHans de Goede if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum) { 544554c0a3aSHans de Goede /* drop the duplicate management frame */ 545554c0a3aSHans de Goede pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++; 546554c0a3aSHans de Goede return; 547554c0a3aSHans de Goede } 548554c0a3aSHans de Goede } 549554c0a3aSHans de Goede psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num; 550554c0a3aSHans de Goede } 551554c0a3aSHans de Goede 552554c0a3aSHans de Goede switch (GetFrameSubType(pframe)) { 553554c0a3aSHans de Goede case WIFI_AUTH: 5540ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) 555554c0a3aSHans de Goede ptable->func = &OnAuth; 556554c0a3aSHans de Goede else 557554c0a3aSHans de Goede ptable->func = &OnAuthClient; 55852a1d9d4SGustavo A. R. Silva fallthrough; 559554c0a3aSHans de Goede case WIFI_ASSOCREQ: 560554c0a3aSHans de Goede case WIFI_REASSOCREQ: 561554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 562554c0a3aSHans de Goede break; 563554c0a3aSHans de Goede case WIFI_PROBEREQ: 564554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 565554c0a3aSHans de Goede break; 566554c0a3aSHans de Goede case WIFI_BEACON: 567554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 568554c0a3aSHans de Goede break; 569554c0a3aSHans de Goede case WIFI_ACTION: 570554c0a3aSHans de Goede /* if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) */ 571554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 572554c0a3aSHans de Goede break; 573554c0a3aSHans de Goede default: 574554c0a3aSHans de Goede _mgt_dispatcher(padapter, ptable, precv_frame); 575554c0a3aSHans de Goede break; 576554c0a3aSHans de Goede } 577554c0a3aSHans de Goede } 578554c0a3aSHans de Goede 579554c0a3aSHans de Goede /**************************************************************************** 580554c0a3aSHans de Goede 581554c0a3aSHans de Goede Following are the callback functions for each subtype of the management frames 582554c0a3aSHans de Goede 583554c0a3aSHans de Goede *****************************************************************************/ 584554c0a3aSHans de Goede 585554c0a3aSHans de Goede unsigned int OnProbeReq(struct adapter *padapter, union recv_frame *precv_frame) 586554c0a3aSHans de Goede { 587554c0a3aSHans de Goede unsigned int ielen; 588554c0a3aSHans de Goede unsigned char *p; 589554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 590554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 591c872ed07SVatsala Narang struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; 592c872ed07SVatsala Narang struct wlan_bssid_ex *cur = &pmlmeinfo->network; 593554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 594554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 595554c0a3aSHans de Goede u8 is_valid_p2p_probereq = false; 596554c0a3aSHans de Goede 597554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) 598554c0a3aSHans de Goede return _SUCCESS; 599554c0a3aSHans de Goede 600554c0a3aSHans de Goede if (check_fwstate(pmlmepriv, _FW_LINKED) == false && 601554c0a3aSHans de Goede check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == false) { 602554c0a3aSHans de Goede return _SUCCESS; 603554c0a3aSHans de Goede } 604554c0a3aSHans de Goede 6053f15277bSRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, WLAN_EID_SSID, (int *)&ielen, 606554c0a3aSHans de Goede len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_); 607554c0a3aSHans de Goede 608554c0a3aSHans de Goede 609554c0a3aSHans de Goede /* check (wildcard) SSID */ 61034557e23SIzabela Bakollari if (p) { 6110ad02fa8SGeorgiana Chelu if (is_valid_p2p_probereq) 612554c0a3aSHans de Goede goto _issue_probersp; 613554c0a3aSHans de Goede 614554c0a3aSHans de Goede if ((ielen != 0 && false == !memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength)) 615554c0a3aSHans de Goede || (ielen == 0 && pmlmeinfo->hidden_ssid_mode) 616554c0a3aSHans de Goede ) 617554c0a3aSHans de Goede return _SUCCESS; 618554c0a3aSHans de Goede 619554c0a3aSHans de Goede _issue_probersp: 6200ad02fa8SGeorgiana Chelu if ((check_fwstate(pmlmepriv, _FW_LINKED) && 621af6afdb6SFabio Aiuto pmlmepriv->cur_network.join_res) || 622af6afdb6SFabio Aiuto check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) 623554c0a3aSHans de Goede issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq); 624554c0a3aSHans de Goede } 625554c0a3aSHans de Goede 626554c0a3aSHans de Goede return _SUCCESS; 627554c0a3aSHans de Goede 628554c0a3aSHans de Goede } 629554c0a3aSHans de Goede 630554c0a3aSHans de Goede unsigned int OnProbeRsp(struct adapter *padapter, union recv_frame *precv_frame) 631554c0a3aSHans de Goede { 632554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 633554c0a3aSHans de Goede 634554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 635554c0a3aSHans de Goede report_survey_event(padapter, precv_frame); 636554c0a3aSHans de Goede return _SUCCESS; 637554c0a3aSHans de Goede } 638554c0a3aSHans de Goede 639554c0a3aSHans de Goede return _SUCCESS; 640554c0a3aSHans de Goede 641554c0a3aSHans de Goede } 642554c0a3aSHans de Goede 643554c0a3aSHans de Goede unsigned int OnBeacon(struct adapter *padapter, union recv_frame *precv_frame) 644554c0a3aSHans de Goede { 645554c0a3aSHans de Goede int cam_idx; 646554c0a3aSHans de Goede struct sta_info *psta; 647554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 648554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 649554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 650554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 651554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 652554c0a3aSHans de Goede uint len = precv_frame->u.hdr.len; 653554c0a3aSHans de Goede struct wlan_bssid_ex *pbss; 654554c0a3aSHans de Goede int ret = _SUCCESS; 655554c0a3aSHans de Goede u8 *p = NULL; 656554c0a3aSHans de Goede u32 ielen = 0; 657554c0a3aSHans de Goede 65800f0b682SRoss 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_); 65934557e23SIzabela Bakollari if (p && ielen > 0) { 660709c8e49SFabio Aiuto if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D)) 661554c0a3aSHans de Goede /* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */ 662554c0a3aSHans de Goede *(p + 1) = ielen - 1; 663554c0a3aSHans de Goede } 664554c0a3aSHans de Goede 665554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 666554c0a3aSHans de Goede report_survey_event(padapter, precv_frame); 667554c0a3aSHans de Goede return _SUCCESS; 668554c0a3aSHans de Goede } 669554c0a3aSHans de Goede 670554c0a3aSHans de Goede if (!memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) { 671554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { 672554c0a3aSHans de Goede /* we should update current network before auth, or some IE is wrong */ 6732ef2b7c2SJoe Perches pbss = rtw_malloc(sizeof(struct wlan_bssid_ex)); 674554c0a3aSHans de Goede if (pbss) { 675554c0a3aSHans de Goede if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) { 676554c0a3aSHans de Goede update_network(&(pmlmepriv->cur_network.network), pbss, padapter, true); 677554c0a3aSHans de Goede rtw_get_bcn_info(&(pmlmepriv->cur_network)); 678554c0a3aSHans de Goede } 6798f24f505SMadhumitha Prabakaran kfree(pbss); 680554c0a3aSHans de Goede } 681554c0a3aSHans de Goede 682554c0a3aSHans de Goede /* check the vendor of the assoc AP */ 683554c0a3aSHans de Goede pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct ieee80211_hdr_3addr), len-sizeof(struct ieee80211_hdr_3addr)); 684554c0a3aSHans de Goede 685554c0a3aSHans de Goede /* update TSF Value */ 686554c0a3aSHans de Goede update_TSF(pmlmeext, pframe, len); 687554c0a3aSHans de Goede 688554c0a3aSHans de Goede /* reset for adaptive_early_32k */ 689554c0a3aSHans de Goede pmlmeext->adaptive_tsf_done = false; 690554c0a3aSHans de Goede pmlmeext->DrvBcnEarly = 0xff; 691554c0a3aSHans de Goede pmlmeext->DrvBcnTimeOut = 0xff; 692554c0a3aSHans de Goede pmlmeext->bcn_cnt = 0; 693554c0a3aSHans de Goede memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt)); 694554c0a3aSHans de Goede memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio)); 695554c0a3aSHans de Goede 696554c0a3aSHans de Goede /* start auth */ 697554c0a3aSHans de Goede start_clnt_auth(padapter); 698554c0a3aSHans de Goede 699554c0a3aSHans de Goede return _SUCCESS; 700554c0a3aSHans de Goede } 701554c0a3aSHans de Goede 702554c0a3aSHans de Goede if (((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) { 703554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 70434557e23SIzabela Bakollari if (psta) { 705554c0a3aSHans de Goede ret = rtw_check_bcn_info(padapter, pframe, len); 706554c0a3aSHans de Goede if (!ret) { 70779df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 70879df841bSFabio Aiuto "ap has changed, disconnect now\n "); 70998dc1208SFabio Aiuto receive_disconnect(padapter, 71098dc1208SFabio Aiuto 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) { 100479df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, "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; 10225e7106f6SFabio M. De Francesco unsigned char *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); 10425e7106f6SFabio M. De Francesco if (frame_type == WIFI_ASSOCREQ) 1043554c0a3aSHans de Goede ie_offset = _ASOCREQ_IE_OFFSET_; 10445e7106f6SFabio M. De Francesco else /* WIFI_REASSOCREQ */ 1045554c0a3aSHans de Goede ie_offset = _REASOCREQ_IE_OFFSET_; 1046554c0a3aSHans de Goede 1047554c0a3aSHans de Goede 1048709c8e49SFabio Aiuto if (pkt_len < sizeof(struct ieee80211_hdr_3addr) + ie_offset) 1049554c0a3aSHans de Goede return _FAIL; 1050554c0a3aSHans de Goede 1051554c0a3aSHans de Goede pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 105241452327SVatsala Narang if (!pstat) { 10535ed3e6f2SRoss Schmidt status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; 1054554c0a3aSHans de Goede goto asoc_class2_error; 1055554c0a3aSHans de Goede } 1056554c0a3aSHans de Goede 1057d48603afSRoss Schmidt capab_info = get_unaligned_le16(pframe + WLAN_HDR_A3_LEN); 1058554c0a3aSHans de Goede /* capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN)); */ 1059554c0a3aSHans de Goede 10607d0b4f3cSQuytelda Kahja left = pkt_len - (sizeof(struct ieee80211_hdr_3addr) + ie_offset); 10617d0b4f3cSQuytelda Kahja pos = pframe + (sizeof(struct ieee80211_hdr_3addr) + ie_offset); 1062554c0a3aSHans de Goede 1063554c0a3aSHans de Goede /* check if this stat has been successfully authenticated/assocated */ 1064554c0a3aSHans de Goede if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS)) { 1065554c0a3aSHans de Goede if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS)) { 10665ed3e6f2SRoss Schmidt status = WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA; 1067554c0a3aSHans de Goede goto asoc_class2_error; 1068554c0a3aSHans de Goede } else { 1069554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_ASSOC_SUCCESS); 1070554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_STATE; 1071554c0a3aSHans de Goede } 1072554c0a3aSHans de Goede } else { 1073554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_AUTH_SUCCESS); 1074554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_STATE; 1075554c0a3aSHans de Goede } 1076554c0a3aSHans de Goede 1077554c0a3aSHans de Goede 1078554c0a3aSHans de Goede pstat->capability = capab_info; 1079554c0a3aSHans de Goede 1080554c0a3aSHans de Goede /* now parse all ieee802_11 ie to point to elems */ 1081554c0a3aSHans de Goede if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed || 1082554c0a3aSHans de Goede !elems.ssid) { 10836d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1084554c0a3aSHans de Goede goto OnAssocReqFail; 1085554c0a3aSHans de Goede } 1086554c0a3aSHans de Goede 1087554c0a3aSHans de Goede /* now we should check all the fields... */ 1088554c0a3aSHans de Goede /* checking SSID */ 10893f15277bSRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_SSID, &ie_len, 1090554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - ie_offset); 1091554c0a3aSHans de Goede 10926493a78fSAymen Qader if (!p || ie_len == 0) { 10936493a78fSAymen Qader /* broadcast ssid, however it is not allowed in assocreq */ 10946d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 10956493a78fSAymen Qader goto OnAssocReqFail; 10966493a78fSAymen Qader } else { 1097554c0a3aSHans de Goede /* check if ssid match */ 1098554c0a3aSHans de Goede if (memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength)) 10996d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1100554c0a3aSHans de Goede 1101554c0a3aSHans de Goede if (ie_len != cur->Ssid.SsidLength) 11026d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1103554c0a3aSHans de Goede } 1104554c0a3aSHans de Goede 11056d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 1106554c0a3aSHans de Goede goto OnAssocReqFail; 1107554c0a3aSHans de Goede 1108554c0a3aSHans de Goede /* check if the supported rate is ok */ 1109c34c45edSRoss 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); 1110554c0a3aSHans de Goede if (p == NULL) { 1111554c0a3aSHans de Goede /* use our own rate set as statoin used */ 1112554c0a3aSHans de Goede /* memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN); */ 1113554c0a3aSHans de Goede /* supportRateNum = AP_BSSRATE_LEN; */ 1114554c0a3aSHans de Goede 11156d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1116554c0a3aSHans de Goede goto OnAssocReqFail; 1117554c0a3aSHans de Goede } else { 1118554c0a3aSHans de Goede memcpy(supportRate, p+2, ie_len); 1119554c0a3aSHans de Goede supportRateNum = ie_len; 1120554c0a3aSHans de Goede 112100f0b682SRoss Schmidt p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, WLAN_EID_EXT_SUPP_RATES, &ie_len, 1122554c0a3aSHans de Goede pkt_len - WLAN_HDR_A3_LEN - ie_offset); 1123554c0a3aSHans de Goede if (p != NULL) { 1124554c0a3aSHans de Goede 1125554c0a3aSHans de Goede if (supportRateNum <= sizeof(supportRate)) { 1126554c0a3aSHans de Goede memcpy(supportRate+supportRateNum, p+2, ie_len); 1127554c0a3aSHans de Goede supportRateNum += ie_len; 1128554c0a3aSHans de Goede } 1129554c0a3aSHans de Goede } 1130554c0a3aSHans de Goede } 1131554c0a3aSHans de Goede 1132554c0a3aSHans de Goede /* todo: mask supportRate between AP & STA -> move to update raid */ 1133554c0a3aSHans de Goede /* get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0); */ 1134554c0a3aSHans de Goede 1135554c0a3aSHans de Goede /* update station supportRate */ 1136554c0a3aSHans de Goede pstat->bssratelen = supportRateNum; 1137554c0a3aSHans de Goede memcpy(pstat->bssrateset, supportRate, supportRateNum); 1138554c0a3aSHans de Goede UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen); 1139554c0a3aSHans de Goede 1140554c0a3aSHans de Goede /* check RSN/WPA/WPS */ 1141554c0a3aSHans de Goede pstat->dot8021xalg = 0; 1142554c0a3aSHans de Goede pstat->wpa_psk = 0; 1143554c0a3aSHans de Goede pstat->wpa_group_cipher = 0; 1144554c0a3aSHans de Goede pstat->wpa2_group_cipher = 0; 1145554c0a3aSHans de Goede pstat->wpa_pairwise_cipher = 0; 1146554c0a3aSHans de Goede pstat->wpa2_pairwise_cipher = 0; 1147554c0a3aSHans de Goede memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie)); 1148554c0a3aSHans de Goede if ((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) { 1149554c0a3aSHans de Goede 1150554c0a3aSHans de Goede int group_cipher = 0, pairwise_cipher = 0; 1151554c0a3aSHans de Goede 1152554c0a3aSHans de Goede wpa_ie = elems.rsn_ie; 1153554c0a3aSHans de Goede wpa_ie_len = elems.rsn_ie_len; 1154554c0a3aSHans de Goede 1155554c0a3aSHans de Goede if (rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { 1156554c0a3aSHans de Goede pstat->dot8021xalg = 1;/* psk, todo:802.1x */ 1157554c0a3aSHans de Goede pstat->wpa_psk |= BIT(1); 1158554c0a3aSHans de Goede 1159554c0a3aSHans de Goede pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher; 1160554c0a3aSHans de Goede pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher; 1161554c0a3aSHans de Goede 1162554c0a3aSHans de Goede if (!pstat->wpa2_group_cipher) 11636d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_GROUP_CIPHER; 1164554c0a3aSHans de Goede 1165554c0a3aSHans de Goede if (!pstat->wpa2_pairwise_cipher) 11666d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; 1167554c0a3aSHans de Goede } else { 1168554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1169554c0a3aSHans de Goede } 1170554c0a3aSHans de Goede 1171554c0a3aSHans de Goede } else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) { 1172554c0a3aSHans de Goede 1173554c0a3aSHans de Goede int group_cipher = 0, pairwise_cipher = 0; 1174554c0a3aSHans de Goede 1175554c0a3aSHans de Goede wpa_ie = elems.wpa_ie; 1176554c0a3aSHans de Goede wpa_ie_len = elems.wpa_ie_len; 1177554c0a3aSHans de Goede 1178554c0a3aSHans de Goede if (rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS) { 1179554c0a3aSHans de Goede pstat->dot8021xalg = 1;/* psk, todo:802.1x */ 1180554c0a3aSHans de Goede pstat->wpa_psk |= BIT(0); 1181554c0a3aSHans de Goede 1182554c0a3aSHans de Goede pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher; 1183554c0a3aSHans de Goede pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher; 1184554c0a3aSHans de Goede 1185554c0a3aSHans de Goede if (!pstat->wpa_group_cipher) 11866d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_GROUP_CIPHER; 1187554c0a3aSHans de Goede 1188554c0a3aSHans de Goede if (!pstat->wpa_pairwise_cipher) 11896d75b504SRoss Schmidt status = WLAN_STATUS_INVALID_PAIRWISE_CIPHER; 1190554c0a3aSHans de Goede 1191554c0a3aSHans de Goede } else { 1192554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1193554c0a3aSHans de Goede } 1194554c0a3aSHans de Goede 1195554c0a3aSHans de Goede } else { 1196554c0a3aSHans de Goede wpa_ie = NULL; 1197554c0a3aSHans de Goede wpa_ie_len = 0; 1198554c0a3aSHans de Goede } 1199554c0a3aSHans de Goede 12006d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 1201554c0a3aSHans de Goede goto OnAssocReqFail; 1202554c0a3aSHans de Goede 1203554c0a3aSHans de Goede pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); 120441452327SVatsala Narang if (!wpa_ie) { 1205554c0a3aSHans de Goede if (elems.wps_ie) { 1206554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WPS; 1207554c0a3aSHans de Goede /* wpabuf_free(sta->wps_ie); */ 1208554c0a3aSHans de Goede /* sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, */ 1209554c0a3aSHans de Goede /* elems.wps_ie_len - 4); */ 1210554c0a3aSHans de Goede } else { 1211554c0a3aSHans de Goede pstat->flags |= WLAN_STA_MAYBE_WPS; 1212554c0a3aSHans de Goede } 1213554c0a3aSHans de Goede 1214554c0a3aSHans de Goede 1215554c0a3aSHans de Goede /* AP support WPA/RSN, and sta is going to do WPS, but AP is not ready */ 1216554c0a3aSHans de Goede /* that the selected registrar of AP is _FLASE */ 1217554c0a3aSHans de Goede if ((psecuritypriv->wpa_psk > 0) 1218554c0a3aSHans de Goede && (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS))) { 1219554c0a3aSHans de Goede if (pmlmepriv->wps_beacon_ie) { 1220554c0a3aSHans de Goede u8 selected_registrar = 0; 1221554c0a3aSHans de Goede 1222554c0a3aSHans de Goede rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL); 1223554c0a3aSHans de Goede 1224554c0a3aSHans de Goede if (!selected_registrar) { 12256d75b504SRoss Schmidt status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 1226554c0a3aSHans de Goede 1227554c0a3aSHans de Goede goto OnAssocReqFail; 1228554c0a3aSHans de Goede } 1229554c0a3aSHans de Goede } 1230554c0a3aSHans de Goede } 1231554c0a3aSHans de Goede 1232554c0a3aSHans de Goede } else { 1233554c0a3aSHans de Goede int copy_len; 1234554c0a3aSHans de Goede 1235554c0a3aSHans de Goede if (psecuritypriv->wpa_psk == 0) { 1236554c0a3aSHans de Goede status = WLAN_STATUS_INVALID_IE; 1237554c0a3aSHans de Goede 1238554c0a3aSHans de Goede goto OnAssocReqFail; 1239554c0a3aSHans de Goede 1240554c0a3aSHans de Goede } 1241554c0a3aSHans de Goede 1242554c0a3aSHans de Goede if (elems.wps_ie) { 1243554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WPS; 1244554c0a3aSHans de Goede copy_len = 0; 1245554c0a3aSHans de Goede } else { 1246554c0a3aSHans de Goede copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2); 1247554c0a3aSHans de Goede } 1248554c0a3aSHans de Goede 1249554c0a3aSHans de Goede 1250554c0a3aSHans de Goede if (copy_len > 0) 1251554c0a3aSHans de Goede memcpy(pstat->wpa_ie, wpa_ie-2, copy_len); 1252554c0a3aSHans de Goede 1253554c0a3aSHans de Goede } 1254554c0a3aSHans de Goede 1255554c0a3aSHans de Goede 1256554c0a3aSHans de Goede /* check if there is WMM IE & support WWM-PS */ 1257554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_WME; 1258554c0a3aSHans de Goede pstat->qos_option = 0; 1259554c0a3aSHans de Goede pstat->qos_info = 0; 1260554c0a3aSHans de Goede pstat->has_legacy_ac = true; 1261554c0a3aSHans de Goede pstat->uapsd_vo = 0; 1262554c0a3aSHans de Goede pstat->uapsd_vi = 0; 1263554c0a3aSHans de Goede pstat->uapsd_be = 0; 1264554c0a3aSHans de Goede pstat->uapsd_bk = 0; 1265554c0a3aSHans de Goede if (pmlmepriv->qospriv.qos_option) { 1266554c0a3aSHans de Goede p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0; 1267554c0a3aSHans de Goede for (;;) { 1268b05cc3a9SRoss Schmidt p = rtw_get_ie(p, WLAN_EID_VENDOR_SPECIFIC, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset); 126934557e23SIzabela Bakollari if (p) { 1270554c0a3aSHans de Goede if (!memcmp(p+2, WMM_IE, 6)) { 1271554c0a3aSHans de Goede 1272554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WME; 1273554c0a3aSHans de Goede 1274554c0a3aSHans de Goede pstat->qos_option = 1; 1275554c0a3aSHans de Goede pstat->qos_info = *(p+8); 1276554c0a3aSHans de Goede 1277554c0a3aSHans de Goede pstat->max_sp_len = (pstat->qos_info>>5)&0x3; 1278554c0a3aSHans de Goede 1279554c0a3aSHans de Goede if ((pstat->qos_info&0xf) != 0xf) 1280554c0a3aSHans de Goede pstat->has_legacy_ac = true; 1281554c0a3aSHans de Goede else 1282554c0a3aSHans de Goede pstat->has_legacy_ac = false; 1283554c0a3aSHans de Goede 1284554c0a3aSHans de Goede if (pstat->qos_info&0xf) { 1285554c0a3aSHans de Goede if (pstat->qos_info&BIT(0)) 1286554c0a3aSHans de Goede pstat->uapsd_vo = BIT(0)|BIT(1); 1287554c0a3aSHans de Goede else 1288554c0a3aSHans de Goede pstat->uapsd_vo = 0; 1289554c0a3aSHans de Goede 1290554c0a3aSHans de Goede if (pstat->qos_info&BIT(1)) 1291554c0a3aSHans de Goede pstat->uapsd_vi = BIT(0)|BIT(1); 1292554c0a3aSHans de Goede else 1293554c0a3aSHans de Goede pstat->uapsd_vi = 0; 1294554c0a3aSHans de Goede 1295554c0a3aSHans de Goede if (pstat->qos_info&BIT(2)) 1296554c0a3aSHans de Goede pstat->uapsd_bk = BIT(0)|BIT(1); 1297554c0a3aSHans de Goede else 1298554c0a3aSHans de Goede pstat->uapsd_bk = 0; 1299554c0a3aSHans de Goede 1300554c0a3aSHans de Goede if (pstat->qos_info&BIT(3)) 1301554c0a3aSHans de Goede pstat->uapsd_be = BIT(0)|BIT(1); 1302554c0a3aSHans de Goede else 1303554c0a3aSHans de Goede pstat->uapsd_be = 0; 1304554c0a3aSHans de Goede 1305554c0a3aSHans de Goede } 1306554c0a3aSHans de Goede 1307554c0a3aSHans de Goede break; 1308554c0a3aSHans de Goede } 1309554c0a3aSHans de Goede } else { 1310554c0a3aSHans de Goede break; 1311554c0a3aSHans de Goede } 1312554c0a3aSHans de Goede p = p + ie_len + 2; 1313554c0a3aSHans de Goede } 1314554c0a3aSHans de Goede } 1315554c0a3aSHans de Goede 1316554c0a3aSHans de Goede /* save HT capabilities in the sta object */ 1317c25d8a7dSRoss Schmidt memset(&pstat->htpriv.ht_cap, 0, sizeof(struct ieee80211_ht_cap)); 1318c25d8a7dSRoss Schmidt if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct ieee80211_ht_cap)) { 1319554c0a3aSHans de Goede pstat->flags |= WLAN_STA_HT; 1320554c0a3aSHans de Goede 1321554c0a3aSHans de Goede pstat->flags |= WLAN_STA_WME; 1322554c0a3aSHans de Goede 1323c25d8a7dSRoss Schmidt memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct ieee80211_ht_cap)); 1324554c0a3aSHans de Goede 1325554c0a3aSHans de Goede } else 1326554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_HT; 1327554c0a3aSHans de Goede 1328554c0a3aSHans de Goede 1329554c0a3aSHans de Goede if ((pmlmepriv->htpriv.ht_option == false) && (pstat->flags&WLAN_STA_HT)) { 13306d75b504SRoss Schmidt status = WLAN_STATUS_CHALLENGE_FAIL; 1331554c0a3aSHans de Goede goto OnAssocReqFail; 1332554c0a3aSHans de Goede } 1333554c0a3aSHans de Goede 1334554c0a3aSHans de Goede 1335554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_HT) && 1336554c0a3aSHans de Goede ((pstat->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) || 1337554c0a3aSHans de Goede (pstat->wpa_pairwise_cipher&WPA_CIPHER_TKIP))) { 13386d75b504SRoss Schmidt /* status = WLAN_STATUS_CIPHER_SUITE_REJECTED; */ 1339554c0a3aSHans de Goede /* goto OnAssocReqFail; */ 1340554c0a3aSHans de Goede } 1341554c0a3aSHans de Goede pstat->flags |= WLAN_STA_NONERP; 1342554c0a3aSHans de Goede for (i = 0; i < pstat->bssratelen; i++) { 1343554c0a3aSHans de Goede if ((pstat->bssrateset[i] & 0x7f) > 22) { 1344554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_NONERP; 1345554c0a3aSHans de Goede break; 1346554c0a3aSHans de Goede } 1347554c0a3aSHans de Goede } 1348554c0a3aSHans de Goede 1349554c0a3aSHans de Goede if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) 1350554c0a3aSHans de Goede pstat->flags |= WLAN_STA_SHORT_PREAMBLE; 1351554c0a3aSHans de Goede else 1352554c0a3aSHans de Goede pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE; 1353554c0a3aSHans de Goede 1354554c0a3aSHans de Goede 1355554c0a3aSHans de Goede 13566d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 1357554c0a3aSHans de Goede goto OnAssocReqFail; 1358554c0a3aSHans de Goede 1359554c0a3aSHans de Goede /* TODO: identify_proprietary_vendor_ie(); */ 1360554c0a3aSHans de Goede /* Realtek proprietary IE */ 1361554c0a3aSHans de Goede /* identify if this is Broadcom sta */ 1362554c0a3aSHans de Goede /* identify if this is ralink sta */ 1363554c0a3aSHans de Goede /* Customer proprietary IE */ 1364554c0a3aSHans de Goede 1365554c0a3aSHans de Goede 1366554c0a3aSHans de Goede 1367554c0a3aSHans de Goede /* get a unique AID */ 136821e161c3SFabio Aiuto if (pstat->aid == 0) { 136987e4a540SYoung Xiao for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) 1370554c0a3aSHans de Goede if (pstapriv->sta_aid[pstat->aid - 1] == NULL) 1371554c0a3aSHans de Goede break; 1372554c0a3aSHans de Goede 1373554c0a3aSHans de Goede /* if (pstat->aid > NUM_STA) { */ 1374554c0a3aSHans de Goede if (pstat->aid > pstapriv->max_num_sta) { 1375554c0a3aSHans de Goede 1376554c0a3aSHans de Goede pstat->aid = 0; 1377554c0a3aSHans de Goede 1378554c0a3aSHans de Goede status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; 1379554c0a3aSHans de Goede 1380554c0a3aSHans de Goede goto OnAssocReqFail; 1381554c0a3aSHans de Goede 1382554c0a3aSHans de Goede 1383554c0a3aSHans de Goede } else { 1384554c0a3aSHans de Goede pstapriv->sta_aid[pstat->aid - 1] = pstat; 1385554c0a3aSHans de Goede } 1386554c0a3aSHans de Goede } 1387554c0a3aSHans de Goede 1388554c0a3aSHans de Goede 1389554c0a3aSHans de Goede pstat->state &= (~WIFI_FW_ASSOC_STATE); 1390554c0a3aSHans de Goede pstat->state |= WIFI_FW_ASSOC_SUCCESS; 1391554c0a3aSHans de Goede 1392554c0a3aSHans de Goede spin_lock_bh(&pstapriv->auth_list_lock); 1393554c0a3aSHans de Goede if (!list_empty(&pstat->auth_list)) { 1394554c0a3aSHans de Goede list_del_init(&pstat->auth_list); 1395554c0a3aSHans de Goede pstapriv->auth_list_cnt--; 1396554c0a3aSHans de Goede } 1397554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->auth_list_lock); 1398554c0a3aSHans de Goede 1399554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1400554c0a3aSHans de Goede if (list_empty(&pstat->asoc_list)) { 1401554c0a3aSHans de Goede pstat->expire_to = pstapriv->expire_to; 1402554c0a3aSHans de Goede list_add_tail(&pstat->asoc_list, &pstapriv->asoc_list); 1403554c0a3aSHans de Goede pstapriv->asoc_list_cnt++; 1404554c0a3aSHans de Goede } 1405554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1406554c0a3aSHans de Goede 1407554c0a3aSHans de Goede /* now the station is qualified to join our BSS... */ 14086d75b504SRoss Schmidt if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (WLAN_STATUS_SUCCESS == status)) { 1409554c0a3aSHans de Goede /* 1 bss_cap_update & sta_info_update */ 1410554c0a3aSHans de Goede bss_cap_update_on_sta_join(padapter, pstat); 1411554c0a3aSHans de Goede sta_info_update(padapter, pstat); 1412554c0a3aSHans de Goede 1413554c0a3aSHans de Goede /* 2 issue assoc rsp before notify station join event. */ 1414554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) 1415554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); 1416554c0a3aSHans de Goede else 1417554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); 1418554c0a3aSHans de Goede 1419554c0a3aSHans de Goede spin_lock_bh(&pstat->lock); 1420554c0a3aSHans de Goede if (pstat->passoc_req) { 1421554c0a3aSHans de Goede kfree(pstat->passoc_req); 1422554c0a3aSHans de Goede pstat->passoc_req = NULL; 1423554c0a3aSHans de Goede pstat->assoc_req_len = 0; 1424554c0a3aSHans de Goede } 1425554c0a3aSHans de Goede 1426554c0a3aSHans de Goede pstat->passoc_req = rtw_zmalloc(pkt_len); 1427554c0a3aSHans de Goede if (pstat->passoc_req) { 1428554c0a3aSHans de Goede memcpy(pstat->passoc_req, pframe, pkt_len); 1429554c0a3aSHans de Goede pstat->assoc_req_len = pkt_len; 1430554c0a3aSHans de Goede } 1431554c0a3aSHans de Goede spin_unlock_bh(&pstat->lock); 1432554c0a3aSHans de Goede 1433554c0a3aSHans de Goede /* 3-(1) report sta add event */ 1434554c0a3aSHans de Goede report_add_sta_event(padapter, pstat->hwaddr, pstat->aid); 1435554c0a3aSHans de Goede } 1436554c0a3aSHans de Goede 1437554c0a3aSHans de Goede return _SUCCESS; 1438554c0a3aSHans de Goede 1439554c0a3aSHans de Goede asoc_class2_error: 1440554c0a3aSHans de Goede 1441554c0a3aSHans de Goede issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status); 1442554c0a3aSHans de Goede 1443554c0a3aSHans de Goede return _FAIL; 1444554c0a3aSHans de Goede 1445554c0a3aSHans de Goede OnAssocReqFail: 1446554c0a3aSHans de Goede 1447554c0a3aSHans de Goede pstat->aid = 0; 1448554c0a3aSHans de Goede if (frame_type == WIFI_ASSOCREQ) 1449554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP); 1450554c0a3aSHans de Goede else 1451554c0a3aSHans de Goede issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP); 1452554c0a3aSHans de Goede 1453554c0a3aSHans de Goede return _FAIL; 1454554c0a3aSHans de Goede } 1455554c0a3aSHans de Goede 1456554c0a3aSHans de Goede unsigned int OnAssocRsp(struct adapter *padapter, union recv_frame *precv_frame) 1457554c0a3aSHans de Goede { 1458554c0a3aSHans de Goede uint i; 1459554c0a3aSHans de Goede int res; 1460554c0a3aSHans de Goede unsigned short status; 1461554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 1462554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1463554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1464554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1465554c0a3aSHans de Goede /* struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); */ 1466554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1467554c0a3aSHans de Goede uint pkt_len = precv_frame->u.hdr.len; 1468554c0a3aSHans de Goede 1469554c0a3aSHans de Goede /* check A1 matches or not */ 1470554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), get_da(pframe), ETH_ALEN)) 1471554c0a3aSHans de Goede return _SUCCESS; 1472554c0a3aSHans de Goede 1473554c0a3aSHans de Goede if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE))) 1474554c0a3aSHans de Goede return _SUCCESS; 1475554c0a3aSHans de Goede 1476554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) 1477554c0a3aSHans de Goede return _SUCCESS; 1478554c0a3aSHans de Goede 1479554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 1480554c0a3aSHans de Goede 1481554c0a3aSHans de Goede /* status */ 1482554c0a3aSHans de Goede status = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 2)); 1483554c0a3aSHans de Goede if (status > 0) { 1484554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 1485554c0a3aSHans de Goede res = -4; 1486554c0a3aSHans de Goede goto report_assoc_result; 1487554c0a3aSHans de Goede } 1488554c0a3aSHans de Goede 1489554c0a3aSHans de Goede /* get capabilities */ 1490554c0a3aSHans de Goede pmlmeinfo->capability = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1491554c0a3aSHans de Goede 1492554c0a3aSHans de Goede /* set slot time */ 1493554c0a3aSHans de Goede pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10)) ? 9 : 20; 1494554c0a3aSHans de Goede 1495554c0a3aSHans de Goede /* AID */ 1496554c0a3aSHans de Goede res = pmlmeinfo->aid = (int)(le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff); 1497554c0a3aSHans de Goede 1498554c0a3aSHans de Goede /* following are moved to join event callback function */ 1499554c0a3aSHans de Goede /* to handle HT, WMM, rate adaptive, update MAC reg */ 1500554c0a3aSHans de Goede /* for not to handle the synchronous IO in the tasklet */ 1501554c0a3aSHans de Goede for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;) { 1502554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pframe + i); 1503554c0a3aSHans de Goede 1504554c0a3aSHans de Goede switch (pIE->ElementID) { 1505b05cc3a9SRoss Schmidt case WLAN_EID_VENDOR_SPECIFIC: 1506554c0a3aSHans de Goede if (!memcmp(pIE->data, WMM_PARA_OUI, 6)) /* WMM */ 1507554c0a3aSHans de Goede WMM_param_handler(padapter, pIE); 1508554c0a3aSHans de Goede break; 1509554c0a3aSHans de Goede 1510fc6a6528SRoss Schmidt case WLAN_EID_HT_CAPABILITY: /* HT caps */ 1511554c0a3aSHans de Goede HT_caps_handler(padapter, pIE); 1512554c0a3aSHans de Goede break; 1513554c0a3aSHans de Goede 1514332ec9dbSRoss Schmidt case WLAN_EID_HT_OPERATION: /* HT info */ 1515554c0a3aSHans de Goede HT_info_handler(padapter, pIE); 1516554c0a3aSHans de Goede break; 1517554c0a3aSHans de Goede 15187bd332ecSRoss Schmidt case WLAN_EID_ERP_INFO: 1519554c0a3aSHans de Goede ERP_IE_handler(padapter, pIE); 15202811861bSGustavo A. R. Silva break; 1521554c0a3aSHans de Goede 1522554c0a3aSHans de Goede default: 1523554c0a3aSHans de Goede break; 1524554c0a3aSHans de Goede } 1525554c0a3aSHans de Goede 1526554c0a3aSHans de Goede i += (pIE->Length + 2); 1527554c0a3aSHans de Goede } 1528554c0a3aSHans de Goede 1529554c0a3aSHans de Goede pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE); 1530554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 1531554c0a3aSHans de Goede 1532554c0a3aSHans de Goede /* Update Basic Rate Table for spec, 2010-12-28 , by thomas */ 1533554c0a3aSHans de Goede UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates); 1534554c0a3aSHans de Goede 1535554c0a3aSHans de Goede report_assoc_result: 1536554c0a3aSHans de Goede if (res > 0) { 1537554c0a3aSHans de Goede rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len); 1538554c0a3aSHans de Goede } else { 1539554c0a3aSHans de Goede rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len); 1540554c0a3aSHans de Goede } 1541554c0a3aSHans de Goede 1542554c0a3aSHans de Goede report_join_res(padapter, res); 1543554c0a3aSHans de Goede 1544554c0a3aSHans de Goede return _SUCCESS; 1545554c0a3aSHans de Goede } 1546554c0a3aSHans de Goede 1547554c0a3aSHans de Goede unsigned int OnDeAuth(struct adapter *padapter, union recv_frame *precv_frame) 1548554c0a3aSHans de Goede { 1549554c0a3aSHans de Goede unsigned short reason; 1550554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 1551554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1552554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1553554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1554554c0a3aSHans de Goede 1555554c0a3aSHans de Goede /* check A3 */ 1556554c0a3aSHans de Goede if (memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)) 1557554c0a3aSHans de Goede return _SUCCESS; 1558554c0a3aSHans de Goede 1559554c0a3aSHans de Goede reason = le16_to_cpu(*(__le16 *)(pframe + WLAN_HDR_A3_LEN)); 1560554c0a3aSHans de Goede 15610ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { 1562554c0a3aSHans de Goede struct sta_info *psta; 1563554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1564554c0a3aSHans de Goede 1565554c0a3aSHans de Goede /* spin_lock_bh(&(pstapriv->sta_hash_lock)); */ 1566554c0a3aSHans de Goede /* rtw_free_stainfo(padapter, psta); */ 1567554c0a3aSHans de Goede /* spin_unlock_bh(&(pstapriv->sta_hash_lock)); */ 1568554c0a3aSHans de Goede 156979df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 157079df841bSFabio Aiuto "ap recv deauth reason code(%d) sta:%pM\n", reason, 157179df841bSFabio Aiuto GetAddr2Ptr(pframe)); 1572554c0a3aSHans de Goede 1573554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1574554c0a3aSHans de Goede if (psta) { 1575554c0a3aSHans de Goede u8 updated = false; 1576554c0a3aSHans de Goede 1577554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1578554c0a3aSHans de Goede if (list_empty(&psta->asoc_list) == false) { 1579554c0a3aSHans de Goede list_del_init(&psta->asoc_list); 1580554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 1581554c0a3aSHans de Goede updated = ap_free_sta(padapter, psta, false, reason); 1582554c0a3aSHans de Goede 1583554c0a3aSHans de Goede } 1584554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1585554c0a3aSHans de Goede 1586554c0a3aSHans de Goede associated_clients_update(padapter, updated); 1587554c0a3aSHans de Goede } 1588554c0a3aSHans de Goede 1589554c0a3aSHans de Goede 1590554c0a3aSHans de Goede return _SUCCESS; 1591554c0a3aSHans de Goede } else { 1592554c0a3aSHans de Goede int ignore_received_deauth = 0; 1593554c0a3aSHans de Goede 1594554c0a3aSHans de Goede /* Commented by Albert 20130604 */ 1595554c0a3aSHans de Goede /* Before sending the auth frame to start the STA/GC mode connection with AP/GO, */ 1596554c0a3aSHans de Goede /* we will send the deauth first. */ 1597554c0a3aSHans de Goede /* However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth. */ 1598554c0a3aSHans de Goede /* Added the following code to avoid this case. */ 1599554c0a3aSHans de Goede if ((pmlmeinfo->state & WIFI_FW_AUTH_STATE) || 1600554c0a3aSHans de Goede (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)) { 1601554c0a3aSHans de Goede if (reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA) { 1602554c0a3aSHans de Goede ignore_received_deauth = 1; 1603554c0a3aSHans de Goede } else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) { 1604554c0a3aSHans de Goede /* TODO: 802.11r */ 1605554c0a3aSHans de Goede ignore_received_deauth = 1; 1606554c0a3aSHans de Goede } 1607554c0a3aSHans de Goede } 1608554c0a3aSHans de Goede 160979df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 161079df841bSFabio Aiuto "sta recv deauth reason code(%d) sta:%pM, ignore = %d\n", 161179df841bSFabio Aiuto reason, GetAddr3Ptr(pframe), 161279df841bSFabio Aiuto 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 164579df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 164679df841bSFabio Aiuto "ap recv disassoc reason code(%d) sta:%pM\n", 1647554c0a3aSHans de Goede reason, GetAddr2Ptr(pframe)); 1648554c0a3aSHans de Goede 1649554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1650554c0a3aSHans de Goede if (psta) { 1651554c0a3aSHans de Goede u8 updated = false; 1652554c0a3aSHans de Goede 1653554c0a3aSHans de Goede spin_lock_bh(&pstapriv->asoc_list_lock); 1654554c0a3aSHans de Goede if (list_empty(&psta->asoc_list) == false) { 1655554c0a3aSHans de Goede list_del_init(&psta->asoc_list); 1656554c0a3aSHans de Goede pstapriv->asoc_list_cnt--; 1657554c0a3aSHans de Goede updated = ap_free_sta(padapter, psta, false, reason); 1658554c0a3aSHans de Goede 1659554c0a3aSHans de Goede } 1660554c0a3aSHans de Goede spin_unlock_bh(&pstapriv->asoc_list_lock); 1661554c0a3aSHans de Goede 1662554c0a3aSHans de Goede associated_clients_update(padapter, updated); 1663554c0a3aSHans de Goede } 1664554c0a3aSHans de Goede 1665554c0a3aSHans de Goede return _SUCCESS; 1666554c0a3aSHans de Goede } else { 166779df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 166879df841bSFabio Aiuto "sta recv disassoc reason code(%d) sta:%pM\n", 1669554c0a3aSHans de Goede reason, GetAddr3Ptr(pframe)); 1670554c0a3aSHans de Goede 1671554c0a3aSHans de Goede receive_disconnect(padapter, GetAddr3Ptr(pframe), reason); 1672554c0a3aSHans de Goede } 1673554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.bBusyTraffic = false; 1674554c0a3aSHans de Goede return _SUCCESS; 1675554c0a3aSHans de Goede 1676554c0a3aSHans de Goede } 1677554c0a3aSHans de Goede 1678554c0a3aSHans de Goede unsigned int OnAtim(struct adapter *padapter, union recv_frame *precv_frame) 1679554c0a3aSHans de Goede { 1680554c0a3aSHans de Goede return _SUCCESS; 1681554c0a3aSHans de Goede } 1682554c0a3aSHans de Goede 1683554c0a3aSHans de Goede unsigned int on_action_spct(struct adapter *padapter, union recv_frame *precv_frame) 1684554c0a3aSHans de Goede { 1685554c0a3aSHans de Goede struct sta_info *psta = NULL; 1686554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1687554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1688554c0a3aSHans de Goede u8 *frame_body = (u8 *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1689554c0a3aSHans de Goede u8 category; 1690554c0a3aSHans de Goede u8 action; 1691554c0a3aSHans de Goede 1692554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe)); 1693554c0a3aSHans de Goede 1694554c0a3aSHans de Goede if (!psta) 1695554c0a3aSHans de Goede goto exit; 1696554c0a3aSHans de Goede 1697554c0a3aSHans de Goede category = frame_body[0]; 1698554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT) 1699554c0a3aSHans de Goede goto exit; 1700554c0a3aSHans de Goede 1701554c0a3aSHans de Goede action = frame_body[1]; 1702554c0a3aSHans de Goede switch (action) { 170372cac683SRoss Schmidt case WLAN_ACTION_SPCT_MSR_REQ: 170472cac683SRoss Schmidt case WLAN_ACTION_SPCT_MSR_RPRT: 170572cac683SRoss Schmidt case WLAN_ACTION_SPCT_TPC_REQ: 170672cac683SRoss Schmidt case WLAN_ACTION_SPCT_TPC_RPRT: 170772cac683SRoss Schmidt case WLAN_ACTION_SPCT_CHL_SWITCH: 1708554c0a3aSHans de Goede break; 1709554c0a3aSHans de Goede default: 1710554c0a3aSHans de Goede break; 1711554c0a3aSHans de Goede } 1712554c0a3aSHans de Goede 1713554c0a3aSHans de Goede exit: 17141c4bfacfSHariprasad Kelam return _FAIL; 1715554c0a3aSHans de Goede } 1716554c0a3aSHans de Goede 1717554c0a3aSHans de Goede unsigned int OnAction_back(struct adapter *padapter, union recv_frame *precv_frame) 1718554c0a3aSHans de Goede { 1719554c0a3aSHans de Goede u8 *addr; 1720554c0a3aSHans de Goede struct sta_info *psta = NULL; 1721554c0a3aSHans de Goede struct recv_reorder_ctrl *preorder_ctrl; 1722554c0a3aSHans de Goede unsigned char *frame_body; 1723554c0a3aSHans de Goede unsigned char category, action; 1724554c0a3aSHans de Goede unsigned short tid, status, reason_code = 0; 1725554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1726554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 1727554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1728554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 1729554c0a3aSHans de Goede 1730554c0a3aSHans de Goede /* check RA matches or not */ 1731554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN))/* for if1, sta/ap mode */ 1732554c0a3aSHans de Goede return _SUCCESS; 1733554c0a3aSHans de Goede 1734554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 1735554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) 1736554c0a3aSHans de Goede return _SUCCESS; 1737554c0a3aSHans de Goede 1738554c0a3aSHans de Goede addr = GetAddr2Ptr(pframe); 1739554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, addr); 1740554c0a3aSHans de Goede 174141452327SVatsala Narang if (!psta) 1742554c0a3aSHans de Goede return _SUCCESS; 1743554c0a3aSHans de Goede 1744554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1745554c0a3aSHans de Goede 1746554c0a3aSHans de Goede category = frame_body[0]; 1747554c0a3aSHans de Goede if (category == RTW_WLAN_CATEGORY_BACK) {/* representing Block Ack */ 1748a65f0d18SVatsala Narang if (!pmlmeinfo->HT_enable) 1749554c0a3aSHans de Goede return _SUCCESS; 1750554c0a3aSHans de Goede 1751554c0a3aSHans de Goede action = frame_body[1]; 1752554c0a3aSHans de Goede switch (action) { 1753f4acd33cSRoss Schmidt case WLAN_ACTION_ADDBA_REQ: /* ADDBA request */ 1754554c0a3aSHans de Goede 1755554c0a3aSHans de Goede memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request)); 1756554c0a3aSHans de Goede /* process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe)); */ 1757554c0a3aSHans de Goede process_addba_req(padapter, (u8 *)&(pmlmeinfo->ADDBA_req), addr); 1758554c0a3aSHans de Goede 17592646633fSAastha Gupta if (pmlmeinfo->accept_addba_req) { 1760f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 0); 1761554c0a3aSHans de Goede } else { 1762f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_ADDBA_RESP, 37);/* reject ADDBA Req */ 1763554c0a3aSHans de Goede } 1764554c0a3aSHans de Goede 1765554c0a3aSHans de Goede break; 1766554c0a3aSHans de Goede 1767f4acd33cSRoss Schmidt case WLAN_ACTION_ADDBA_RESP: /* ADDBA response */ 1768d48603afSRoss Schmidt status = get_unaligned_le16(&frame_body[3]); 1769554c0a3aSHans de Goede tid = ((frame_body[5] >> 2) & 0x7); 1770554c0a3aSHans de Goede 1771554c0a3aSHans de Goede if (status == 0) { 1772554c0a3aSHans de Goede /* successful */ 1773e52d8d0dSVatsala Narang psta->htpriv.agg_enable_bitmap |= BIT(tid); 1774554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); 1775554c0a3aSHans de Goede } else { 1776554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 1777554c0a3aSHans de Goede } 1778554c0a3aSHans de Goede 1779554c0a3aSHans de Goede if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { 1780554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 1781554c0a3aSHans de Goede psta->expire_to = pstapriv->expire_to; 1782554c0a3aSHans de Goede psta->state ^= WIFI_STA_ALIVE_CHK_STATE; 1783554c0a3aSHans de Goede } 1784554c0a3aSHans de Goede 1785554c0a3aSHans de Goede break; 1786554c0a3aSHans de Goede 1787f4acd33cSRoss Schmidt case WLAN_ACTION_DELBA: /* DELBA */ 1788554c0a3aSHans de Goede if ((frame_body[3] & BIT(3)) == 0) { 1789e52d8d0dSVatsala Narang psta->htpriv.agg_enable_bitmap &= 1790e52d8d0dSVatsala Narang ~BIT((frame_body[3] >> 4) & 0xf); 1791e52d8d0dSVatsala Narang psta->htpriv.candidate_tid_bitmap &= 1792e52d8d0dSVatsala Narang ~BIT((frame_body[3] >> 4) & 0xf); 1793554c0a3aSHans de Goede 1794554c0a3aSHans de Goede /* reason_code = frame_body[4] | (frame_body[5] << 8); */ 1795d48603afSRoss Schmidt reason_code = get_unaligned_le16(&frame_body[4]); 1796554c0a3aSHans de Goede } else if ((frame_body[3] & BIT(3)) == BIT(3)) { 1797554c0a3aSHans de Goede tid = (frame_body[3] >> 4) & 0x0F; 1798554c0a3aSHans de Goede 1799554c0a3aSHans de Goede preorder_ctrl = &psta->recvreorder_ctrl[tid]; 1800554c0a3aSHans de Goede preorder_ctrl->enable = false; 1801554c0a3aSHans de Goede preorder_ctrl->indicate_seq = 0xffff; 1802554c0a3aSHans de Goede } 1803554c0a3aSHans de Goede /* todo: how to notify the host while receiving DELETE BA */ 1804554c0a3aSHans de Goede break; 1805554c0a3aSHans de Goede 1806554c0a3aSHans de Goede default: 1807554c0a3aSHans de Goede break; 1808554c0a3aSHans de Goede } 1809554c0a3aSHans de Goede } 1810554c0a3aSHans de Goede return _SUCCESS; 1811554c0a3aSHans de Goede } 1812554c0a3aSHans de Goede 1813554c0a3aSHans de Goede static s32 rtw_action_public_decache(union recv_frame *recv_frame, s32 token) 1814554c0a3aSHans de Goede { 1815554c0a3aSHans de Goede struct adapter *adapter = recv_frame->u.hdr.adapter; 1816554c0a3aSHans de Goede struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv); 1817554c0a3aSHans de Goede u8 *frame = recv_frame->u.hdr.rx_data; 1818554c0a3aSHans de Goede u16 seq_ctrl = ((recv_frame->u.hdr.attrib.seq_num&0xffff) << 4) | 1819554c0a3aSHans de Goede (recv_frame->u.hdr.attrib.frag_num & 0xf); 1820554c0a3aSHans de Goede 1821554c0a3aSHans de Goede if (GetRetry(frame)) { 1822554c0a3aSHans de Goede if (token >= 0) { 1823554c0a3aSHans de Goede if ((seq_ctrl == mlmeext->action_public_rxseq) 1824709c8e49SFabio Aiuto && (token == mlmeext->action_public_dialog_token)) 1825554c0a3aSHans de Goede return _FAIL; 1826554c0a3aSHans de Goede } else { 1827709c8e49SFabio Aiuto if (seq_ctrl == mlmeext->action_public_rxseq) 1828554c0a3aSHans de Goede return _FAIL; 1829554c0a3aSHans de Goede } 1830554c0a3aSHans de Goede } 1831554c0a3aSHans de Goede 1832554c0a3aSHans de Goede mlmeext->action_public_rxseq = seq_ctrl; 1833554c0a3aSHans de Goede 1834554c0a3aSHans de Goede if (token >= 0) 1835554c0a3aSHans de Goede mlmeext->action_public_dialog_token = token; 1836554c0a3aSHans de Goede 1837554c0a3aSHans de Goede return _SUCCESS; 1838554c0a3aSHans de Goede } 1839554c0a3aSHans de Goede 1840554c0a3aSHans de Goede static unsigned int on_action_public_p2p(union recv_frame *precv_frame) 1841554c0a3aSHans de Goede { 1842554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1843554c0a3aSHans de Goede u8 *frame_body; 1844554c0a3aSHans de Goede u8 dialogToken = 0; 1845554c0a3aSHans de Goede 1846554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1847554c0a3aSHans de Goede 1848554c0a3aSHans de Goede dialogToken = frame_body[7]; 1849554c0a3aSHans de Goede 1850554c0a3aSHans de Goede if (rtw_action_public_decache(precv_frame, dialogToken) == _FAIL) 1851554c0a3aSHans de Goede return _FAIL; 1852554c0a3aSHans de Goede 1853554c0a3aSHans de Goede return _SUCCESS; 1854554c0a3aSHans de Goede } 1855554c0a3aSHans de Goede 1856554c0a3aSHans de Goede static unsigned int on_action_public_vendor(union recv_frame *precv_frame) 1857554c0a3aSHans de Goede { 1858554c0a3aSHans de Goede unsigned int ret = _FAIL; 1859554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1860554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 1861554c0a3aSHans de Goede 1862554c0a3aSHans de Goede if (!memcmp(frame_body + 2, P2P_OUI, 4)) { 1863554c0a3aSHans de Goede ret = on_action_public_p2p(precv_frame); 1864554c0a3aSHans de Goede } 1865554c0a3aSHans de Goede 1866554c0a3aSHans de Goede return ret; 1867554c0a3aSHans de Goede } 1868554c0a3aSHans de Goede 1869554c0a3aSHans de Goede static unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action) 1870554c0a3aSHans de Goede { 1871554c0a3aSHans de Goede unsigned int ret = _FAIL; 1872554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1873554c0a3aSHans de Goede uint frame_len = precv_frame->u.hdr.len; 1874554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 1875554c0a3aSHans de Goede u8 token; 1876554c0a3aSHans de Goede struct adapter *adapter = precv_frame->u.hdr.adapter; 1877554c0a3aSHans de Goede char msg[64]; 1878554c0a3aSHans de Goede 1879554c0a3aSHans de Goede token = frame_body[2]; 1880554c0a3aSHans de Goede 1881554c0a3aSHans de Goede if (rtw_action_public_decache(precv_frame, token) == _FAIL) 1882554c0a3aSHans de Goede goto exit; 1883554c0a3aSHans de Goede 188441b25593SCandy Febriyanto scnprintf(msg, sizeof(msg), "%s(token:%u)", action_public_str(action), token); 1885554c0a3aSHans de Goede rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg); 1886554c0a3aSHans de Goede 1887554c0a3aSHans de Goede ret = _SUCCESS; 1888554c0a3aSHans de Goede 1889554c0a3aSHans de Goede exit: 1890554c0a3aSHans de Goede return ret; 1891554c0a3aSHans de Goede } 1892554c0a3aSHans de Goede 1893554c0a3aSHans de Goede unsigned int on_action_public(struct adapter *padapter, union recv_frame *precv_frame) 1894554c0a3aSHans de Goede { 1895554c0a3aSHans de Goede unsigned int ret = _FAIL; 1896554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1897554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 1898554c0a3aSHans de Goede u8 category, action; 1899554c0a3aSHans de Goede 1900554c0a3aSHans de Goede /* check RA matches or not */ 1901554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN)) 1902554c0a3aSHans de Goede goto exit; 1903554c0a3aSHans de Goede 1904554c0a3aSHans de Goede category = frame_body[0]; 1905554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_PUBLIC) 1906554c0a3aSHans de Goede goto exit; 1907554c0a3aSHans de Goede 1908554c0a3aSHans de Goede action = frame_body[1]; 1909554c0a3aSHans de Goede switch (action) { 1910554c0a3aSHans de Goede case ACT_PUBLIC_VENDOR: 1911554c0a3aSHans de Goede ret = on_action_public_vendor(precv_frame); 1912554c0a3aSHans de Goede break; 1913554c0a3aSHans de Goede default: 1914554c0a3aSHans de Goede ret = on_action_public_default(precv_frame, action); 1915554c0a3aSHans de Goede break; 1916554c0a3aSHans de Goede } 1917554c0a3aSHans de Goede 1918554c0a3aSHans de Goede exit: 1919554c0a3aSHans de Goede return ret; 1920554c0a3aSHans de Goede } 1921554c0a3aSHans de Goede 1922554c0a3aSHans de Goede unsigned int OnAction_ht(struct adapter *padapter, union recv_frame *precv_frame) 1923554c0a3aSHans de Goede { 1924554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1925554c0a3aSHans de Goede u8 *frame_body = pframe + sizeof(struct ieee80211_hdr_3addr); 1926554c0a3aSHans de Goede u8 category, action; 1927554c0a3aSHans de Goede 1928554c0a3aSHans de Goede /* check RA matches or not */ 1929554c0a3aSHans de Goede if (memcmp(myid(&(padapter->eeprompriv)), GetAddr1Ptr(pframe), ETH_ALEN)) 1930554c0a3aSHans de Goede goto exit; 1931554c0a3aSHans de Goede 1932554c0a3aSHans de Goede category = frame_body[0]; 1933554c0a3aSHans de Goede if (category != RTW_WLAN_CATEGORY_HT) 1934554c0a3aSHans de Goede goto exit; 1935554c0a3aSHans de Goede 1936554c0a3aSHans de Goede action = frame_body[1]; 1937554c0a3aSHans de Goede switch (action) { 1938a9d87638SRoss Schmidt case WLAN_HT_ACTION_COMPRESSED_BF: 1939554c0a3aSHans de Goede break; 1940554c0a3aSHans de Goede default: 1941554c0a3aSHans de Goede break; 1942554c0a3aSHans de Goede } 1943554c0a3aSHans de Goede 1944554c0a3aSHans de Goede exit: 1945554c0a3aSHans de Goede 1946554c0a3aSHans de Goede return _SUCCESS; 1947554c0a3aSHans de Goede } 1948554c0a3aSHans de Goede 1949554c0a3aSHans de Goede unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv_frame) 1950554c0a3aSHans de Goede { 1951554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1952554c0a3aSHans de Goede struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib; 1953554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 1954554c0a3aSHans de Goede unsigned short tid; 1955554c0a3aSHans de Goede 1956554c0a3aSHans de Goede switch (pframe[WLAN_HDR_A3_LEN+1]) { 1957554c0a3aSHans de Goede case 0: /* SA Query req */ 1958554c0a3aSHans de Goede memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(unsigned short)); 1959554c0a3aSHans de Goede issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid); 1960554c0a3aSHans de Goede break; 1961554c0a3aSHans de Goede 1962554c0a3aSHans de Goede case 1: /* SA Query rsp */ 1963554c0a3aSHans de Goede del_timer_sync(&pmlmeext->sa_query_timer); 1964554c0a3aSHans de Goede break; 1965554c0a3aSHans de Goede default: 1966554c0a3aSHans de Goede break; 1967554c0a3aSHans de Goede } 1968554c0a3aSHans de Goede if (0) { 1969554c0a3aSHans de Goede int pp; 1970c926f022SSimran Singhal 1971554c0a3aSHans de Goede printk("pattrib->pktlen = %d =>", pattrib->pkt_len); 1972554c0a3aSHans de Goede for (pp = 0; pp < pattrib->pkt_len; pp++) 1973554c0a3aSHans de Goede printk(" %02x ", pframe[pp]); 1974554c0a3aSHans de Goede printk("\n"); 1975554c0a3aSHans de Goede } 1976554c0a3aSHans de Goede 1977554c0a3aSHans de Goede return _SUCCESS; 1978554c0a3aSHans de Goede } 1979554c0a3aSHans de Goede 1980554c0a3aSHans de Goede unsigned int OnAction(struct adapter *padapter, union recv_frame *precv_frame) 1981554c0a3aSHans de Goede { 1982554c0a3aSHans de Goede int i; 1983554c0a3aSHans de Goede unsigned char category; 1984554c0a3aSHans de Goede struct action_handler *ptable; 1985554c0a3aSHans de Goede unsigned char *frame_body; 1986554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 1987554c0a3aSHans de Goede 1988554c0a3aSHans de Goede frame_body = (unsigned char *)(pframe + sizeof(struct ieee80211_hdr_3addr)); 1989554c0a3aSHans de Goede 1990554c0a3aSHans de Goede category = frame_body[0]; 1991554c0a3aSHans de Goede 199260db8d10SJérémy Lefaure for (i = 0; i < ARRAY_SIZE(OnAction_tbl); i++) { 1993554c0a3aSHans de Goede ptable = &OnAction_tbl[i]; 1994554c0a3aSHans de Goede 1995554c0a3aSHans de Goede if (category == ptable->num) 1996554c0a3aSHans de Goede ptable->func(padapter, precv_frame); 1997554c0a3aSHans de Goede 1998554c0a3aSHans de Goede } 1999554c0a3aSHans de Goede 2000554c0a3aSHans de Goede return _SUCCESS; 2001554c0a3aSHans de Goede 2002554c0a3aSHans de Goede } 2003554c0a3aSHans de Goede 2004554c0a3aSHans de Goede unsigned int DoReserved(struct adapter *padapter, union recv_frame *precv_frame) 2005554c0a3aSHans de Goede { 2006554c0a3aSHans de Goede return _SUCCESS; 2007554c0a3aSHans de Goede } 2008554c0a3aSHans de Goede 2009554c0a3aSHans de Goede static struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once) 2010554c0a3aSHans de Goede { 2011554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2012554c0a3aSHans de Goede struct xmit_buf *pxmitbuf; 2013554c0a3aSHans de Goede 2014554c0a3aSHans de Goede if (once) 2015554c0a3aSHans de Goede pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv); 2016554c0a3aSHans de Goede else 2017554c0a3aSHans de Goede pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv); 2018554c0a3aSHans de Goede 2019e427bdd8SFabio Aiuto if (!pmgntframe) 2020554c0a3aSHans de Goede goto exit; 2021554c0a3aSHans de Goede 2022554c0a3aSHans de Goede pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv); 2023554c0a3aSHans de Goede if (pxmitbuf == NULL) { 2024554c0a3aSHans de Goede rtw_free_xmitframe(pxmitpriv, pmgntframe); 2025554c0a3aSHans de Goede pmgntframe = NULL; 2026554c0a3aSHans de Goede goto exit; 2027554c0a3aSHans de Goede } 2028554c0a3aSHans de Goede 2029554c0a3aSHans de Goede pmgntframe->frame_tag = MGNT_FRAMETAG; 2030554c0a3aSHans de Goede pmgntframe->pxmitbuf = pxmitbuf; 2031554c0a3aSHans de Goede pmgntframe->buf_addr = pxmitbuf->pbuf; 2032554c0a3aSHans de Goede pxmitbuf->priv_data = pmgntframe; 2033554c0a3aSHans de Goede 2034554c0a3aSHans de Goede exit: 2035554c0a3aSHans de Goede return pmgntframe; 2036554c0a3aSHans de Goede 2037554c0a3aSHans de Goede } 2038554c0a3aSHans de Goede 2039554c0a3aSHans de Goede inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv) 2040554c0a3aSHans de Goede { 2041554c0a3aSHans de Goede return _alloc_mgtxmitframe(pxmitpriv, false); 2042554c0a3aSHans de Goede } 2043554c0a3aSHans de Goede 2044554c0a3aSHans de Goede /**************************************************************************** 2045554c0a3aSHans de Goede 204668468503SAndreas Hellmich Following are some TX functions for WiFi MLME 2047554c0a3aSHans de Goede 2048554c0a3aSHans de Goede *****************************************************************************/ 2049554c0a3aSHans de Goede 2050554c0a3aSHans de Goede void update_mgnt_tx_rate(struct adapter *padapter, u8 rate) 2051554c0a3aSHans de Goede { 2052554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2053554c0a3aSHans de Goede 2054554c0a3aSHans de Goede pmlmeext->tx_rate = rate; 2055554c0a3aSHans de Goede } 2056554c0a3aSHans de Goede 2057554c0a3aSHans de Goede void update_mgntframe_attrib(struct adapter *padapter, struct pkt_attrib *pattrib) 2058554c0a3aSHans de Goede { 2059554c0a3aSHans de Goede u8 wireless_mode; 2060554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2061554c0a3aSHans de Goede 2062554c0a3aSHans de Goede /* memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib)); */ 2063554c0a3aSHans de Goede 2064554c0a3aSHans de Goede pattrib->hdrlen = 24; 2065554c0a3aSHans de Goede pattrib->nr_frags = 1; 2066554c0a3aSHans de Goede pattrib->priority = 7; 2067554c0a3aSHans de Goede pattrib->mac_id = 0; 2068554c0a3aSHans de Goede pattrib->qsel = 0x12; 2069554c0a3aSHans de Goede 2070554c0a3aSHans de Goede pattrib->pktlen = 0; 2071554c0a3aSHans de Goede 2072554c0a3aSHans de Goede if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB) 2073554c0a3aSHans de Goede wireless_mode = WIRELESS_11B; 2074554c0a3aSHans de Goede else 2075554c0a3aSHans de Goede wireless_mode = WIRELESS_11G; 2076554c0a3aSHans de Goede pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode); 2077554c0a3aSHans de Goede pattrib->rate = pmlmeext->tx_rate; 2078554c0a3aSHans de Goede 2079554c0a3aSHans de Goede pattrib->encrypt = _NO_PRIVACY_; 2080554c0a3aSHans de Goede pattrib->bswenc = false; 2081554c0a3aSHans de Goede 2082554c0a3aSHans de Goede pattrib->qos_en = false; 2083554c0a3aSHans de Goede pattrib->ht_en = false; 2084554c0a3aSHans de Goede pattrib->bwmode = CHANNEL_WIDTH_20; 2085554c0a3aSHans de Goede pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 2086554c0a3aSHans de Goede pattrib->sgi = false; 2087554c0a3aSHans de Goede 2088554c0a3aSHans de Goede pattrib->seqnum = pmlmeext->mgnt_seq; 2089554c0a3aSHans de Goede 2090554c0a3aSHans de Goede pattrib->retry_ctrl = true; 2091554c0a3aSHans de Goede 2092554c0a3aSHans de Goede pattrib->mbssid = 0; 2093554c0a3aSHans de Goede 2094554c0a3aSHans de Goede } 2095554c0a3aSHans de Goede 2096554c0a3aSHans de Goede void update_mgntframe_attrib_addr(struct adapter *padapter, struct xmit_frame *pmgntframe) 2097554c0a3aSHans de Goede { 2098554c0a3aSHans de Goede u8 *pframe; 2099554c0a3aSHans de Goede struct pkt_attrib *pattrib = &pmgntframe->attrib; 2100554c0a3aSHans de Goede 2101554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2102554c0a3aSHans de Goede 2103554c0a3aSHans de Goede memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN); 2104554c0a3aSHans de Goede memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN); 2105554c0a3aSHans de Goede } 2106554c0a3aSHans de Goede 2107554c0a3aSHans de Goede void dump_mgntframe(struct adapter *padapter, struct xmit_frame *pmgntframe) 2108554c0a3aSHans de Goede { 21090ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 21100ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2111554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2112554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2113554c0a3aSHans de Goede return; 2114554c0a3aSHans de Goede } 2115554c0a3aSHans de Goede 2116554c0a3aSHans de Goede rtw_hal_mgnt_xmit(padapter, pmgntframe); 2117554c0a3aSHans de Goede } 2118554c0a3aSHans de Goede 2119554c0a3aSHans de Goede s32 dump_mgntframe_and_wait(struct adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms) 2120554c0a3aSHans de Goede { 2121554c0a3aSHans de Goede s32 ret = _FAIL; 212200d5865cSMarco Cesati unsigned long irqL; 2123554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 2124554c0a3aSHans de Goede struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf; 2125554c0a3aSHans de Goede struct submit_ctx sctx; 2126554c0a3aSHans de Goede 21270ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 21280ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2129554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2130554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2131554c0a3aSHans de Goede return ret; 2132554c0a3aSHans de Goede } 2133554c0a3aSHans de Goede 2134554c0a3aSHans de Goede rtw_sctx_init(&sctx, timeout_ms); 2135554c0a3aSHans de Goede pxmitbuf->sctx = &sctx; 2136554c0a3aSHans de Goede 2137554c0a3aSHans de Goede ret = rtw_hal_mgnt_xmit(padapter, pmgntframe); 2138554c0a3aSHans de Goede 2139554c0a3aSHans de Goede if (ret == _SUCCESS) 2140*5f8e9affSBryan Brattlof ret = rtw_sctx_wait(&sctx); 2141554c0a3aSHans de Goede 2142554c0a3aSHans de Goede spin_lock_irqsave(&pxmitpriv->lock_sctx, irqL); 2143554c0a3aSHans de Goede pxmitbuf->sctx = NULL; 2144554c0a3aSHans de Goede spin_unlock_irqrestore(&pxmitpriv->lock_sctx, irqL); 2145554c0a3aSHans de Goede 2146554c0a3aSHans de Goede return ret; 2147554c0a3aSHans de Goede } 2148554c0a3aSHans de Goede 2149554c0a3aSHans de Goede s32 dump_mgntframe_and_wait_ack(struct adapter *padapter, struct xmit_frame *pmgntframe) 2150554c0a3aSHans de Goede { 215140d4aa0fSShreeya Patel static u8 seq_no; 2152554c0a3aSHans de Goede s32 ret = _FAIL; 2153554c0a3aSHans de Goede u32 timeout_ms = 500;/* 500ms */ 2154554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 2155554c0a3aSHans de Goede 21560ad02fa8SGeorgiana Chelu if (padapter->bSurpriseRemoved || 21570ad02fa8SGeorgiana Chelu padapter->bDriverStopped) { 2158554c0a3aSHans de Goede rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf); 2159554c0a3aSHans de Goede rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe); 2160554c0a3aSHans de Goede return -1; 2161554c0a3aSHans de Goede } 2162554c0a3aSHans de Goede 2163554c0a3aSHans de Goede if (mutex_lock_interruptible(&pxmitpriv->ack_tx_mutex) == 0) { 2164554c0a3aSHans de Goede pxmitpriv->ack_tx = true; 2165554c0a3aSHans de Goede pxmitpriv->seq_no = seq_no++; 2166554c0a3aSHans de Goede pmgntframe->ack_report = 1; 2167a65f0d18SVatsala Narang if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) 2168554c0a3aSHans de Goede ret = rtw_ack_tx_wait(pxmitpriv, timeout_ms); 2169554c0a3aSHans de Goede 2170554c0a3aSHans de Goede pxmitpriv->ack_tx = false; 2171554c0a3aSHans de Goede mutex_unlock(&pxmitpriv->ack_tx_mutex); 2172554c0a3aSHans de Goede } 2173554c0a3aSHans de Goede 2174554c0a3aSHans de Goede return ret; 2175554c0a3aSHans de Goede } 2176554c0a3aSHans de Goede 2177554c0a3aSHans de Goede static int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode) 2178554c0a3aSHans de Goede { 2179554c0a3aSHans de Goede u8 *ssid_ie; 2180d495c550SMarco Cesati signed int ssid_len_ori; 2181554c0a3aSHans de Goede int len_diff = 0; 2182554c0a3aSHans de Goede 2183554c0a3aSHans de Goede ssid_ie = rtw_get_ie(ies, WLAN_EID_SSID, &ssid_len_ori, ies_len); 2184554c0a3aSHans de Goede 2185554c0a3aSHans de Goede if (ssid_ie && ssid_len_ori > 0) { 2186554c0a3aSHans de Goede switch (hidden_ssid_mode) { 2187554c0a3aSHans de Goede case 1: 2188554c0a3aSHans de Goede { 2189554c0a3aSHans de Goede u8 *next_ie = ssid_ie + 2 + ssid_len_ori; 2190554c0a3aSHans de Goede u32 remain_len = 0; 2191554c0a3aSHans de Goede 2192554c0a3aSHans de Goede remain_len = ies_len - (next_ie-ies); 2193554c0a3aSHans de Goede 2194554c0a3aSHans de Goede ssid_ie[1] = 0; 2195554c0a3aSHans de Goede memcpy(ssid_ie+2, next_ie, remain_len); 2196554c0a3aSHans de Goede len_diff -= ssid_len_ori; 2197554c0a3aSHans de Goede 2198554c0a3aSHans de Goede break; 2199554c0a3aSHans de Goede } 2200554c0a3aSHans de Goede case 2: 2201554c0a3aSHans de Goede memset(&ssid_ie[2], 0, ssid_len_ori); 2202554c0a3aSHans de Goede break; 2203554c0a3aSHans de Goede default: 2204554c0a3aSHans de Goede break; 2205554c0a3aSHans de Goede } 2206554c0a3aSHans de Goede } 2207554c0a3aSHans de Goede 2208554c0a3aSHans de Goede return len_diff; 2209554c0a3aSHans de Goede } 2210554c0a3aSHans de Goede 2211554c0a3aSHans de Goede void issue_beacon(struct adapter *padapter, int timeout_ms) 2212554c0a3aSHans de Goede { 2213554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2214554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2215554c0a3aSHans de Goede unsigned char *pframe; 2216554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2217554c0a3aSHans de Goede __le16 *fctrl; 2218554c0a3aSHans de Goede unsigned int rate_len; 2219554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2220554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2221554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2222554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2223554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 2224554c0a3aSHans de Goede u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 2225554c0a3aSHans de Goede 2226554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2227709c8e49SFabio Aiuto if (!pmgntframe) 2228554c0a3aSHans de Goede return; 2229554c0a3aSHans de Goede 2230554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->bcn_update_lock); 2231554c0a3aSHans de Goede 2232554c0a3aSHans de Goede /* update attribute */ 2233554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2234554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2235554c0a3aSHans de Goede pattrib->qsel = 0x10; 2236554c0a3aSHans de Goede 2237554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2238554c0a3aSHans de Goede 2239554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2240554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2241554c0a3aSHans de Goede 2242554c0a3aSHans de Goede 2243554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2244554c0a3aSHans de Goede *(fctrl) = 0; 2245554c0a3aSHans de Goede 2246554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); 2247554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 2248554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN); 2249554c0a3aSHans de Goede 2250554c0a3aSHans de Goede SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/); 2251554c0a3aSHans de Goede /* pmlmeext->mgnt_seq++; */ 2252554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_BEACON); 2253554c0a3aSHans de Goede 2254554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2255554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2256554c0a3aSHans de Goede 2257554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { 2258554c0a3aSHans de Goede { 2259554c0a3aSHans de Goede int len_diff; 2260c926f022SSimran Singhal 2261554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, cur_network->IELength); 22625641eeecSRoss Schmidt len_diff = update_hidden_ssid(pframe+_BEACON_IE_OFFSET_, 22635641eeecSRoss Schmidt cur_network->IELength-_BEACON_IE_OFFSET_, 22645641eeecSRoss Schmidt pmlmeinfo->hidden_ssid_mode); 2265554c0a3aSHans de Goede pframe += (cur_network->IELength+len_diff); 2266554c0a3aSHans de Goede pattrib->pktlen += (cur_network->IELength+len_diff); 2267554c0a3aSHans de Goede } 2268554c0a3aSHans de Goede 2269554c0a3aSHans de Goede { 2270554c0a3aSHans de Goede u8 *wps_ie; 2271554c0a3aSHans de Goede uint wps_ielen; 2272554c0a3aSHans de Goede u8 sr = 0; 2273c926f022SSimran Singhal 2274554c0a3aSHans de Goede wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_, 2275554c0a3aSHans de Goede pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen); 2276554c0a3aSHans de Goede if (wps_ie && wps_ielen > 0) { 2277554c0a3aSHans de Goede rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8 *)(&sr), NULL); 2278554c0a3aSHans de Goede } 2279554c0a3aSHans de Goede if (sr != 0) 2280554c0a3aSHans de Goede set_fwstate(pmlmepriv, WIFI_UNDER_WPS); 2281554c0a3aSHans de Goede else 2282554c0a3aSHans de Goede _clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS); 2283554c0a3aSHans de Goede } 2284554c0a3aSHans de Goede 2285554c0a3aSHans de Goede goto _issue_bcn; 2286554c0a3aSHans de Goede 2287554c0a3aSHans de Goede } 2288554c0a3aSHans de Goede 2289554c0a3aSHans de Goede /* below for ad-hoc mode */ 2290554c0a3aSHans de Goede 2291554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 2292554c0a3aSHans de Goede pframe += 8; 2293554c0a3aSHans de Goede pattrib->pktlen += 8; 2294554c0a3aSHans de Goede 2295554c0a3aSHans de Goede /* beacon interval: 2 bytes */ 2296554c0a3aSHans de Goede 2297554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 2298554c0a3aSHans de Goede 2299554c0a3aSHans de Goede pframe += 2; 2300554c0a3aSHans de Goede pattrib->pktlen += 2; 2301554c0a3aSHans de Goede 2302554c0a3aSHans de Goede /* capability info: 2 bytes */ 2303554c0a3aSHans de Goede 2304554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); 2305554c0a3aSHans de Goede 2306554c0a3aSHans de Goede pframe += 2; 2307554c0a3aSHans de Goede pattrib->pktlen += 2; 2308554c0a3aSHans de Goede 2309554c0a3aSHans de Goede /* SSID */ 23103f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); 2311554c0a3aSHans de Goede 2312554c0a3aSHans de Goede /* supported rates... */ 2313554c0a3aSHans de Goede rate_len = rtw_get_rateset_len(cur_network->SupportedRates); 2314c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); 2315554c0a3aSHans de Goede 2316554c0a3aSHans de Goede /* DS parameter set */ 23178f6a9446SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen); 2318554c0a3aSHans de Goede 2319554c0a3aSHans de Goede /* if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) */ 2320554c0a3aSHans de Goede { 2321554c0a3aSHans de Goede u8 erpinfo = 0; 2322554c0a3aSHans de Goede u32 ATIMWindow; 2323554c0a3aSHans de Goede /* IBSS Parameter Set... */ 2324554c0a3aSHans de Goede /* ATIMWindow = cur->Configuration.ATIMWindow; */ 2325554c0a3aSHans de Goede ATIMWindow = 0; 2326e6038a48SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); 2327554c0a3aSHans de Goede 2328554c0a3aSHans de Goede /* ERP IE */ 23297bd332ecSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen); 2330554c0a3aSHans de Goede } 2331554c0a3aSHans de Goede 2332554c0a3aSHans de Goede 2333554c0a3aSHans de Goede /* EXTERNDED SUPPORTED RATE */ 2334554c0a3aSHans de Goede if (rate_len > 8) { 233500f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); 2336554c0a3aSHans de Goede } 2337554c0a3aSHans de Goede 2338554c0a3aSHans de Goede 2339554c0a3aSHans de Goede /* todo:HT for adhoc */ 2340554c0a3aSHans de Goede 2341554c0a3aSHans de Goede _issue_bcn: 2342554c0a3aSHans de Goede 2343554c0a3aSHans de Goede pmlmepriv->update_bcn = false; 2344554c0a3aSHans de Goede 2345554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->bcn_update_lock); 2346554c0a3aSHans de Goede 2347709c8e49SFabio Aiuto if ((pattrib->pktlen + TXDESC_SIZE) > 512) 2348554c0a3aSHans de Goede return; 2349554c0a3aSHans de Goede 2350554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2351554c0a3aSHans de Goede 2352554c0a3aSHans de Goede if (timeout_ms > 0) 2353554c0a3aSHans de Goede dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms); 2354554c0a3aSHans de Goede else 2355554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2356554c0a3aSHans de Goede 2357554c0a3aSHans de Goede } 2358554c0a3aSHans de Goede 2359554c0a3aSHans de Goede void issue_probersp(struct adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq) 2360554c0a3aSHans de Goede { 2361554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2362554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2363554c0a3aSHans de Goede unsigned char *pframe; 2364554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2365554c0a3aSHans de Goede __le16 *fctrl; 2366554c0a3aSHans de Goede unsigned char *mac, *bssid; 2367554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2368554c0a3aSHans de Goede 2369554c0a3aSHans de Goede u8 *pwps_ie; 2370554c0a3aSHans de Goede uint wps_ielen; 2371554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 2372554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2373554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2374554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 2375554c0a3aSHans de Goede unsigned int rate_len; 2376554c0a3aSHans de Goede 2377554c0a3aSHans de Goede if (da == NULL) 2378554c0a3aSHans de Goede return; 2379554c0a3aSHans de Goede 2380554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2381e427bdd8SFabio Aiuto if (!pmgntframe) 2382554c0a3aSHans de Goede return; 2383554c0a3aSHans de Goede 2384554c0a3aSHans de Goede /* update attribute */ 2385554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2386554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2387554c0a3aSHans de Goede 2388554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2389554c0a3aSHans de Goede 2390554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2391554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2392554c0a3aSHans de Goede 2393554c0a3aSHans de Goede mac = myid(&(padapter->eeprompriv)); 2394554c0a3aSHans de Goede bssid = cur_network->MacAddress; 2395554c0a3aSHans de Goede 2396554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2397554c0a3aSHans de Goede *(fctrl) = 0; 2398554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 2399554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, mac, ETH_ALEN); 2400554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, bssid, ETH_ALEN); 2401554c0a3aSHans de Goede 2402554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2403554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2404554c0a3aSHans de Goede SetFrameSubType(fctrl, WIFI_PROBERSP); 2405554c0a3aSHans de Goede 2406554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 2407554c0a3aSHans de Goede pattrib->pktlen = pattrib->hdrlen; 2408554c0a3aSHans de Goede pframe += pattrib->hdrlen; 2409554c0a3aSHans de Goede 2410554c0a3aSHans de Goede 2411554c0a3aSHans de Goede if (cur_network->IELength > MAX_IE_SZ) 2412554c0a3aSHans de Goede return; 2413554c0a3aSHans de Goede 2414554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) { 2415554c0a3aSHans de Goede pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen); 2416554c0a3aSHans de Goede 2417554c0a3aSHans de Goede /* inerset & update wps_probe_resp_ie */ 241834557e23SIzabela Bakollari if (pmlmepriv->wps_probe_resp_ie && pwps_ie && wps_ielen > 0) { 2419554c0a3aSHans de Goede uint wps_offset, remainder_ielen; 2420554c0a3aSHans de Goede u8 *premainder_ie; 2421554c0a3aSHans de Goede 2422554c0a3aSHans de Goede wps_offset = (uint)(pwps_ie - cur_network->IEs); 2423554c0a3aSHans de Goede 2424554c0a3aSHans de Goede premainder_ie = pwps_ie + wps_ielen; 2425554c0a3aSHans de Goede 2426554c0a3aSHans de Goede remainder_ielen = cur_network->IELength - wps_offset - wps_ielen; 2427554c0a3aSHans de Goede 2428554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, wps_offset); 2429554c0a3aSHans de Goede pframe += wps_offset; 2430554c0a3aSHans de Goede pattrib->pktlen += wps_offset; 2431554c0a3aSHans de Goede 2432554c0a3aSHans de Goede wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];/* to get ie data len */ 2433554c0a3aSHans de Goede if ((wps_offset+wps_ielen+2) <= MAX_IE_SZ) { 2434554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2); 2435554c0a3aSHans de Goede pframe += wps_ielen+2; 2436554c0a3aSHans de Goede pattrib->pktlen += wps_ielen+2; 2437554c0a3aSHans de Goede } 2438554c0a3aSHans de Goede 2439554c0a3aSHans de Goede if ((wps_offset+wps_ielen+2+remainder_ielen) <= MAX_IE_SZ) { 2440554c0a3aSHans de Goede memcpy(pframe, premainder_ie, remainder_ielen); 2441554c0a3aSHans de Goede pframe += remainder_ielen; 2442554c0a3aSHans de Goede pattrib->pktlen += remainder_ielen; 2443554c0a3aSHans de Goede } 2444554c0a3aSHans de Goede } else { 2445554c0a3aSHans de Goede memcpy(pframe, cur_network->IEs, cur_network->IELength); 2446554c0a3aSHans de Goede pframe += cur_network->IELength; 2447554c0a3aSHans de Goede pattrib->pktlen += cur_network->IELength; 2448554c0a3aSHans de Goede } 2449554c0a3aSHans de Goede 2450554c0a3aSHans de Goede /* retrieve SSID IE from cur_network->Ssid */ 2451554c0a3aSHans de Goede { 2452554c0a3aSHans de Goede u8 *ssid_ie; 2453d495c550SMarco Cesati signed int ssid_ielen; 2454d495c550SMarco Cesati signed int ssid_ielen_diff; 2455705655a2SLee Jones u8 *buf; 2456554c0a3aSHans de Goede u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct ieee80211_hdr_3addr); 2457554c0a3aSHans de Goede 2458705655a2SLee Jones buf = rtw_zmalloc(MAX_IE_SZ); 2459705655a2SLee Jones if (!buf) 2460705655a2SLee Jones return; 2461705655a2SLee Jones 24623f15277bSRoss Schmidt ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, WLAN_EID_SSID, &ssid_ielen, 2463554c0a3aSHans de Goede (pframe-ies)-_FIXED_IE_LENGTH_); 2464554c0a3aSHans de Goede 2465554c0a3aSHans de Goede ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen; 2466554c0a3aSHans de Goede 2467554c0a3aSHans de Goede if (ssid_ie && cur_network->Ssid.SsidLength) { 2468554c0a3aSHans de Goede uint remainder_ielen; 2469554c0a3aSHans de Goede u8 *remainder_ie; 2470c926f022SSimran Singhal 2471554c0a3aSHans de Goede remainder_ie = ssid_ie+2; 2472554c0a3aSHans de Goede remainder_ielen = (pframe-remainder_ie); 2473554c0a3aSHans de Goede 2474554c0a3aSHans de Goede if (remainder_ielen > MAX_IE_SZ) { 247579df841bSFabio Aiuto netdev_warn(padapter->pnetdev, 247679df841bSFabio Aiuto FUNC_ADPT_FMT " remainder_ielen > MAX_IE_SZ\n", 247779df841bSFabio Aiuto FUNC_ADPT_ARG(padapter)); 2478554c0a3aSHans de Goede remainder_ielen = MAX_IE_SZ; 2479554c0a3aSHans de Goede } 2480554c0a3aSHans de Goede 2481554c0a3aSHans de Goede memcpy(buf, remainder_ie, remainder_ielen); 2482554c0a3aSHans de Goede memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen); 2483554c0a3aSHans de Goede *(ssid_ie+1) = cur_network->Ssid.SsidLength; 2484554c0a3aSHans de Goede memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength); 2485554c0a3aSHans de Goede 2486554c0a3aSHans de Goede pframe += ssid_ielen_diff; 2487554c0a3aSHans de Goede pattrib->pktlen += ssid_ielen_diff; 2488554c0a3aSHans de Goede } 2489705655a2SLee Jones kfree (buf); 2490554c0a3aSHans de Goede } 2491554c0a3aSHans de Goede } else { 2492554c0a3aSHans de Goede /* timestamp will be inserted by hardware */ 2493554c0a3aSHans de Goede pframe += 8; 2494554c0a3aSHans de Goede pattrib->pktlen += 8; 2495554c0a3aSHans de Goede 2496554c0a3aSHans de Goede /* beacon interval: 2 bytes */ 2497554c0a3aSHans de Goede 2498554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 2499554c0a3aSHans de Goede 2500554c0a3aSHans de Goede pframe += 2; 2501554c0a3aSHans de Goede pattrib->pktlen += 2; 2502554c0a3aSHans de Goede 2503554c0a3aSHans de Goede /* capability info: 2 bytes */ 2504554c0a3aSHans de Goede 2505554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2); 2506554c0a3aSHans de Goede 2507554c0a3aSHans de Goede pframe += 2; 2508554c0a3aSHans de Goede pattrib->pktlen += 2; 2509554c0a3aSHans de Goede 2510554c0a3aSHans de Goede /* below for ad-hoc mode */ 2511554c0a3aSHans de Goede 2512554c0a3aSHans de Goede /* SSID */ 25133f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen); 2514554c0a3aSHans de Goede 2515554c0a3aSHans de Goede /* supported rates... */ 2516554c0a3aSHans de Goede rate_len = rtw_get_rateset_len(cur_network->SupportedRates); 2517c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, ((rate_len > 8) ? 8 : rate_len), cur_network->SupportedRates, &pattrib->pktlen); 2518554c0a3aSHans de Goede 2519554c0a3aSHans de Goede /* DS parameter set */ 25208f6a9446SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen); 2521554c0a3aSHans de Goede 2522554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 2523554c0a3aSHans de Goede u8 erpinfo = 0; 2524554c0a3aSHans de Goede u32 ATIMWindow; 2525554c0a3aSHans de Goede /* IBSS Parameter Set... */ 2526554c0a3aSHans de Goede /* ATIMWindow = cur->Configuration.ATIMWindow; */ 2527554c0a3aSHans de Goede ATIMWindow = 0; 2528e6038a48SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_IBSS_PARAMS, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen); 2529554c0a3aSHans de Goede 2530554c0a3aSHans de Goede /* ERP IE */ 25317bd332ecSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_ERP_INFO, 1, &erpinfo, &pattrib->pktlen); 2532554c0a3aSHans de Goede } 2533554c0a3aSHans de Goede 2534554c0a3aSHans de Goede 2535554c0a3aSHans de Goede /* EXTERNDED SUPPORTED RATE */ 2536554c0a3aSHans de Goede if (rate_len > 8) { 253700f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen); 2538554c0a3aSHans de Goede } 2539554c0a3aSHans de Goede 2540554c0a3aSHans de Goede 2541554c0a3aSHans de Goede /* todo:HT for adhoc */ 2542554c0a3aSHans de Goede 2543554c0a3aSHans de Goede } 2544554c0a3aSHans de Goede 2545554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2546554c0a3aSHans de Goede 2547554c0a3aSHans de Goede 2548554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2549554c0a3aSHans de Goede 2550554c0a3aSHans de Goede return; 2551554c0a3aSHans de Goede 2552554c0a3aSHans de Goede } 2553554c0a3aSHans de Goede 255442b3b621SAishwarya Pant static int _issue_probereq(struct adapter *padapter, 255542b3b621SAishwarya Pant struct ndis_802_11_ssid *pssid, 255642b3b621SAishwarya Pant u8 *da, u8 ch, bool append_wps, bool wait_ack) 2557554c0a3aSHans de Goede { 2558554c0a3aSHans de Goede int ret = _FAIL; 2559554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2560554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2561554c0a3aSHans de Goede unsigned char *pframe; 2562554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2563554c0a3aSHans de Goede __le16 *fctrl; 2564554c0a3aSHans de Goede unsigned char *mac; 2565554c0a3aSHans de Goede unsigned char bssrate[NumRates]; 2566554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2567554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2568554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2569554c0a3aSHans de Goede int bssrate_len = 0; 2570554c0a3aSHans de Goede u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 2571554c0a3aSHans de Goede 2572554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 257341452327SVatsala Narang if (!pmgntframe) 2574554c0a3aSHans de Goede goto exit; 2575554c0a3aSHans de Goede 2576554c0a3aSHans de Goede /* update attribute */ 2577554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2578554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2579554c0a3aSHans de Goede 2580554c0a3aSHans de Goede 2581554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2582554c0a3aSHans de Goede 2583554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2584554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2585554c0a3aSHans de Goede 2586554c0a3aSHans de Goede mac = myid(&(padapter->eeprompriv)); 2587554c0a3aSHans de Goede 2588554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2589554c0a3aSHans de Goede *(fctrl) = 0; 2590554c0a3aSHans de Goede 2591554c0a3aSHans de Goede if (da) { 2592554c0a3aSHans de Goede /* unicast probe request frame */ 2593554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 2594554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, da, ETH_ALEN); 2595554c0a3aSHans de Goede } else { 2596554c0a3aSHans de Goede /* broadcast probe request frame */ 2597554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN); 2598554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN); 2599554c0a3aSHans de Goede } 2600554c0a3aSHans de Goede 2601554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, mac, ETH_ALEN); 2602554c0a3aSHans de Goede 2603554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2604554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2605554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_PROBEREQ); 2606554c0a3aSHans de Goede 2607554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2608554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2609554c0a3aSHans de Goede 2610554c0a3aSHans de Goede if (pssid) 26113f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen)); 2612554c0a3aSHans de Goede else 26133f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, 0, NULL, &(pattrib->pktlen)); 2614554c0a3aSHans de Goede 2615554c0a3aSHans de Goede get_rate_set(padapter, bssrate, &bssrate_len); 2616554c0a3aSHans de Goede 2617554c0a3aSHans de Goede if (bssrate_len > 8) { 2618c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen)); 261900f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); 2620554c0a3aSHans de Goede } else { 2621c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen)); 2622554c0a3aSHans de Goede } 2623554c0a3aSHans de Goede 2624554c0a3aSHans de Goede if (ch) 26258f6a9446SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_DS_PARAMS, 1, &ch, &pattrib->pktlen); 2626554c0a3aSHans de Goede 2627554c0a3aSHans de Goede if (append_wps) { 2628554c0a3aSHans de Goede /* add wps_ie for wps2.0 */ 2629554c0a3aSHans de Goede if (pmlmepriv->wps_probe_req_ie_len > 0 && pmlmepriv->wps_probe_req_ie) { 2630554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len); 2631554c0a3aSHans de Goede pframe += pmlmepriv->wps_probe_req_ie_len; 2632554c0a3aSHans de Goede pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len; 2633554c0a3aSHans de Goede } 2634554c0a3aSHans de Goede } 2635554c0a3aSHans de Goede 2636554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2637554c0a3aSHans de Goede 2638554c0a3aSHans de Goede if (wait_ack) { 2639554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 2640554c0a3aSHans de Goede } else { 2641554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2642554c0a3aSHans de Goede ret = _SUCCESS; 2643554c0a3aSHans de Goede } 2644554c0a3aSHans de Goede 2645554c0a3aSHans de Goede exit: 2646554c0a3aSHans de Goede return ret; 2647554c0a3aSHans de Goede } 2648554c0a3aSHans de Goede 2649554c0a3aSHans de Goede inline void issue_probereq(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da) 2650554c0a3aSHans de Goede { 2651554c0a3aSHans de Goede _issue_probereq(padapter, pssid, da, 0, 1, false); 2652554c0a3aSHans de Goede } 2653554c0a3aSHans de Goede 2654554c0a3aSHans de Goede int issue_probereq_ex(struct adapter *padapter, struct ndis_802_11_ssid *pssid, u8 *da, u8 ch, bool append_wps, 2655554c0a3aSHans de Goede int try_cnt, int wait_ms) 2656554c0a3aSHans de Goede { 2657554c0a3aSHans de Goede int ret; 2658554c0a3aSHans de Goede int i = 0; 2659554c0a3aSHans de Goede 2660554c0a3aSHans de Goede do { 26619cdb1928SSaiyam Doshi ret = _issue_probereq(padapter, pssid, da, ch, append_wps, 26629cdb1928SSaiyam Doshi wait_ms > 0); 2663554c0a3aSHans de Goede 2664554c0a3aSHans de Goede i++; 2665554c0a3aSHans de Goede 2666554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 2667554c0a3aSHans de Goede break; 2668554c0a3aSHans de Goede 2669554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 2670554c0a3aSHans de Goede msleep(wait_ms); 2671554c0a3aSHans de Goede 2672554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 2673554c0a3aSHans de Goede 2674554c0a3aSHans de Goede if (ret != _FAIL) { 2675554c0a3aSHans de Goede ret = _SUCCESS; 2676554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 2677554c0a3aSHans de Goede goto exit; 2678554c0a3aSHans de Goede #endif 2679554c0a3aSHans de Goede } 2680554c0a3aSHans de Goede 2681554c0a3aSHans de Goede exit: 2682554c0a3aSHans de Goede return ret; 2683554c0a3aSHans de Goede } 2684554c0a3aSHans de Goede 268568468503SAndreas Hellmich /* if psta == NULL, indicate we are station(client) now... */ 2686554c0a3aSHans de Goede void issue_auth(struct adapter *padapter, struct sta_info *psta, unsigned short status) 2687554c0a3aSHans de Goede { 2688554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2689554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2690554c0a3aSHans de Goede unsigned char *pframe; 2691554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2692554c0a3aSHans de Goede __le16 *fctrl; 2693554c0a3aSHans de Goede unsigned int val32; 2694554c0a3aSHans de Goede unsigned short val16; 2695554c0a3aSHans de Goede int use_shared_key = 0; 2696554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2697554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2698554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2699554c0a3aSHans de Goede __le16 le_tmp; 2700554c0a3aSHans de Goede 2701554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2702554c0a3aSHans de Goede if (pmgntframe == NULL) 2703554c0a3aSHans de Goede return; 2704554c0a3aSHans de Goede 2705554c0a3aSHans de Goede /* update attribute */ 2706554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2707554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2708554c0a3aSHans de Goede 2709554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2710554c0a3aSHans de Goede 2711554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2712554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2713554c0a3aSHans de Goede 2714554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2715554c0a3aSHans de Goede *(fctrl) = 0; 2716554c0a3aSHans de Goede 2717554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2718554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2719554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_AUTH); 2720554c0a3aSHans de Goede 2721554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2722554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2723554c0a3aSHans de Goede 2724554c0a3aSHans de Goede 2725554c0a3aSHans de Goede if (psta) { /* for AP mode */ 2726554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN); 2727554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 2728554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, myid(&(padapter->eeprompriv)), ETH_ALEN); 2729554c0a3aSHans de Goede 2730554c0a3aSHans de Goede /* setting auth algo number */ 2731554c0a3aSHans de Goede val16 = (u16)psta->authalg; 2732554c0a3aSHans de Goede 27336d75b504SRoss Schmidt if (status != WLAN_STATUS_SUCCESS) 2734554c0a3aSHans de Goede val16 = 0; 2735554c0a3aSHans de Goede 2736554c0a3aSHans de Goede if (val16) 2737554c0a3aSHans de Goede use_shared_key = 1; 2738554c0a3aSHans de Goede 2739554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 2740554c0a3aSHans de Goede 2741554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2742554c0a3aSHans de Goede 2743554c0a3aSHans de Goede /* setting auth seq number */ 2744554c0a3aSHans de Goede val16 = (u16)psta->auth_seq; 2745554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 2746554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2747554c0a3aSHans de Goede 2748554c0a3aSHans de Goede /* setting status code... */ 2749554c0a3aSHans de Goede val16 = status; 2750554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 2751554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2752554c0a3aSHans de Goede 2753554c0a3aSHans de Goede /* added challenging text... */ 2754554c0a3aSHans de Goede if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) 275538caee0aSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, psta->chg_txt, &(pattrib->pktlen)); 2756554c0a3aSHans de Goede 2757554c0a3aSHans de Goede } else { 2758554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); 2759554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&padapter->eeprompriv), ETH_ALEN); 2760554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN); 2761554c0a3aSHans de Goede 2762554c0a3aSHans de Goede /* setting auth algo number */ 2763554c0a3aSHans de Goede val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) ? 1 : 0;/* 0:OPEN System, 1:Shared key */ 2764554c0a3aSHans de Goede if (val16) { 2765554c0a3aSHans de Goede use_shared_key = 1; 2766554c0a3aSHans de Goede } 2767554c0a3aSHans de Goede le_tmp = cpu_to_le16(val16); 2768554c0a3aSHans de Goede 2769554c0a3aSHans de Goede /* setting IV for auth seq #3 */ 2770554c0a3aSHans de Goede if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { 2771554c0a3aSHans de Goede __le32 le_tmp32; 2772554c0a3aSHans de Goede 2773554c0a3aSHans de Goede val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30)); 2774554c0a3aSHans de Goede le_tmp32 = cpu_to_le32(val32); 2775554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&le_tmp32, &(pattrib->pktlen)); 2776554c0a3aSHans de Goede 2777554c0a3aSHans de Goede pattrib->iv_len = 4; 2778554c0a3aSHans de Goede } 2779554c0a3aSHans de Goede 2780554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2781554c0a3aSHans de Goede 2782554c0a3aSHans de Goede /* setting auth seq number */ 2783554c0a3aSHans de Goede le_tmp = cpu_to_le16(pmlmeinfo->auth_seq); 2784554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2785554c0a3aSHans de Goede 2786554c0a3aSHans de Goede 2787554c0a3aSHans de Goede /* setting status code... */ 2788554c0a3aSHans de Goede le_tmp = cpu_to_le16(status); 2789554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2790554c0a3aSHans de Goede 2791554c0a3aSHans de Goede /* then checking to see if sending challenging text... */ 2792554c0a3aSHans de Goede if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key == 1)) { 279338caee0aSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_CHALLENGE, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen)); 2794554c0a3aSHans de Goede 2795554c0a3aSHans de Goede SetPrivacy(fctrl); 2796554c0a3aSHans de Goede 2797554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 2798554c0a3aSHans de Goede 2799554c0a3aSHans de Goede pattrib->encrypt = _WEP40_; 2800554c0a3aSHans de Goede 2801554c0a3aSHans de Goede pattrib->icv_len = 4; 2802554c0a3aSHans de Goede 2803554c0a3aSHans de Goede pattrib->pktlen += pattrib->icv_len; 2804554c0a3aSHans de Goede 2805554c0a3aSHans de Goede } 2806554c0a3aSHans de Goede 2807554c0a3aSHans de Goede } 2808554c0a3aSHans de Goede 2809554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2810554c0a3aSHans de Goede 2811554c0a3aSHans de Goede rtw_wep_encrypt(padapter, (u8 *)pmgntframe); 2812554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2813554c0a3aSHans de Goede } 2814554c0a3aSHans de Goede 2815554c0a3aSHans de Goede 2816554c0a3aSHans de Goede void issue_asocrsp(struct adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type) 2817554c0a3aSHans de Goede { 2818554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2819554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2820554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2821554c0a3aSHans de Goede unsigned char *pbuf, *pframe; 2822554c0a3aSHans de Goede unsigned short val; 2823554c0a3aSHans de Goede __le16 *fctrl; 2824554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2825554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2826554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 2827554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2828554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); 2829554c0a3aSHans de Goede u8 *ie = pnetwork->IEs; 2830554c0a3aSHans de Goede __le16 lestatus, le_tmp; 2831554c0a3aSHans de Goede 2832554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2833554c0a3aSHans de Goede if (pmgntframe == NULL) 2834554c0a3aSHans de Goede return; 2835554c0a3aSHans de Goede 2836554c0a3aSHans de Goede /* update attribute */ 2837554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2838554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2839554c0a3aSHans de Goede 2840554c0a3aSHans de Goede 2841554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2842554c0a3aSHans de Goede 2843554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2844554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2845554c0a3aSHans de Goede 2846554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2847554c0a3aSHans de Goede *(fctrl) = 0; 2848554c0a3aSHans de Goede 2849554c0a3aSHans de Goede memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN); 2850554c0a3aSHans de Goede memcpy((void *)GetAddr2Ptr(pwlanhdr), myid(&(padapter->eeprompriv)), ETH_ALEN); 2851554c0a3aSHans de Goede memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 2852554c0a3aSHans de Goede 2853554c0a3aSHans de Goede 2854554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2855554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2856554c0a3aSHans de Goede if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP)) 2857554c0a3aSHans de Goede SetFrameSubType(pwlanhdr, pkt_type); 2858554c0a3aSHans de Goede else 2859554c0a3aSHans de Goede return; 2860554c0a3aSHans de Goede 2861554c0a3aSHans de Goede pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); 2862554c0a3aSHans de Goede pattrib->pktlen += pattrib->hdrlen; 2863554c0a3aSHans de Goede pframe += pattrib->hdrlen; 2864554c0a3aSHans de Goede 2865554c0a3aSHans de Goede /* capability */ 2866554c0a3aSHans de Goede val = *(unsigned short *)rtw_get_capability_from_ie(ie); 2867554c0a3aSHans de Goede 2868554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_, (unsigned char *)&val, &(pattrib->pktlen)); 2869554c0a3aSHans de Goede 2870554c0a3aSHans de Goede lestatus = cpu_to_le16(status); 2871554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&lestatus, &(pattrib->pktlen)); 2872554c0a3aSHans de Goede 2873554c0a3aSHans de Goede le_tmp = cpu_to_le16(pstat->aid | BIT(14) | BIT(15)); 2874554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 2875554c0a3aSHans de Goede 2876554c0a3aSHans de Goede if (pstat->bssratelen <= 8) { 2877c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen)); 2878554c0a3aSHans de Goede } else { 2879c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, pstat->bssrateset, &(pattrib->pktlen)); 288000f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen)); 2881554c0a3aSHans de Goede } 2882554c0a3aSHans de Goede 2883554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option)) { 2884554c0a3aSHans de Goede uint ie_len = 0; 2885554c0a3aSHans de Goede 2886554c0a3aSHans de Goede /* FILL HT CAP INFO IE */ 2887554c0a3aSHans de Goede /* p = hostapd_eid_ht_capabilities_info(hapd, p); */ 2888fc6a6528SRoss Schmidt pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_CAPABILITY, &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 /* FILL HT ADD INFO IE */ 2896554c0a3aSHans de Goede /* p = hostapd_eid_ht_operation(hapd, p); */ 2897332ec9dbSRoss Schmidt pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, WLAN_EID_HT_OPERATION, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_)); 2898554c0a3aSHans de Goede if (pbuf && ie_len > 0) { 2899554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 2900554c0a3aSHans de Goede pframe += (ie_len+2); 2901554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 2902554c0a3aSHans de Goede } 2903554c0a3aSHans de Goede 2904554c0a3aSHans de Goede } 2905554c0a3aSHans de Goede 2906554c0a3aSHans de Goede /* FILL WMM IE */ 2907554c0a3aSHans de Goede if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option)) { 2908554c0a3aSHans de Goede uint ie_len = 0; 2909554c0a3aSHans de Goede unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; 2910554c0a3aSHans de Goede 2911554c0a3aSHans de Goede for (pbuf = ie + _BEACON_IE_OFFSET_; ; pbuf += (ie_len + 2)) { 2912b05cc3a9SRoss Schmidt pbuf = rtw_get_ie(pbuf, WLAN_EID_VENDOR_SPECIFIC, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2))); 2913554c0a3aSHans de Goede if (pbuf && !memcmp(pbuf+2, WMM_PARA_IE, 6)) { 2914554c0a3aSHans de Goede memcpy(pframe, pbuf, ie_len+2); 2915554c0a3aSHans de Goede pframe += (ie_len+2); 2916554c0a3aSHans de Goede pattrib->pktlen += (ie_len+2); 2917554c0a3aSHans de Goede 2918554c0a3aSHans de Goede break; 2919554c0a3aSHans de Goede } 2920554c0a3aSHans de Goede 2921554c0a3aSHans de Goede if ((pbuf == NULL) || (ie_len == 0)) { 2922554c0a3aSHans de Goede break; 2923554c0a3aSHans de Goede } 2924554c0a3aSHans de Goede } 2925554c0a3aSHans de Goede 2926554c0a3aSHans de Goede } 2927554c0a3aSHans de Goede 2928554c0a3aSHans de Goede if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) { 2929b05cc3a9SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen)); 2930554c0a3aSHans de Goede } 2931554c0a3aSHans de Goede 2932554c0a3aSHans de Goede /* add WPS IE ie for wps 2.0 */ 2933554c0a3aSHans de Goede if (pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len > 0) { 2934554c0a3aSHans de Goede memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len); 2935554c0a3aSHans de Goede 2936554c0a3aSHans de Goede pframe += pmlmepriv->wps_assoc_resp_ie_len; 2937554c0a3aSHans de Goede pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len; 2938554c0a3aSHans de Goede } 2939554c0a3aSHans de Goede 2940554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 2941554c0a3aSHans de Goede 2942554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 2943554c0a3aSHans de Goede } 2944554c0a3aSHans de Goede 2945554c0a3aSHans de Goede void issue_assocreq(struct adapter *padapter) 2946554c0a3aSHans de Goede { 2947554c0a3aSHans de Goede int ret = _FAIL; 2948554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 2949554c0a3aSHans de Goede struct pkt_attrib *pattrib; 2950554c0a3aSHans de Goede unsigned char *pframe; 2951554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 2952554c0a3aSHans de Goede __le16 *fctrl; 2953554c0a3aSHans de Goede __le16 val16; 2954554c0a3aSHans de Goede unsigned int i, j, index = 0; 2955554c0a3aSHans de Goede unsigned char bssrate[NumRates], sta_bssrate[NumRates]; 2956554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 2957554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 2958554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 2959554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 2960554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 2961554c0a3aSHans de Goede int bssrate_len = 0, sta_bssrate_len = 0; 2962554c0a3aSHans de Goede u8 vs_ie_length = 0; 2963554c0a3aSHans de Goede 2964554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 2965554c0a3aSHans de Goede if (pmgntframe == NULL) 2966554c0a3aSHans de Goede goto exit; 2967554c0a3aSHans de Goede 2968554c0a3aSHans de Goede /* update attribute */ 2969554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 2970554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 2971554c0a3aSHans de Goede 2972554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 2973554c0a3aSHans de Goede 2974554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 2975554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 2976554c0a3aSHans de Goede 2977554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 2978554c0a3aSHans de Goede *(fctrl) = 0; 2979554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 2980554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 2981554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 2982554c0a3aSHans de Goede 2983554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 2984554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 2985554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ASSOCREQ); 2986554c0a3aSHans de Goede 2987554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 2988554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 2989554c0a3aSHans de Goede 2990554c0a3aSHans de Goede /* caps */ 2991554c0a3aSHans de Goede memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2); 2992554c0a3aSHans de Goede 2993554c0a3aSHans de Goede pframe += 2; 2994554c0a3aSHans de Goede pattrib->pktlen += 2; 2995554c0a3aSHans de Goede 2996554c0a3aSHans de Goede /* listen interval */ 2997554c0a3aSHans de Goede /* todo: listen interval for power saving */ 2998554c0a3aSHans de Goede val16 = cpu_to_le16(3); 2999554c0a3aSHans de Goede memcpy(pframe, (unsigned char *)&val16, 2); 3000554c0a3aSHans de Goede pframe += 2; 3001554c0a3aSHans de Goede pattrib->pktlen += 2; 3002554c0a3aSHans de Goede 3003554c0a3aSHans de Goede /* SSID */ 30043f15277bSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SSID, pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen)); 3005554c0a3aSHans de Goede 3006554c0a3aSHans de Goede /* supported rate & extended supported rate */ 3007554c0a3aSHans de Goede 3008554c0a3aSHans de Goede /* Check if the AP's supported rates are also supported by STA. */ 3009554c0a3aSHans de Goede get_rate_set(padapter, sta_bssrate, &sta_bssrate_len); 3010554c0a3aSHans de Goede 3011554c0a3aSHans de Goede if (pmlmeext->cur_channel == 14) /* for JAPAN, channel 14 can only uses B Mode(CCK) */ 3012554c0a3aSHans de Goede sta_bssrate_len = 4; 3013554c0a3aSHans de Goede 3014554c0a3aSHans de Goede 3015554c0a3aSHans de Goede /* for (i = 0; i < sta_bssrate_len; i++) { */ 3016554c0a3aSHans de Goede /* */ 3017554c0a3aSHans de Goede 3018554c0a3aSHans de Goede for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { 3019554c0a3aSHans de Goede if (pmlmeinfo->network.SupportedRates[i] == 0) 3020554c0a3aSHans de Goede break; 3021554c0a3aSHans de Goede } 3022554c0a3aSHans de Goede 3023554c0a3aSHans de Goede 3024554c0a3aSHans de Goede for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) { 3025554c0a3aSHans de Goede if (pmlmeinfo->network.SupportedRates[i] == 0) 3026554c0a3aSHans de Goede break; 3027554c0a3aSHans de Goede 3028554c0a3aSHans de Goede 3029554c0a3aSHans de Goede /* Check if the AP's supported rates are also supported by STA. */ 3030554c0a3aSHans de Goede for (j = 0; j < sta_bssrate_len; j++) { 3031554c0a3aSHans de Goede /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */ 3032554c0a3aSHans de Goede if ((pmlmeinfo->network.SupportedRates[i] | IEEE80211_BASIC_RATE_MASK) 3033709c8e49SFabio Aiuto == (sta_bssrate[j] | IEEE80211_BASIC_RATE_MASK)) 3034554c0a3aSHans de Goede break; 3035554c0a3aSHans de Goede } 3036554c0a3aSHans de Goede 3037709c8e49SFabio Aiuto if (j != sta_bssrate_len) 3038554c0a3aSHans de Goede /* the rate is supported by STA */ 3039554c0a3aSHans de Goede bssrate[index++] = pmlmeinfo->network.SupportedRates[i]; 3040554c0a3aSHans de Goede } 3041554c0a3aSHans de Goede 3042554c0a3aSHans de Goede bssrate_len = index; 3043554c0a3aSHans de Goede 3044554c0a3aSHans de Goede if (bssrate_len == 0) { 3045554c0a3aSHans de Goede rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf); 3046554c0a3aSHans de Goede rtw_free_xmitframe(pxmitpriv, pmgntframe); 3047554c0a3aSHans de Goede goto exit; /* don't connect to AP if no joint supported rate */ 3048554c0a3aSHans de Goede } 3049554c0a3aSHans de Goede 3050554c0a3aSHans de Goede 3051554c0a3aSHans de Goede if (bssrate_len > 8) { 3052c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, 8, bssrate, &(pattrib->pktlen)); 305300f0b682SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_SUPP_RATES, (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen)); 3054554c0a3aSHans de Goede } else 3055c34c45edSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_SUPP_RATES, bssrate_len, bssrate, &(pattrib->pktlen)); 3056554c0a3aSHans de Goede 3057554c0a3aSHans de Goede /* vendor specific IE, such as WPA, WMM, WPS */ 3058554c0a3aSHans de Goede for (i = sizeof(struct ndis_802_11_fix_ie); i < pmlmeinfo->network.IELength;) { 3059554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pmlmeinfo->network.IEs + i); 3060554c0a3aSHans de Goede 3061554c0a3aSHans de Goede switch (pIE->ElementID) { 3062b05cc3a9SRoss Schmidt case WLAN_EID_VENDOR_SPECIFIC: 3063554c0a3aSHans de Goede if ((!memcmp(pIE->data, RTW_WPA_OUI, 4)) || 3064554c0a3aSHans de Goede (!memcmp(pIE->data, WMM_OUI, 4)) || 3065554c0a3aSHans de Goede (!memcmp(pIE->data, WPS_OUI, 4))) { 3066554c0a3aSHans de Goede vs_ie_length = pIE->Length; 3067554c0a3aSHans de Goede if ((!padapter->registrypriv.wifi_spec) && (!memcmp(pIE->data, WPS_OUI, 4))) { 30684d17363dSAndreas Hellmich /* Commented by Kurt 20110629 30694d17363dSAndreas Hellmich * In some older APs, WPS handshake 30704d17363dSAndreas Hellmich * would be fail if we append vendor 30714d17363dSAndreas Hellmich * extensions information to AP 30724d17363dSAndreas Hellmich */ 3073554c0a3aSHans de Goede 3074554c0a3aSHans de Goede vs_ie_length = 14; 3075554c0a3aSHans de Goede } 3076554c0a3aSHans de Goede 3077b05cc3a9SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, vs_ie_length, pIE->data, &(pattrib->pktlen)); 3078554c0a3aSHans de Goede } 3079554c0a3aSHans de Goede break; 3080554c0a3aSHans de Goede 30813359e292SRoss Schmidt case WLAN_EID_RSN: 30823359e292SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_RSN, pIE->Length, pIE->data, &(pattrib->pktlen)); 3083554c0a3aSHans de Goede break; 3084fc6a6528SRoss Schmidt case WLAN_EID_HT_CAPABILITY: 30850ad02fa8SGeorgiana Chelu if (padapter->mlmepriv.htpriv.ht_option) { 3086554c0a3aSHans de Goede if (!(is_ap_in_tkip(padapter))) { 3087554c0a3aSHans de Goede memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element)); 3088fc6a6528SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_HT_CAPABILITY, pIE->Length, (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen)); 3089554c0a3aSHans de Goede } 3090554c0a3aSHans de Goede } 3091554c0a3aSHans de Goede break; 3092554c0a3aSHans de Goede 30935b45010fSRoss Schmidt case WLAN_EID_EXT_CAPABILITY: 30940ad02fa8SGeorgiana Chelu if (padapter->mlmepriv.htpriv.ht_option) 30955b45010fSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_EXT_CAPABILITY, pIE->Length, pIE->data, &(pattrib->pktlen)); 3096554c0a3aSHans de Goede break; 3097554c0a3aSHans de Goede default: 3098554c0a3aSHans de Goede break; 3099554c0a3aSHans de Goede } 3100554c0a3aSHans de Goede 3101554c0a3aSHans de Goede i += (pIE->Length + 2); 3102554c0a3aSHans de Goede } 3103554c0a3aSHans de Goede 3104554c0a3aSHans de Goede if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK) 3105b05cc3a9SRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_VENDOR_SPECIFIC, 6, REALTEK_96B_IE, &(pattrib->pktlen)); 3106554c0a3aSHans de Goede 3107554c0a3aSHans de Goede 3108554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3109554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3110554c0a3aSHans de Goede 3111554c0a3aSHans de Goede ret = _SUCCESS; 3112554c0a3aSHans de Goede 3113554c0a3aSHans de Goede exit: 3114554c0a3aSHans de Goede if (ret == _SUCCESS) 3115554c0a3aSHans de Goede rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen); 3116554c0a3aSHans de Goede else 3117554c0a3aSHans de Goede rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len); 3118554c0a3aSHans de Goede } 3119554c0a3aSHans de Goede 312068468503SAndreas Hellmich /* when wait_ack is true, this function should be called at process context */ 312142b3b621SAishwarya Pant static int _issue_nulldata(struct adapter *padapter, unsigned char *da, 312242b3b621SAishwarya Pant unsigned int power_mode, bool wait_ack) 3123554c0a3aSHans de Goede { 3124554c0a3aSHans de Goede int ret = _FAIL; 3125554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3126554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3127554c0a3aSHans de Goede unsigned char *pframe; 3128554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3129554c0a3aSHans de Goede __le16 *fctrl; 3130554c0a3aSHans de Goede struct xmit_priv *pxmitpriv; 3131554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 3132554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo; 3133554c0a3aSHans de Goede 3134554c0a3aSHans de Goede if (!padapter) 3135554c0a3aSHans de Goede goto exit; 3136554c0a3aSHans de Goede 3137554c0a3aSHans de Goede pxmitpriv = &(padapter->xmitpriv); 3138554c0a3aSHans de Goede pmlmeext = &(padapter->mlmeextpriv); 3139554c0a3aSHans de Goede pmlmeinfo = &(pmlmeext->mlmext_info); 3140554c0a3aSHans de Goede 3141554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3142554c0a3aSHans de Goede if (pmgntframe == NULL) 3143554c0a3aSHans de Goede goto exit; 3144554c0a3aSHans de Goede 3145554c0a3aSHans de Goede /* update attribute */ 3146554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3147554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3148554c0a3aSHans de Goede pattrib->retry_ctrl = false; 3149554c0a3aSHans de Goede 3150554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3151554c0a3aSHans de Goede 3152554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3153554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3154554c0a3aSHans de Goede 3155554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3156554c0a3aSHans de Goede *(fctrl) = 0; 3157554c0a3aSHans de Goede 3158554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) 3159554c0a3aSHans de Goede SetFrDs(fctrl); 3160554c0a3aSHans de Goede else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) 3161554c0a3aSHans de Goede SetToDs(fctrl); 3162554c0a3aSHans de Goede 3163554c0a3aSHans de Goede if (power_mode) 3164554c0a3aSHans de Goede SetPwrMgt(fctrl); 3165554c0a3aSHans de Goede 3166554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3167554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3168554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3169554c0a3aSHans de Goede 3170554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3171554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3172554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_DATA_NULL); 3173554c0a3aSHans de Goede 3174554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3175554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3176554c0a3aSHans de Goede 3177554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3178554c0a3aSHans de Goede 3179554c0a3aSHans de Goede if (wait_ack) { 3180554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3181554c0a3aSHans de Goede } else { 3182554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3183554c0a3aSHans de Goede ret = _SUCCESS; 3184554c0a3aSHans de Goede } 3185554c0a3aSHans de Goede 3186554c0a3aSHans de Goede exit: 3187554c0a3aSHans de Goede return ret; 3188554c0a3aSHans de Goede } 3189554c0a3aSHans de Goede 3190554c0a3aSHans de Goede /* 3191554c0a3aSHans de Goede * [IMPORTANT] Don't call this function in interrupt context 3192554c0a3aSHans de Goede * 319368468503SAndreas Hellmich * When wait_ms > 0, this function should be called at process context 3194554c0a3aSHans de Goede * da == NULL for station mode 3195554c0a3aSHans de Goede */ 3196554c0a3aSHans de Goede int issue_nulldata(struct adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms) 3197554c0a3aSHans de Goede { 3198554c0a3aSHans de Goede int ret; 3199554c0a3aSHans de Goede int i = 0; 3200554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3201554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3202554c0a3aSHans de Goede struct sta_info *psta; 3203554c0a3aSHans de Goede 3204554c0a3aSHans de Goede 320568468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 32065947e900SNishka Dasgupta if (!da) 3207554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3208554c0a3aSHans de Goede 3209554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, da); 3210554c0a3aSHans de Goede if (psta) { 3211554c0a3aSHans de Goede if (power_mode) 3212554c0a3aSHans de Goede rtw_hal_macid_sleep(padapter, psta->mac_id); 3213554c0a3aSHans de Goede else 3214554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 3215554c0a3aSHans de Goede } else { 3216554c0a3aSHans de Goede rtw_warn_on(1); 3217554c0a3aSHans de Goede } 3218554c0a3aSHans de Goede 3219554c0a3aSHans de Goede do { 32209cdb1928SSaiyam Doshi ret = _issue_nulldata(padapter, da, power_mode, wait_ms > 0); 3221554c0a3aSHans de Goede 3222554c0a3aSHans de Goede i++; 3223554c0a3aSHans de Goede 3224554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3225554c0a3aSHans de Goede break; 3226554c0a3aSHans de Goede 3227554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 3228554c0a3aSHans de Goede msleep(wait_ms); 3229554c0a3aSHans de Goede 3230554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3231554c0a3aSHans de Goede 3232554c0a3aSHans de Goede if (ret != _FAIL) { 3233554c0a3aSHans de Goede ret = _SUCCESS; 3234554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3235554c0a3aSHans de Goede goto exit; 3236554c0a3aSHans de Goede #endif 3237554c0a3aSHans de Goede } 3238554c0a3aSHans de Goede 3239554c0a3aSHans de Goede exit: 3240554c0a3aSHans de Goede return ret; 3241554c0a3aSHans de Goede } 3242554c0a3aSHans de Goede 3243554c0a3aSHans de Goede /* 3244554c0a3aSHans de Goede * [IMPORTANT] This function run in interrupt context 3245554c0a3aSHans de Goede * 3246554c0a3aSHans de Goede * The null data packet would be sent without power bit, 3247554c0a3aSHans de Goede * and not guarantee success. 3248554c0a3aSHans de Goede */ 3249554c0a3aSHans de Goede s32 issue_nulldata_in_interrupt(struct adapter *padapter, u8 *da) 3250554c0a3aSHans de Goede { 3251554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 3252554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo; 3253554c0a3aSHans de Goede 3254554c0a3aSHans de Goede 3255554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 3256554c0a3aSHans de Goede pmlmeinfo = &pmlmeext->mlmext_info; 3257554c0a3aSHans de Goede 325868468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 32595947e900SNishka Dasgupta if (!da) 3260554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3261554c0a3aSHans de Goede 326263ff599aSNishka Dasgupta return _issue_nulldata(padapter, da, 0, false); 3263554c0a3aSHans de Goede } 3264554c0a3aSHans de Goede 326568468503SAndreas Hellmich /* when wait_ack is true, this function should be called at process context */ 326642b3b621SAishwarya Pant static int _issue_qos_nulldata(struct adapter *padapter, unsigned char *da, 326742b3b621SAishwarya Pant u16 tid, bool wait_ack) 3268554c0a3aSHans de Goede { 3269554c0a3aSHans de Goede int ret = _FAIL; 3270554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3271554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3272554c0a3aSHans de Goede unsigned char *pframe; 3273554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3274554c0a3aSHans de Goede __le16 *fctrl; 3275554c0a3aSHans de Goede u16 *qc; 3276554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3277554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3278554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3279554c0a3aSHans de Goede 3280554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3281554c0a3aSHans de Goede if (pmgntframe == NULL) 3282554c0a3aSHans de Goede goto exit; 3283554c0a3aSHans de Goede 3284554c0a3aSHans de Goede /* update attribute */ 3285554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3286554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3287554c0a3aSHans de Goede 3288554c0a3aSHans de Goede pattrib->hdrlen += 2; 3289554c0a3aSHans de Goede pattrib->qos_en = true; 3290554c0a3aSHans de Goede pattrib->eosp = 1; 3291554c0a3aSHans de Goede pattrib->ack_policy = 0; 3292554c0a3aSHans de Goede pattrib->mdata = 0; 3293554c0a3aSHans de Goede 3294554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3295554c0a3aSHans de Goede 3296554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3297554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3298554c0a3aSHans de Goede 3299554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3300554c0a3aSHans de Goede *(fctrl) = 0; 3301554c0a3aSHans de Goede 3302554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) 3303554c0a3aSHans de Goede SetFrDs(fctrl); 3304554c0a3aSHans de Goede else if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) 3305554c0a3aSHans de Goede SetToDs(fctrl); 3306554c0a3aSHans de Goede 3307554c0a3aSHans de Goede if (pattrib->mdata) 3308554c0a3aSHans de Goede SetMData(fctrl); 3309554c0a3aSHans de Goede 3310554c0a3aSHans de Goede qc = (unsigned short *)(pframe + pattrib->hdrlen - 2); 3311554c0a3aSHans de Goede 3312554c0a3aSHans de Goede SetPriority(qc, tid); 3313554c0a3aSHans de Goede 3314554c0a3aSHans de Goede SetEOSP(qc, pattrib->eosp); 3315554c0a3aSHans de Goede 3316554c0a3aSHans de Goede SetAckpolicy(qc, pattrib->ack_policy); 3317554c0a3aSHans de Goede 3318554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3319554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3320554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3321554c0a3aSHans de Goede 3322554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3323554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3324554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_QOS_DATA_NULL); 3325554c0a3aSHans de Goede 3326554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_qos_hdr); 3327554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_qos_hdr); 3328554c0a3aSHans de Goede 3329554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3330554c0a3aSHans de Goede 3331554c0a3aSHans de Goede if (wait_ack) { 3332554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3333554c0a3aSHans de Goede } else { 3334554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3335554c0a3aSHans de Goede ret = _SUCCESS; 3336554c0a3aSHans de Goede } 3337554c0a3aSHans de Goede 3338554c0a3aSHans de Goede exit: 3339554c0a3aSHans de Goede return ret; 3340554c0a3aSHans de Goede } 3341554c0a3aSHans de Goede 334268468503SAndreas Hellmich /* when wait_ms >0 , this function should be called at process context */ 3343554c0a3aSHans de Goede /* da == NULL for station mode */ 3344554c0a3aSHans de Goede int issue_qos_nulldata(struct adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms) 3345554c0a3aSHans de Goede { 3346554c0a3aSHans de Goede int ret; 3347554c0a3aSHans de Goede int i = 0; 3348554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3349554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3350554c0a3aSHans de Goede 335168468503SAndreas Hellmich /* da == NULL, assume it's null data for sta to ap*/ 33525947e900SNishka Dasgupta if (!da) 3353554c0a3aSHans de Goede da = get_my_bssid(&(pmlmeinfo->network)); 3354554c0a3aSHans de Goede 3355554c0a3aSHans de Goede do { 33569cdb1928SSaiyam Doshi ret = _issue_qos_nulldata(padapter, da, tid, wait_ms > 0); 3357554c0a3aSHans de Goede 3358554c0a3aSHans de Goede i++; 3359554c0a3aSHans de Goede 3360554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3361554c0a3aSHans de Goede break; 3362554c0a3aSHans de Goede 3363554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 3364554c0a3aSHans de Goede msleep(wait_ms); 3365554c0a3aSHans de Goede 3366554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3367554c0a3aSHans de Goede 3368554c0a3aSHans de Goede if (ret != _FAIL) { 3369554c0a3aSHans de Goede ret = _SUCCESS; 3370554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3371554c0a3aSHans de Goede goto exit; 3372554c0a3aSHans de Goede #endif 3373554c0a3aSHans de Goede } 3374554c0a3aSHans de Goede 3375554c0a3aSHans de Goede exit: 3376554c0a3aSHans de Goede return ret; 3377554c0a3aSHans de Goede } 3378554c0a3aSHans de Goede 337942b3b621SAishwarya Pant static int _issue_deauth(struct adapter *padapter, unsigned char *da, 338042b3b621SAishwarya Pant unsigned short reason, bool wait_ack) 3381554c0a3aSHans de Goede { 3382554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3383554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3384554c0a3aSHans de Goede unsigned char *pframe; 3385554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3386554c0a3aSHans de Goede __le16 *fctrl; 3387554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3388554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3389554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3390554c0a3aSHans de Goede int ret = _FAIL; 3391554c0a3aSHans de Goede __le16 le_tmp; 3392554c0a3aSHans de Goede 3393554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3394554c0a3aSHans de Goede if (pmgntframe == NULL) { 3395554c0a3aSHans de Goede goto exit; 3396554c0a3aSHans de Goede } 3397554c0a3aSHans de Goede 3398554c0a3aSHans de Goede /* update attribute */ 3399554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3400554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3401554c0a3aSHans de Goede pattrib->retry_ctrl = false; 3402554c0a3aSHans de Goede 3403554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3404554c0a3aSHans de Goede 3405554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3406554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3407554c0a3aSHans de Goede 3408554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3409554c0a3aSHans de Goede *(fctrl) = 0; 3410554c0a3aSHans de Goede 3411554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, da, ETH_ALEN); 3412554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3413554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3414554c0a3aSHans de Goede 3415554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3416554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3417554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_DEAUTH); 3418554c0a3aSHans de Goede 3419554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3420554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3421554c0a3aSHans de Goede 3422554c0a3aSHans de Goede le_tmp = cpu_to_le16(reason); 3423554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_, (unsigned char *)&le_tmp, &(pattrib->pktlen)); 3424554c0a3aSHans de Goede 3425554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3426554c0a3aSHans de Goede 3427554c0a3aSHans de Goede 3428554c0a3aSHans de Goede if (wait_ack) { 3429554c0a3aSHans de Goede ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe); 3430554c0a3aSHans de Goede } else { 3431554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3432554c0a3aSHans de Goede ret = _SUCCESS; 3433554c0a3aSHans de Goede } 3434554c0a3aSHans de Goede 3435554c0a3aSHans de Goede exit: 3436554c0a3aSHans de Goede return ret; 3437554c0a3aSHans de Goede } 3438554c0a3aSHans de Goede 3439554c0a3aSHans de Goede int issue_deauth(struct adapter *padapter, unsigned char *da, unsigned short reason) 3440554c0a3aSHans de Goede { 3441554c0a3aSHans de Goede return _issue_deauth(padapter, da, reason, false); 3442554c0a3aSHans de Goede } 3443554c0a3aSHans de Goede 3444554c0a3aSHans de Goede int issue_deauth_ex(struct adapter *padapter, u8 *da, unsigned short reason, int try_cnt, 3445554c0a3aSHans de Goede int wait_ms) 3446554c0a3aSHans de Goede { 3447554c0a3aSHans de Goede int ret; 3448554c0a3aSHans de Goede int i = 0; 3449554c0a3aSHans de Goede 3450554c0a3aSHans de Goede do { 34519cdb1928SSaiyam Doshi ret = _issue_deauth(padapter, da, reason, wait_ms > 0); 3452554c0a3aSHans de Goede 3453554c0a3aSHans de Goede i++; 3454554c0a3aSHans de Goede 3455554c0a3aSHans de Goede if (padapter->bDriverStopped || padapter->bSurpriseRemoved) 3456554c0a3aSHans de Goede break; 3457554c0a3aSHans de Goede 3458554c0a3aSHans de Goede if (i < try_cnt && wait_ms > 0 && ret == _FAIL) 34591c8cb89eSJia-Ju Bai mdelay(wait_ms); 3460554c0a3aSHans de Goede 3461554c0a3aSHans de Goede } while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0))); 3462554c0a3aSHans de Goede 3463554c0a3aSHans de Goede if (ret != _FAIL) { 3464554c0a3aSHans de Goede ret = _SUCCESS; 3465554c0a3aSHans de Goede #ifndef DBG_XMIT_ACK 3466554c0a3aSHans de Goede goto exit; 3467554c0a3aSHans de Goede #endif 3468554c0a3aSHans de Goede } 3469554c0a3aSHans de Goede 3470554c0a3aSHans de Goede exit: 3471554c0a3aSHans de Goede return ret; 3472554c0a3aSHans de Goede } 3473554c0a3aSHans de Goede 3474554c0a3aSHans de Goede void issue_action_SA_Query(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid) 3475554c0a3aSHans de Goede { 3476554c0a3aSHans de Goede u8 category = RTW_WLAN_CATEGORY_SA_QUERY; 3477554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3478554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3479554c0a3aSHans de Goede u8 *pframe; 3480554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3481554c0a3aSHans de Goede __le16 *fctrl; 3482554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3483554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3484554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3485554c0a3aSHans de Goede __le16 le_tmp; 3486554c0a3aSHans de Goede 3487554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3488e427bdd8SFabio Aiuto if (!pmgntframe) 3489554c0a3aSHans de Goede return; 3490554c0a3aSHans de Goede 3491554c0a3aSHans de Goede /* update attribute */ 3492554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3493554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3494554c0a3aSHans de Goede 3495554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3496554c0a3aSHans de Goede 3497554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3498554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3499554c0a3aSHans de Goede 3500554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3501554c0a3aSHans de Goede *(fctrl) = 0; 3502554c0a3aSHans de Goede 3503554c0a3aSHans de Goede if (raddr) 3504554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); 3505554c0a3aSHans de Goede else 3506554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3507554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3508554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3509554c0a3aSHans de Goede 3510554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3511554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3512554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 3513554c0a3aSHans de Goede 3514554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3515554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3516554c0a3aSHans de Goede 3517554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen); 3518554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen); 3519554c0a3aSHans de Goede 3520554c0a3aSHans de Goede switch (action) { 3521554c0a3aSHans de Goede case 0: /* SA Query req */ 3522554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen); 3523554c0a3aSHans de Goede pmlmeext->sa_query_seq++; 3524554c0a3aSHans de Goede /* send sa query request to AP, AP should reply sa query response in 1 second */ 3525554c0a3aSHans de Goede set_sa_query_timer(pmlmeext, 1000); 3526554c0a3aSHans de Goede break; 3527554c0a3aSHans de Goede 3528554c0a3aSHans de Goede case 1: /* SA Query rsp */ 3529554c0a3aSHans de Goede le_tmp = cpu_to_le16(tid); 3530554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&le_tmp, &pattrib->pktlen); 3531554c0a3aSHans de Goede break; 3532554c0a3aSHans de Goede default: 3533554c0a3aSHans de Goede break; 3534554c0a3aSHans de Goede } 3535554c0a3aSHans de Goede 3536554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3537554c0a3aSHans de Goede 3538554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3539554c0a3aSHans de Goede } 3540554c0a3aSHans de Goede 3541554c0a3aSHans de Goede void issue_action_BA(struct adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short status) 3542554c0a3aSHans de Goede { 3543554c0a3aSHans de Goede u8 category = RTW_WLAN_CATEGORY_BACK; 3544554c0a3aSHans de Goede u16 start_seq; 3545554c0a3aSHans de Goede u16 BA_para_set; 3546554c0a3aSHans de Goede u16 reason_code; 3547554c0a3aSHans de Goede u16 BA_timeout_value; 3548554c0a3aSHans de Goede u16 BA_starting_seqctrl = 0; 354998b32c71SRoss Schmidt enum ieee80211_max_ampdu_length_exp max_rx_ampdu_factor; 3550554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3551554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3552554c0a3aSHans de Goede u8 *pframe; 3553554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3554554c0a3aSHans de Goede __le16 *fctrl; 3555554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3556554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3557554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3558554c0a3aSHans de Goede struct sta_info *psta; 3559554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 3560554c0a3aSHans de Goede struct registry_priv *pregpriv = &padapter->registrypriv; 3561554c0a3aSHans de Goede __le16 le_tmp; 3562554c0a3aSHans de Goede 3563554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 356441452327SVatsala Narang if (!pmgntframe) 3565554c0a3aSHans de Goede return; 3566554c0a3aSHans de Goede 3567554c0a3aSHans de Goede /* update attribute */ 3568554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3569554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3570554c0a3aSHans de Goede 3571554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3572554c0a3aSHans de Goede 3573554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3574554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3575554c0a3aSHans de Goede 3576554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3577554c0a3aSHans de Goede *(fctrl) = 0; 3578554c0a3aSHans de Goede 3579554c0a3aSHans de Goede /* memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); */ 3580554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); 3581554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3582554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3583554c0a3aSHans de Goede 3584554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3585554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3586554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 3587554c0a3aSHans de Goede 3588554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3589554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3590554c0a3aSHans de Goede 3591554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); 3592554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); 3593554c0a3aSHans de Goede 3594554c0a3aSHans de Goede if (category == 3) { 3595554c0a3aSHans de Goede switch (action) { 3596554c0a3aSHans de Goede case 0: /* ADDBA req */ 3597554c0a3aSHans de Goede do { 3598554c0a3aSHans de Goede pmlmeinfo->dialogToken++; 3599554c0a3aSHans de Goede } while (pmlmeinfo->dialogToken == 0); 3600554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen)); 3601554c0a3aSHans de Goede 3602d312a47fSNishka Dasgupta if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter)) { 3603554c0a3aSHans de Goede /* A-MSDU NOT Supported */ 3604554c0a3aSHans de Goede BA_para_set = 0; 3605554c0a3aSHans de Goede /* immediate Block Ack */ 3606f36fa2d9SPayal Kshirsagar BA_para_set |= BIT(1) & IEEE80211_ADDBA_PARAM_POLICY_MASK; 3607554c0a3aSHans de Goede /* TID */ 3608554c0a3aSHans de Goede BA_para_set |= (status << 2) & IEEE80211_ADDBA_PARAM_TID_MASK; 3609554c0a3aSHans de Goede /* max buffer size is 8 MSDU */ 3610b3ae8af6SRoss Schmidt BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3611554c0a3aSHans de Goede } else { 3612554c0a3aSHans de Goede BA_para_set = (0x1002 | ((status & 0xf) << 2)); /* immediate ack & 64 buffer size */ 3613554c0a3aSHans de Goede } 3614554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 3615554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3616554c0a3aSHans de Goede 3617554c0a3aSHans de Goede BA_timeout_value = 5000;/* 5ms */ 3618554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_timeout_value); 3619554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3620554c0a3aSHans de Goede 3621554c0a3aSHans de Goede /* if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL) */ 3622554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, raddr); 362334557e23SIzabela Bakollari if (psta) { 3624554c0a3aSHans de Goede start_seq = (psta->sta_xmitpriv.txseq_tid[status & 0x07]&0xfff) + 1; 3625554c0a3aSHans de Goede 3626554c0a3aSHans de Goede psta->BA_starting_seqctrl[status & 0x07] = start_seq; 3627554c0a3aSHans de Goede 3628554c0a3aSHans de Goede BA_starting_seqctrl = start_seq << 4; 3629554c0a3aSHans de Goede } 3630554c0a3aSHans de Goede 3631554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_starting_seqctrl); 3632554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3633554c0a3aSHans de Goede break; 3634554c0a3aSHans de Goede 3635554c0a3aSHans de Goede case 1: /* ADDBA rsp */ 3636554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen)); 3637554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen)); 3638554c0a3aSHans de Goede if (padapter->driver_rx_ampdu_factor != 0xFF) 3639554c0a3aSHans de Goede max_rx_ampdu_factor = 364098b32c71SRoss Schmidt (enum ieee80211_max_ampdu_length_exp)padapter->driver_rx_ampdu_factor; 3641554c0a3aSHans de Goede else 3642554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, 3643554c0a3aSHans de Goede HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); 3644554c0a3aSHans de Goede 364598b32c71SRoss Schmidt if (IEEE80211_HT_MAX_AMPDU_64K == max_rx_ampdu_factor) 3646554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */ 364798b32c71SRoss Schmidt else if (IEEE80211_HT_MAX_AMPDU_32K == max_rx_ampdu_factor) 3648554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0800); /* 32 buffer size */ 364998b32c71SRoss Schmidt else if (IEEE80211_HT_MAX_AMPDU_16K == max_rx_ampdu_factor) 3650554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0400); /* 16 buffer size */ 365198b32c71SRoss Schmidt else if (IEEE80211_HT_MAX_AMPDU_8K == max_rx_ampdu_factor) 3652554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x0200); /* 8 buffer size */ 3653554c0a3aSHans de Goede else 3654554c0a3aSHans de Goede BA_para_set = ((le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set) & 0x3f) | 0x1000); /* 64 buffer size */ 3655554c0a3aSHans de Goede 3656d312a47fSNishka Dasgupta if (hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter) && 3657554c0a3aSHans de Goede padapter->driver_rx_ampdu_factor == 0xFF) { 3658554c0a3aSHans de Goede /* max buffer size is 8 MSDU */ 3659b3ae8af6SRoss Schmidt BA_para_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3660b3ae8af6SRoss Schmidt BA_para_set |= (8 << 6) & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; 3661554c0a3aSHans de Goede } 3662554c0a3aSHans de Goede 3663554c0a3aSHans de Goede if (pregpriv->ampdu_amsdu == 0)/* disabled */ 3664554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set & ~BIT(0)); 3665554c0a3aSHans de Goede else if (pregpriv->ampdu_amsdu == 1)/* enabled */ 3666554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set | BIT(0)); 3667554c0a3aSHans de Goede else /* auto */ 3668554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 3669554c0a3aSHans de Goede 3670554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3671554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen)); 3672554c0a3aSHans de Goede break; 3673554c0a3aSHans de Goede case 2:/* DELBA */ 3674554c0a3aSHans de Goede BA_para_set = (status & 0x1F) << 3; 3675554c0a3aSHans de Goede le_tmp = cpu_to_le16(BA_para_set); 3676554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3677554c0a3aSHans de Goede 3678554c0a3aSHans de Goede reason_code = 37; 3679554c0a3aSHans de Goede le_tmp = cpu_to_le16(reason_code); 3680554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(le_tmp)), &(pattrib->pktlen)); 3681554c0a3aSHans de Goede break; 3682554c0a3aSHans de Goede default: 3683554c0a3aSHans de Goede break; 3684554c0a3aSHans de Goede } 3685554c0a3aSHans de Goede } 3686554c0a3aSHans de Goede 3687554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3688554c0a3aSHans de Goede 3689554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3690554c0a3aSHans de Goede } 3691554c0a3aSHans de Goede 3692554c0a3aSHans de Goede static void issue_action_BSSCoexistPacket(struct adapter *padapter) 3693554c0a3aSHans de Goede { 3694554c0a3aSHans de Goede struct list_head *plist, *phead; 3695554c0a3aSHans de Goede unsigned char category, action; 3696554c0a3aSHans de Goede struct xmit_frame *pmgntframe; 3697554c0a3aSHans de Goede struct pkt_attrib *pattrib; 3698554c0a3aSHans de Goede unsigned char *pframe; 3699554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 3700554c0a3aSHans de Goede __le16 *fctrl; 3701554c0a3aSHans de Goede struct wlan_network *pnetwork = NULL; 3702554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 3703554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 3704554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 3705554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3706554c0a3aSHans de Goede struct __queue *queue = &(pmlmepriv->scanned_queue); 3707554c0a3aSHans de Goede u8 InfoContent[16] = {0}; 3708554c0a3aSHans de Goede u8 ICS[8][15]; 3709554c0a3aSHans de Goede 3710554c0a3aSHans de Goede if ((pmlmepriv->num_FortyMHzIntolerant == 0) || (pmlmepriv->num_sta_no_ht == 0)) 3711554c0a3aSHans de Goede return; 3712554c0a3aSHans de Goede 3713554c0a3aSHans de Goede if (true == pmlmeinfo->bwmode_updated) 3714554c0a3aSHans de Goede return; 3715554c0a3aSHans de Goede 3716554c0a3aSHans de Goede category = RTW_WLAN_CATEGORY_PUBLIC; 3717554c0a3aSHans de Goede action = ACT_PUBLIC_BSSCOEXIST; 3718554c0a3aSHans de Goede 3719554c0a3aSHans de Goede pmgntframe = alloc_mgtxmitframe(pxmitpriv); 3720554c0a3aSHans de Goede if (pmgntframe == NULL) { 3721554c0a3aSHans de Goede return; 3722554c0a3aSHans de Goede } 3723554c0a3aSHans de Goede 3724554c0a3aSHans de Goede /* update attribute */ 3725554c0a3aSHans de Goede pattrib = &pmgntframe->attrib; 3726554c0a3aSHans de Goede update_mgntframe_attrib(padapter, pattrib); 3727554c0a3aSHans de Goede 3728554c0a3aSHans de Goede memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET); 3729554c0a3aSHans de Goede 3730554c0a3aSHans de Goede pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; 3731554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 3732554c0a3aSHans de Goede 3733554c0a3aSHans de Goede fctrl = &(pwlanhdr->frame_control); 3734554c0a3aSHans de Goede *(fctrl) = 0; 3735554c0a3aSHans de Goede 3736554c0a3aSHans de Goede memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3737554c0a3aSHans de Goede memcpy(pwlanhdr->addr2, myid(&(padapter->eeprompriv)), ETH_ALEN); 3738554c0a3aSHans de Goede memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); 3739554c0a3aSHans de Goede 3740554c0a3aSHans de Goede SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq); 3741554c0a3aSHans de Goede pmlmeext->mgnt_seq++; 3742554c0a3aSHans de Goede SetFrameSubType(pframe, WIFI_ACTION); 3743554c0a3aSHans de Goede 3744554c0a3aSHans de Goede pframe += sizeof(struct ieee80211_hdr_3addr); 3745554c0a3aSHans de Goede pattrib->pktlen = sizeof(struct ieee80211_hdr_3addr); 3746554c0a3aSHans de Goede 3747554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen)); 3748554c0a3aSHans de Goede pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen)); 3749554c0a3aSHans de Goede 3750554c0a3aSHans de Goede 3751554c0a3aSHans de Goede /* */ 3752554c0a3aSHans de Goede if (pmlmepriv->num_FortyMHzIntolerant > 0) { 3753554c0a3aSHans de Goede u8 iedata = 0; 3754554c0a3aSHans de Goede 3755554c0a3aSHans de Goede iedata |= BIT(2);/* 20 MHz BSS Width Request */ 3756554c0a3aSHans de Goede 37579b5d8c1fSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_BSS_COEX_2040, 1, &iedata, &(pattrib->pktlen)); 3758554c0a3aSHans de Goede 3759554c0a3aSHans de Goede } 3760554c0a3aSHans de Goede 3761554c0a3aSHans de Goede 3762554c0a3aSHans de Goede /* */ 3763554c0a3aSHans de Goede memset(ICS, 0, sizeof(ICS)); 3764554c0a3aSHans de Goede if (pmlmepriv->num_sta_no_ht > 0) { 3765554c0a3aSHans de Goede int i; 3766554c0a3aSHans de Goede 3767554c0a3aSHans de Goede spin_lock_bh(&(pmlmepriv->scanned_queue.lock)); 3768554c0a3aSHans de Goede 3769554c0a3aSHans de Goede phead = get_list_head(queue); 3770554c0a3aSHans de Goede plist = get_next(phead); 3771554c0a3aSHans de Goede 3772554c0a3aSHans de Goede while (1) { 3773554c0a3aSHans de Goede int len; 3774554c0a3aSHans de Goede u8 *p; 3775554c0a3aSHans de Goede struct wlan_bssid_ex *pbss_network; 3776554c0a3aSHans de Goede 3777554c0a3aSHans de Goede if (phead == plist) 3778554c0a3aSHans de Goede break; 3779554c0a3aSHans de Goede 378019cf9d7aSRoss Schmidt pnetwork = container_of(plist, struct wlan_network, list); 3781554c0a3aSHans de Goede 3782554c0a3aSHans de Goede plist = get_next(plist); 3783554c0a3aSHans de Goede 3784554c0a3aSHans de Goede pbss_network = (struct wlan_bssid_ex *)&pnetwork->network; 3785554c0a3aSHans de Goede 3786fc6a6528SRoss Schmidt p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, WLAN_EID_HT_CAPABILITY, &len, pbss_network->IELength - _FIXED_IE_LENGTH_); 3787554c0a3aSHans de Goede if ((p == NULL) || (len == 0)) {/* non-HT */ 3788554c0a3aSHans de Goede 3789554c0a3aSHans de Goede if ((pbss_network->Configuration.DSConfig <= 0) || (pbss_network->Configuration.DSConfig > 14)) 3790554c0a3aSHans de Goede continue; 3791554c0a3aSHans de Goede 3792554c0a3aSHans de Goede ICS[0][pbss_network->Configuration.DSConfig] = 1; 3793554c0a3aSHans de Goede 3794554c0a3aSHans de Goede if (ICS[0][0] == 0) 3795554c0a3aSHans de Goede ICS[0][0] = 1; 3796554c0a3aSHans de Goede } 3797554c0a3aSHans de Goede 3798554c0a3aSHans de Goede } 3799554c0a3aSHans de Goede 3800554c0a3aSHans de Goede spin_unlock_bh(&(pmlmepriv->scanned_queue.lock)); 3801554c0a3aSHans de Goede 3802554c0a3aSHans de Goede 3803554c0a3aSHans de Goede for (i = 0; i < 8; i++) { 3804554c0a3aSHans de Goede if (ICS[i][0] == 1) { 3805554c0a3aSHans de Goede int j, k = 0; 3806554c0a3aSHans de Goede 3807554c0a3aSHans de Goede InfoContent[k] = i; 3808554c0a3aSHans de Goede /* SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent, i); */ 3809554c0a3aSHans de Goede k++; 3810554c0a3aSHans de Goede 3811554c0a3aSHans de Goede for (j = 1; j <= 14; j++) { 3812554c0a3aSHans de Goede if (ICS[i][j] == 1) { 3813554c0a3aSHans de Goede if (k < 16) { 3814554c0a3aSHans de Goede InfoContent[k] = j; /* channel number */ 3815554c0a3aSHans de Goede /* SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j); */ 3816554c0a3aSHans de Goede k++; 3817554c0a3aSHans de Goede } 3818554c0a3aSHans de Goede } 3819554c0a3aSHans de Goede } 3820554c0a3aSHans de Goede 3821d7ca2c3dSRoss Schmidt pframe = rtw_set_ie(pframe, WLAN_EID_BSS_INTOLERANT_CHL_REPORT, k, InfoContent, &(pattrib->pktlen)); 3822554c0a3aSHans de Goede 3823554c0a3aSHans de Goede } 3824554c0a3aSHans de Goede 3825554c0a3aSHans de Goede } 3826554c0a3aSHans de Goede 3827554c0a3aSHans de Goede 3828554c0a3aSHans de Goede } 3829554c0a3aSHans de Goede 3830554c0a3aSHans de Goede 3831554c0a3aSHans de Goede pattrib->last_txcmdsz = pattrib->pktlen; 3832554c0a3aSHans de Goede 3833554c0a3aSHans de Goede dump_mgntframe(padapter, pmgntframe); 3834554c0a3aSHans de Goede } 3835554c0a3aSHans de Goede 3836554c0a3aSHans de Goede unsigned int send_delba(struct adapter *padapter, u8 initiator, u8 *addr) 3837554c0a3aSHans de Goede { 3838554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 3839554c0a3aSHans de Goede struct sta_info *psta = NULL; 3840554c0a3aSHans de Goede /* struct recv_reorder_ctrl *preorder_ctrl; */ 3841554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 3842554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3843554c0a3aSHans de Goede u16 tid; 3844554c0a3aSHans de Goede 3845554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE) 3846554c0a3aSHans de Goede if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) 3847554c0a3aSHans de Goede return _SUCCESS; 3848554c0a3aSHans de Goede 3849554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, addr); 3850554c0a3aSHans de Goede if (psta == NULL) 3851554c0a3aSHans de Goede return _SUCCESS; 3852554c0a3aSHans de Goede 3853554c0a3aSHans de Goede if (initiator == 0) {/* recipient */ 3854554c0a3aSHans de Goede for (tid = 0; tid < MAXTID; tid++) { 38550ad02fa8SGeorgiana Chelu if (psta->recvreorder_ctrl[tid].enable) { 3856f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F)); 3857554c0a3aSHans de Goede psta->recvreorder_ctrl[tid].enable = false; 3858554c0a3aSHans de Goede psta->recvreorder_ctrl[tid].indicate_seq = 0xffff; 3859554c0a3aSHans de Goede } 3860554c0a3aSHans de Goede } 3861554c0a3aSHans de Goede } else if (initiator == 1) {/* originator */ 3862554c0a3aSHans de Goede for (tid = 0; tid < MAXTID; tid++) { 3863554c0a3aSHans de Goede if (psta->htpriv.agg_enable_bitmap & BIT(tid)) { 3864f4acd33cSRoss Schmidt issue_action_BA(padapter, addr, WLAN_ACTION_DELBA, (((tid << 1) | initiator)&0x1F)); 3865554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap &= ~BIT(tid); 3866554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(tid); 3867554c0a3aSHans de Goede 3868554c0a3aSHans de Goede } 3869554c0a3aSHans de Goede } 3870554c0a3aSHans de Goede } 3871554c0a3aSHans de Goede 3872554c0a3aSHans de Goede return _SUCCESS; 3873554c0a3aSHans de Goede 3874554c0a3aSHans de Goede } 3875554c0a3aSHans de Goede 3876554c0a3aSHans de Goede unsigned int send_beacon(struct adapter *padapter) 3877554c0a3aSHans de Goede { 3878554c0a3aSHans de Goede u8 bxmitok = false; 3879554c0a3aSHans de Goede int issue = 0; 3880554c0a3aSHans de Goede int poll = 0; 3881554c0a3aSHans de Goede 3882554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL); 3883554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL); 3884554c0a3aSHans de Goede do { 3885554c0a3aSHans de Goede issue_beacon(padapter, 100); 3886554c0a3aSHans de Goede issue++; 3887554c0a3aSHans de Goede do { 3888c22da34aSThomas Avery cond_resched(); 3889554c0a3aSHans de Goede rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok)); 3890554c0a3aSHans de Goede poll++; 3891554c0a3aSHans de Goede } while ((poll%10) != 0 && false == bxmitok && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 3892554c0a3aSHans de Goede 3893554c0a3aSHans de Goede } while (false == bxmitok && issue < 100 && !padapter->bSurpriseRemoved && !padapter->bDriverStopped); 3894554c0a3aSHans de Goede 3895554c0a3aSHans de Goede if (padapter->bSurpriseRemoved || padapter->bDriverStopped) { 3896554c0a3aSHans de Goede return _FAIL; 3897554c0a3aSHans de Goede } 3898554c0a3aSHans de Goede 3899554c0a3aSHans de Goede 3900e427bdd8SFabio Aiuto if (!bxmitok) 3901554c0a3aSHans de Goede return _FAIL; 3902709c8e49SFabio Aiuto else 3903554c0a3aSHans de Goede return _SUCCESS; 3904554c0a3aSHans de Goede } 3905554c0a3aSHans de Goede 3906554c0a3aSHans de Goede /**************************************************************************** 3907554c0a3aSHans de Goede 390868468503SAndreas Hellmich Following are some utility functions for WiFi MLME 3909554c0a3aSHans de Goede 3910554c0a3aSHans de Goede *****************************************************************************/ 3911554c0a3aSHans de Goede 3912554c0a3aSHans de Goede void site_survey(struct adapter *padapter) 3913554c0a3aSHans de Goede { 3914554c0a3aSHans de Goede unsigned char survey_channel = 0, val8; 3915c2e0b9a7SMarco Cesati enum rt_scan_type ScanType = SCAN_PASSIVE; 3916554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 3917554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 3918554c0a3aSHans de Goede u32 initialgain = 0; 3919554c0a3aSHans de Goede u32 channel_scan_time_ms = 0; 3920554c0a3aSHans de Goede 3921554c0a3aSHans de Goede { 3922554c0a3aSHans de Goede struct rtw_ieee80211_channel *ch; 3923c926f022SSimran Singhal 3924554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.channel_idx < pmlmeext->sitesurvey_res.ch_num) { 3925554c0a3aSHans de Goede ch = &pmlmeext->sitesurvey_res.ch[pmlmeext->sitesurvey_res.channel_idx]; 3926554c0a3aSHans de Goede survey_channel = ch->hw_value; 3927554c0a3aSHans de Goede ScanType = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE; 3928554c0a3aSHans de Goede } 3929554c0a3aSHans de Goede } 3930554c0a3aSHans de Goede 3931554c0a3aSHans de Goede if (survey_channel != 0) { 3932554c0a3aSHans de Goede /* PAUSE 4-AC Queue when site_survey */ 3933554c0a3aSHans de Goede /* rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 3934554c0a3aSHans de Goede /* val8 |= 0x0f; */ 3935554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 3936554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.channel_idx == 0) { 3937554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 3938554c0a3aSHans de Goede if (pmlmeext->fixed_chan != 0xff) 3939554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->fixed_chan, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 3940554c0a3aSHans de Goede else 3941554c0a3aSHans de Goede #endif 3942554c0a3aSHans de Goede set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 3943554c0a3aSHans de Goede } else { 3944554c0a3aSHans de Goede #ifdef DBG_FIXED_CHAN 3945554c0a3aSHans de Goede if (pmlmeext->fixed_chan != 0xff) 3946554c0a3aSHans de Goede SelectChannel(padapter, pmlmeext->fixed_chan); 3947554c0a3aSHans de Goede else 3948554c0a3aSHans de Goede #endif 3949554c0a3aSHans de Goede SelectChannel(padapter, survey_channel); 3950554c0a3aSHans de Goede } 3951554c0a3aSHans de Goede 3952554c0a3aSHans de Goede if (ScanType == SCAN_ACTIVE) { /* obey the channel plan setting... */ 3953554c0a3aSHans de Goede { 3954554c0a3aSHans de Goede int i; 3955c926f022SSimran Singhal 3956554c0a3aSHans de Goede for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { 3957554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) { 3958554c0a3aSHans de Goede /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */ 3959554c0a3aSHans de Goede if (padapter->registrypriv.wifi_spec) 3960554c0a3aSHans de Goede issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL); 3961554c0a3aSHans de Goede else 3962554c0a3aSHans de Goede issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0); 3963554c0a3aSHans de Goede issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL); 3964554c0a3aSHans de Goede } 3965554c0a3aSHans de Goede } 3966554c0a3aSHans de Goede 3967554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) { 3968554c0a3aSHans de Goede /* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */ 3969554c0a3aSHans de Goede if (padapter->registrypriv.wifi_spec) 3970554c0a3aSHans de Goede issue_probereq(padapter, NULL, NULL); 3971554c0a3aSHans de Goede else 3972554c0a3aSHans de Goede issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0); 3973554c0a3aSHans de Goede issue_probereq(padapter, NULL, NULL); 3974554c0a3aSHans de Goede } 3975554c0a3aSHans de Goede } 3976554c0a3aSHans de Goede } 3977554c0a3aSHans de Goede 3978554c0a3aSHans de Goede channel_scan_time_ms = pmlmeext->chan_scan_time; 3979554c0a3aSHans de Goede 3980554c0a3aSHans de Goede set_survey_timer(pmlmeext, channel_scan_time_ms); 3981554c0a3aSHans de Goede } else { 3982554c0a3aSHans de Goede 3983554c0a3aSHans de Goede /* channel number is 0 or this channel is not valid. */ 3984554c0a3aSHans de Goede 3985554c0a3aSHans de Goede { 3986554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_COMPLETE; 3987554c0a3aSHans de Goede 3988554c0a3aSHans de Goede /* switch back to the original channel */ 3989554c0a3aSHans de Goede /* SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset); */ 3990554c0a3aSHans de Goede 3991554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 3992554c0a3aSHans de Goede 3993554c0a3aSHans de Goede /* flush 4-AC Queue after site_survey */ 3994554c0a3aSHans de Goede /* val8 = 0; */ 3995554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, (u8 *)(&val8)); */ 3996554c0a3aSHans de Goede 3997554c0a3aSHans de Goede /* config MSR */ 3998554c0a3aSHans de Goede Set_MSR(padapter, (pmlmeinfo->state & 0x3)); 3999554c0a3aSHans de Goede 4000554c0a3aSHans de Goede initialgain = 0xff; /* restore RX GAIN */ 4001554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 4002554c0a3aSHans de Goede /* turn on dynamic functions */ 4003554c0a3aSHans de Goede Restore_DM_Func_Flag(padapter); 4004554c0a3aSHans de Goede /* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); */ 4005554c0a3aSHans de Goede 40060ad02fa8SGeorgiana Chelu if (is_client_associated_to_ap(padapter)) 4007554c0a3aSHans de Goede issue_nulldata(padapter, NULL, 0, 3, 500); 4008554c0a3aSHans de Goede 4009554c0a3aSHans de Goede val8 = 0; /* survey done */ 4010554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); 4011554c0a3aSHans de Goede 4012554c0a3aSHans de Goede report_surveydone_event(padapter); 4013554c0a3aSHans de Goede 4014554c0a3aSHans de Goede pmlmeext->chan_scan_time = SURVEY_TO; 4015554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_DISABLE; 4016554c0a3aSHans de Goede 4017554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4018554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4019554c0a3aSHans de Goede issue_action_BSSCoexistPacket(padapter); 4020554c0a3aSHans de Goede } 4021554c0a3aSHans de Goede } 4022554c0a3aSHans de Goede 4023554c0a3aSHans de Goede return; 4024554c0a3aSHans de Goede 4025554c0a3aSHans de Goede } 4026554c0a3aSHans de Goede 4027554c0a3aSHans de Goede /* collect bss info from Beacon and Probe request/response frames. */ 4028554c0a3aSHans de Goede u8 collect_bss_info(struct adapter *padapter, union recv_frame *precv_frame, struct wlan_bssid_ex *bssid) 4029554c0a3aSHans de Goede { 4030554c0a3aSHans de Goede int i; 4031554c0a3aSHans de Goede u32 len; 4032554c0a3aSHans de Goede u8 *p; 4033554c0a3aSHans de Goede u16 val16, subtype; 4034554c0a3aSHans de Goede u8 *pframe = precv_frame->u.hdr.rx_data; 4035554c0a3aSHans de Goede u32 packet_len = precv_frame->u.hdr.len; 4036554c0a3aSHans de Goede u8 ie_offset; 4037554c0a3aSHans de Goede struct registry_priv *pregistrypriv = &padapter->registrypriv; 4038554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4039554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4040554c0a3aSHans de Goede __le32 le32_tmp; 4041554c0a3aSHans de Goede 4042554c0a3aSHans de Goede len = packet_len - sizeof(struct ieee80211_hdr_3addr); 4043554c0a3aSHans de Goede 4044709c8e49SFabio Aiuto if (len > MAX_IE_SZ) 4045554c0a3aSHans de Goede return _FAIL; 4046554c0a3aSHans de Goede 4047554c0a3aSHans de Goede memset(bssid, 0, sizeof(struct wlan_bssid_ex)); 4048554c0a3aSHans de Goede 4049554c0a3aSHans de Goede subtype = GetFrameSubType(pframe); 4050554c0a3aSHans de Goede 4051554c0a3aSHans de Goede if (subtype == WIFI_BEACON) { 4052554c0a3aSHans de Goede bssid->Reserved[0] = 1; 4053554c0a3aSHans de Goede ie_offset = _BEACON_IE_OFFSET_; 4054554c0a3aSHans de Goede } else { 4055554c0a3aSHans de Goede /* FIXME : more type */ 4056554c0a3aSHans de Goede if (subtype == WIFI_PROBERSP) { 4057554c0a3aSHans de Goede ie_offset = _PROBERSP_IE_OFFSET_; 4058554c0a3aSHans de Goede bssid->Reserved[0] = 3; 4059554c0a3aSHans de Goede } else if (subtype == WIFI_PROBEREQ) { 4060554c0a3aSHans de Goede ie_offset = _PROBEREQ_IE_OFFSET_; 4061554c0a3aSHans de Goede bssid->Reserved[0] = 2; 4062554c0a3aSHans de Goede } else { 4063554c0a3aSHans de Goede bssid->Reserved[0] = 0; 4064554c0a3aSHans de Goede ie_offset = _FIXED_IE_LENGTH_; 4065554c0a3aSHans de Goede } 4066554c0a3aSHans de Goede } 4067554c0a3aSHans de Goede 4068554c0a3aSHans de Goede bssid->Length = sizeof(struct wlan_bssid_ex) - MAX_IE_SZ + len; 4069554c0a3aSHans de Goede 4070554c0a3aSHans de Goede /* below is to copy the information element */ 4071554c0a3aSHans de Goede bssid->IELength = len; 4072554c0a3aSHans de Goede memcpy(bssid->IEs, (pframe + sizeof(struct ieee80211_hdr_3addr)), bssid->IELength); 4073554c0a3aSHans de Goede 4074554c0a3aSHans de Goede /* get the signal strength */ 4075554c0a3aSHans de Goede bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; /* in dBM.raw data */ 4076554c0a3aSHans de Goede bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;/* in percentage */ 4077554c0a3aSHans de Goede bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;/* in percentage */ 4078554c0a3aSHans de Goede 4079554c0a3aSHans de Goede /* checking SSID */ 40803f15277bSRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_SSID, &len, bssid->IELength - ie_offset); 4081e427bdd8SFabio Aiuto if (!p) 4082554c0a3aSHans de Goede return _FAIL; 4083554c0a3aSHans de Goede 4084554c0a3aSHans de Goede if (*(p + 1)) { 4085709c8e49SFabio Aiuto if (len > NDIS_802_11_LENGTH_SSID) 4086554c0a3aSHans de Goede return _FAIL; 4087709c8e49SFabio Aiuto 4088554c0a3aSHans de Goede memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1)); 4089554c0a3aSHans de Goede bssid->Ssid.SsidLength = *(p + 1); 4090554c0a3aSHans de Goede } else 4091554c0a3aSHans de Goede bssid->Ssid.SsidLength = 0; 4092554c0a3aSHans de Goede 4093554c0a3aSHans de Goede memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX); 4094554c0a3aSHans de Goede 4095554c0a3aSHans de Goede /* checking rate info... */ 4096554c0a3aSHans de Goede i = 0; 4097c34c45edSRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_SUPP_RATES, &len, bssid->IELength - ie_offset); 409834557e23SIzabela Bakollari if (p) { 4099709c8e49SFabio Aiuto if (len > NDIS_802_11_LENGTH_RATES_EX) 4100554c0a3aSHans de Goede return _FAIL; 4101709c8e49SFabio Aiuto 4102554c0a3aSHans de Goede memcpy(bssid->SupportedRates, (p + 2), len); 4103554c0a3aSHans de Goede i = len; 4104554c0a3aSHans de Goede } 4105554c0a3aSHans de Goede 410600f0b682SRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_EXT_SUPP_RATES, &len, bssid->IELength - ie_offset); 410734557e23SIzabela Bakollari if (p) { 4108709c8e49SFabio Aiuto if (len > (NDIS_802_11_LENGTH_RATES_EX-i)) 4109554c0a3aSHans de Goede return _FAIL; 4110709c8e49SFabio Aiuto 4111554c0a3aSHans de Goede memcpy(bssid->SupportedRates + i, (p + 2), len); 4112554c0a3aSHans de Goede } 4113554c0a3aSHans de Goede 4114554c0a3aSHans de Goede bssid->NetworkTypeInUse = Ndis802_11OFDM24; 4115554c0a3aSHans de Goede 4116554c0a3aSHans de Goede if (bssid->IELength < 12) 4117554c0a3aSHans de Goede return _FAIL; 4118554c0a3aSHans de Goede 4119554c0a3aSHans de Goede /* Checking for DSConfig */ 41208f6a9446SRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_DS_PARAMS, &len, bssid->IELength - ie_offset); 4121554c0a3aSHans de Goede 4122554c0a3aSHans de Goede bssid->Configuration.DSConfig = 0; 4123554c0a3aSHans de Goede bssid->Configuration.Length = 0; 4124554c0a3aSHans de Goede 4125554c0a3aSHans de Goede if (p) { 4126554c0a3aSHans de Goede bssid->Configuration.DSConfig = *(p + 2); 4127554c0a3aSHans de Goede } else { 4128554c0a3aSHans de Goede /* In 5G, some ap do not have DSSET IE */ 4129554c0a3aSHans de Goede /* checking HT info for channel */ 4130332ec9dbSRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_HT_OPERATION, &len, bssid->IELength - ie_offset); 4131554c0a3aSHans de Goede if (p) { 4132554c0a3aSHans de Goede struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2); 4133c926f022SSimran Singhal 4134554c0a3aSHans de Goede bssid->Configuration.DSConfig = HT_info->primary_channel; 4135554c0a3aSHans de Goede } else { /* use current channel */ 4136554c0a3aSHans de Goede bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter); 4137554c0a3aSHans de Goede } 4138554c0a3aSHans de Goede } 4139554c0a3aSHans de Goede 4140554c0a3aSHans de Goede memcpy(&le32_tmp, rtw_get_beacon_interval_from_ie(bssid->IEs), 2); 4141554c0a3aSHans de Goede bssid->Configuration.BeaconPeriod = le32_to_cpu(le32_tmp); 4142554c0a3aSHans de Goede 4143554c0a3aSHans de Goede val16 = rtw_get_capability((struct wlan_bssid_ex *)bssid); 4144554c0a3aSHans de Goede 4145554c0a3aSHans de Goede if (val16 & BIT(0)) { 4146554c0a3aSHans de Goede bssid->InfrastructureMode = Ndis802_11Infrastructure; 4147554c0a3aSHans de Goede memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN); 4148554c0a3aSHans de Goede } else { 4149554c0a3aSHans de Goede bssid->InfrastructureMode = Ndis802_11IBSS; 4150554c0a3aSHans de Goede memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN); 4151554c0a3aSHans de Goede } 4152554c0a3aSHans de Goede 4153554c0a3aSHans de Goede if (val16 & BIT(4)) 4154554c0a3aSHans de Goede bssid->Privacy = 1; 4155554c0a3aSHans de Goede else 4156554c0a3aSHans de Goede bssid->Privacy = 0; 4157554c0a3aSHans de Goede 4158554c0a3aSHans de Goede bssid->Configuration.ATIMWindow = 0; 4159554c0a3aSHans de Goede 4160554c0a3aSHans de Goede /* 20/40 BSS Coexistence check */ 4161554c0a3aSHans de Goede if ((pregistrypriv->wifi_spec == 1) && (false == pmlmeinfo->bwmode_updated)) { 4162554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 4163554c0a3aSHans de Goede 4164fc6a6528SRoss Schmidt p = rtw_get_ie(bssid->IEs + ie_offset, WLAN_EID_HT_CAPABILITY, &len, bssid->IELength - ie_offset); 4165554c0a3aSHans de Goede if (p && len > 0) { 4166554c0a3aSHans de Goede struct HT_caps_element *pHT_caps; 4167c926f022SSimran Singhal 4168554c0a3aSHans de Goede pHT_caps = (struct HT_caps_element *)(p + 2); 4169554c0a3aSHans de Goede 4170554c0a3aSHans de Goede if (le16_to_cpu(pHT_caps->u.HT_cap_element.HT_caps_info) & BIT(14)) 4171554c0a3aSHans de Goede pmlmepriv->num_FortyMHzIntolerant++; 4172554c0a3aSHans de Goede } else 4173554c0a3aSHans de Goede pmlmepriv->num_sta_no_ht++; 4174554c0a3aSHans de Goede } 4175554c0a3aSHans de Goede 417668468503SAndreas Hellmich /* mark bss info receiving from nearby channel as SignalQuality 101 */ 4177554c0a3aSHans de Goede if (bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter)) 4178554c0a3aSHans de Goede bssid->PhyInfo.SignalQuality = 101; 4179554c0a3aSHans de Goede 4180554c0a3aSHans de Goede return _SUCCESS; 4181554c0a3aSHans de Goede } 4182554c0a3aSHans de Goede 4183554c0a3aSHans de Goede void start_create_ibss(struct adapter *padapter) 4184554c0a3aSHans de Goede { 4185554c0a3aSHans de Goede unsigned short caps; 4186554c0a3aSHans de Goede u8 val8; 4187554c0a3aSHans de Goede u8 join_type; 4188554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4189554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4190554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 4191c926f022SSimran Singhal 4192554c0a3aSHans de Goede pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; 4193554c0a3aSHans de Goede pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); 4194554c0a3aSHans de Goede 4195554c0a3aSHans de Goede /* update wireless mode */ 4196554c0a3aSHans de Goede update_wireless_mode(padapter); 4197554c0a3aSHans de Goede 419868468503SAndreas Hellmich /* update capability */ 4199554c0a3aSHans de Goede caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); 4200554c0a3aSHans de Goede update_capinfo(padapter, caps); 42012415ae7fSRoss Schmidt if (caps&WLAN_CAPABILITY_IBSS) {/* adhoc master */ 4202554c0a3aSHans de Goede val8 = 0xcf; 4203554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4204554c0a3aSHans de Goede 4205554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL); 4206554c0a3aSHans de Goede 4207554c0a3aSHans de Goede /* switch channel */ 4208554c0a3aSHans de Goede /* SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE); */ 4209554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20); 4210554c0a3aSHans de Goede 4211554c0a3aSHans de Goede beacon_timing_control(padapter); 4212554c0a3aSHans de Goede 4213554c0a3aSHans de Goede /* set msr to WIFI_FW_ADHOC_STATE */ 4214554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_ADHOC_STATE; 4215554c0a3aSHans de Goede Set_MSR(padapter, (pmlmeinfo->state & 0x3)); 4216554c0a3aSHans de Goede 4217554c0a3aSHans de Goede /* issue beacon */ 4218554c0a3aSHans de Goede if (send_beacon(padapter) == _FAIL) { 4219554c0a3aSHans de Goede report_join_res(padapter, -1); 4220554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4221554c0a3aSHans de Goede } else { 4222554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress); 4223554c0a3aSHans de Goede join_type = 0; 4224554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 4225554c0a3aSHans de Goede 4226554c0a3aSHans de Goede report_join_res(padapter, 1); 4227554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 4228554c0a3aSHans de Goede rtw_indicate_connect(padapter); 4229554c0a3aSHans de Goede } 4230554c0a3aSHans de Goede } else { 4231554c0a3aSHans de Goede return; 4232554c0a3aSHans de Goede } 4233554c0a3aSHans de Goede /* update bc/mc sta_info */ 4234554c0a3aSHans de Goede update_bmc_sta(padapter); 4235554c0a3aSHans de Goede 4236554c0a3aSHans de Goede } 4237554c0a3aSHans de Goede 4238554c0a3aSHans de Goede void start_clnt_join(struct adapter *padapter) 4239554c0a3aSHans de Goede { 4240554c0a3aSHans de Goede unsigned short caps; 4241554c0a3aSHans de Goede u8 val8; 4242554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4243554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4244554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 4245554c0a3aSHans de Goede int beacon_timeout; 4246554c0a3aSHans de Goede 4247554c0a3aSHans de Goede /* update wireless mode */ 4248554c0a3aSHans de Goede update_wireless_mode(padapter); 4249554c0a3aSHans de Goede 425068468503SAndreas Hellmich /* update capability */ 4251554c0a3aSHans de Goede caps = rtw_get_capability((struct wlan_bssid_ex *)pnetwork); 4252554c0a3aSHans de Goede update_capinfo(padapter, caps); 42532415ae7fSRoss Schmidt if (caps&WLAN_CAPABILITY_ESS) { 4254554c0a3aSHans de Goede Set_MSR(padapter, WIFI_FW_STATION_STATE); 4255554c0a3aSHans de Goede 4256554c0a3aSHans de Goede val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) ? 0xcc : 0xcf; 4257554c0a3aSHans de Goede 4258554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4259554c0a3aSHans de Goede 4260554c0a3aSHans de Goede /* Because of AP's not receiving deauth before */ 4261554c0a3aSHans de Goede /* AP may: 1)not response auth or 2)deauth us after link is complete */ 4262554c0a3aSHans de Goede /* issue deauth before issuing auth to deal with the situation */ 4263554c0a3aSHans de Goede 4264554c0a3aSHans de Goede /* Commented by Albert 2012/07/21 */ 4265554c0a3aSHans 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. */ 4266554c0a3aSHans de Goede { 4267554c0a3aSHans de Goede /* To avoid connecting to AP fail during resume process, change retry count from 5 to 1 */ 4268554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); 4269554c0a3aSHans de Goede } 4270554c0a3aSHans de Goede 4271554c0a3aSHans de Goede /* here wait for receiving the beacon to start auth */ 4272554c0a3aSHans de Goede /* and enable a timer */ 4273554c0a3aSHans de Goede beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval); 4274554c0a3aSHans de Goede set_link_timer(pmlmeext, beacon_timeout); 4275554c0a3aSHans de Goede _set_timer(&padapter->mlmepriv.assoc_timer, 4276554c0a3aSHans de Goede (REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) + beacon_timeout); 4277554c0a3aSHans de Goede 4278554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE; 42792415ae7fSRoss Schmidt } else if (caps&WLAN_CAPABILITY_IBSS) { /* adhoc client */ 4280554c0a3aSHans de Goede Set_MSR(padapter, WIFI_FW_ADHOC_STATE); 4281554c0a3aSHans de Goede 4282554c0a3aSHans de Goede val8 = 0xcf; 4283554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8)); 4284554c0a3aSHans de Goede 4285554c0a3aSHans de Goede beacon_timing_control(padapter); 4286554c0a3aSHans de Goede 4287554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_ADHOC_STATE; 4288554c0a3aSHans de Goede 4289554c0a3aSHans de Goede report_join_res(padapter, 1); 4290554c0a3aSHans de Goede } else { 4291554c0a3aSHans de Goede return; 4292554c0a3aSHans de Goede } 4293554c0a3aSHans de Goede 4294554c0a3aSHans de Goede } 4295554c0a3aSHans de Goede 4296554c0a3aSHans de Goede void start_clnt_auth(struct adapter *padapter) 4297554c0a3aSHans de Goede { 4298554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4299554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4300554c0a3aSHans de Goede 4301554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 4302554c0a3aSHans de Goede 4303554c0a3aSHans de Goede pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL); 4304554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_AUTH_STATE; 4305554c0a3aSHans de Goede 4306554c0a3aSHans de Goede pmlmeinfo->auth_seq = 1; 4307554c0a3aSHans de Goede pmlmeinfo->reauth_count = 0; 4308554c0a3aSHans de Goede pmlmeinfo->reassoc_count = 0; 4309554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 4310554c0a3aSHans de Goede pmlmeext->retry = 0; 4311554c0a3aSHans de Goede 4312554c0a3aSHans de Goede 431379df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, "start auth\n"); 4314554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 4315554c0a3aSHans de Goede 4316554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 4317554c0a3aSHans de Goede 4318554c0a3aSHans de Goede } 4319554c0a3aSHans de Goede 4320554c0a3aSHans de Goede 4321554c0a3aSHans de Goede void start_clnt_assoc(struct adapter *padapter) 4322554c0a3aSHans de Goede { 4323554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4324554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4325554c0a3aSHans de Goede 4326554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 4327554c0a3aSHans de Goede 4328554c0a3aSHans de Goede pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE)); 4329554c0a3aSHans de Goede pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE); 4330554c0a3aSHans de Goede 4331554c0a3aSHans de Goede issue_assocreq(padapter); 4332554c0a3aSHans de Goede 4333554c0a3aSHans de Goede set_link_timer(pmlmeext, REASSOC_TO); 4334554c0a3aSHans de Goede } 4335554c0a3aSHans de Goede 4336554c0a3aSHans de Goede unsigned int receive_disconnect(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) 4337554c0a3aSHans de Goede { 4338554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4339554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4340554c0a3aSHans de Goede 4341554c0a3aSHans de Goede /* check A3 */ 4342554c0a3aSHans de Goede if (!(!memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN))) 4343554c0a3aSHans de Goede return _SUCCESS; 4344554c0a3aSHans de Goede 4345554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 4346554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { 4347554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4348554c0a3aSHans de Goede report_del_sta_event(padapter, MacAddr, reason); 4349554c0a3aSHans de Goede 4350554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE) { 4351554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4352554c0a3aSHans de Goede report_join_res(padapter, -2); 4353554c0a3aSHans de Goede } 4354554c0a3aSHans de Goede } 4355554c0a3aSHans de Goede 4356554c0a3aSHans de Goede return _SUCCESS; 4357554c0a3aSHans de Goede } 4358554c0a3aSHans de Goede 4359554c0a3aSHans de Goede static void process_80211d(struct adapter *padapter, struct wlan_bssid_ex *bssid) 4360554c0a3aSHans de Goede { 4361554c0a3aSHans de Goede struct registry_priv *pregistrypriv; 4362554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 4363f0e46c47SMarco Cesati struct rt_channel_info *chplan_new; 4364554c0a3aSHans de Goede u8 channel; 4365554c0a3aSHans de Goede u8 i; 4366554c0a3aSHans de Goede 4367554c0a3aSHans de Goede 4368554c0a3aSHans de Goede pregistrypriv = &padapter->registrypriv; 4369554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 4370554c0a3aSHans de Goede 4371554c0a3aSHans de Goede /* Adjust channel plan by AP Country IE */ 4372554c0a3aSHans de Goede if (pregistrypriv->enable80211d && 4373554c0a3aSHans de Goede (!pmlmeext->update_channel_plan_by_ap_done)) { 4374554c0a3aSHans de Goede u8 *ie, *p; 4375554c0a3aSHans de Goede u32 len; 4376f0e46c47SMarco Cesati struct rt_channel_plan chplan_ap; 4377f0e46c47SMarco Cesati struct rt_channel_info chplan_sta[MAX_CHANNEL_NUM]; 4378554c0a3aSHans de Goede u8 country[4]; 4379554c0a3aSHans de Goede u8 fcn; /* first channel number */ 4380554c0a3aSHans de Goede u8 noc; /* number of channel */ 4381554c0a3aSHans de Goede u8 j, k; 4382554c0a3aSHans de Goede 43830b44fca9SRoss Schmidt ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, WLAN_EID_COUNTRY, &len, bssid->IELength - _FIXED_IE_LENGTH_); 4384554c0a3aSHans de Goede if (!ie) 4385554c0a3aSHans de Goede return; 4386554c0a3aSHans de Goede if (len < 6) 4387554c0a3aSHans de Goede return; 4388554c0a3aSHans de Goede 4389554c0a3aSHans de Goede ie += 2; 4390554c0a3aSHans de Goede p = ie; 4391554c0a3aSHans de Goede ie += len; 4392554c0a3aSHans de Goede 4393554c0a3aSHans de Goede memset(country, 0, 4); 4394554c0a3aSHans de Goede memcpy(country, p, 3); 4395554c0a3aSHans de Goede p += 3; 4396554c0a3aSHans de Goede 4397554c0a3aSHans de Goede i = 0; 4398554c0a3aSHans de Goede while ((ie - p) >= 3) { 4399554c0a3aSHans de Goede fcn = *(p++); 4400554c0a3aSHans de Goede noc = *(p++); 4401554c0a3aSHans de Goede p++; 4402554c0a3aSHans de Goede 4403554c0a3aSHans de Goede for (j = 0; j < noc; j++) { 4404554c0a3aSHans de Goede if (fcn <= 14) 4405554c0a3aSHans de Goede channel = fcn + j; /* 2.4 GHz */ 4406554c0a3aSHans de Goede else 4407554c0a3aSHans de Goede channel = fcn + j*4; /* 5 GHz */ 4408554c0a3aSHans de Goede 4409554c0a3aSHans de Goede chplan_ap.Channel[i++] = channel; 4410554c0a3aSHans de Goede } 4411554c0a3aSHans de Goede } 4412554c0a3aSHans de Goede chplan_ap.Len = i; 4413554c0a3aSHans de Goede 4414554c0a3aSHans de Goede memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta)); 4415554c0a3aSHans de Goede 4416554c0a3aSHans de Goede memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set)); 4417554c0a3aSHans de Goede chplan_new = pmlmeext->channel_set; 4418554c0a3aSHans de Goede 4419554c0a3aSHans de Goede i = j = k = 0; 4420554c0a3aSHans de Goede if (pregistrypriv->wireless_mode & WIRELESS_11G) { 4421554c0a3aSHans de Goede do { 4422554c0a3aSHans de Goede if ((i == MAX_CHANNEL_NUM) || 4423554c0a3aSHans de Goede (chplan_sta[i].ChannelNum == 0) || 4424554c0a3aSHans de Goede (chplan_sta[i].ChannelNum > 14)) 4425554c0a3aSHans de Goede break; 4426554c0a3aSHans de Goede 4427554c0a3aSHans de Goede if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14)) 4428554c0a3aSHans de Goede break; 4429554c0a3aSHans de Goede 4430554c0a3aSHans de Goede if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { 4431554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4432554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4433554c0a3aSHans de Goede i++; 4434554c0a3aSHans de Goede j++; 4435554c0a3aSHans de Goede k++; 4436554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { 4437554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4438554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4439554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4440554c0a3aSHans de Goede i++; 4441554c0a3aSHans de Goede k++; 4442554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { 4443554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4444554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4445554c0a3aSHans de Goede j++; 4446554c0a3aSHans de Goede k++; 4447554c0a3aSHans de Goede } 4448554c0a3aSHans de Goede } while (1); 4449554c0a3aSHans de Goede 4450554c0a3aSHans de Goede /* change AP not support channel to Passive scan */ 4451554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && 4452554c0a3aSHans de Goede (chplan_sta[i].ChannelNum != 0) && 4453554c0a3aSHans de Goede (chplan_sta[i].ChannelNum <= 14)) { 4454554c0a3aSHans de Goede 4455554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4456554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4457554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4458554c0a3aSHans de Goede i++; 4459554c0a3aSHans de Goede k++; 4460554c0a3aSHans de Goede } 4461554c0a3aSHans de Goede 4462554c0a3aSHans de Goede /* add channel AP supported */ 4463554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) { 4464554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4465554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4466554c0a3aSHans de Goede j++; 4467554c0a3aSHans de Goede k++; 4468554c0a3aSHans de Goede } 4469554c0a3aSHans de Goede } else { 4470554c0a3aSHans de Goede /* keep original STA 2.4G channel plan */ 4471554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && 4472554c0a3aSHans de Goede (chplan_sta[i].ChannelNum != 0) && 4473554c0a3aSHans de Goede (chplan_sta[i].ChannelNum <= 14)) { 4474554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4475554c0a3aSHans de Goede chplan_new[k].ScanType = chplan_sta[i].ScanType; 4476554c0a3aSHans de Goede i++; 4477554c0a3aSHans de Goede k++; 4478554c0a3aSHans de Goede } 4479554c0a3aSHans de Goede 4480554c0a3aSHans de Goede /* skip AP 2.4G channel plan */ 4481554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14)) { 4482554c0a3aSHans de Goede j++; 4483554c0a3aSHans de Goede } 4484554c0a3aSHans de Goede } 4485554c0a3aSHans de Goede 4486554c0a3aSHans de Goede if (pregistrypriv->wireless_mode & WIRELESS_11A) { 4487554c0a3aSHans de Goede do { 4488554c0a3aSHans de Goede if ((i == MAX_CHANNEL_NUM) || 4489554c0a3aSHans de Goede (chplan_sta[i].ChannelNum == 0)) 4490554c0a3aSHans de Goede break; 4491554c0a3aSHans de Goede 4492554c0a3aSHans de Goede if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0)) 4493554c0a3aSHans de Goede break; 4494554c0a3aSHans de Goede 4495554c0a3aSHans de Goede if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j]) { 4496554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4497554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4498554c0a3aSHans de Goede i++; 4499554c0a3aSHans de Goede j++; 4500554c0a3aSHans de Goede k++; 4501554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j]) { 4502554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4503554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4504554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4505554c0a3aSHans de Goede i++; 4506554c0a3aSHans de Goede k++; 4507554c0a3aSHans de Goede } else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j]) { 4508554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4509554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4510554c0a3aSHans de Goede j++; 4511554c0a3aSHans de Goede k++; 4512554c0a3aSHans de Goede } 4513554c0a3aSHans de Goede } while (1); 4514554c0a3aSHans de Goede 4515554c0a3aSHans de Goede /* change AP not support channel to Passive scan */ 4516554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4517554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4518554c0a3aSHans de Goede /* chplan_new[k].ScanType = chplan_sta[i].ScanType; */ 4519554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_PASSIVE; 4520554c0a3aSHans de Goede i++; 4521554c0a3aSHans de Goede k++; 4522554c0a3aSHans de Goede } 4523554c0a3aSHans de Goede 4524554c0a3aSHans de Goede /* add channel AP supported */ 4525554c0a3aSHans de Goede while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0)) { 4526554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_ap.Channel[j]; 4527554c0a3aSHans de Goede chplan_new[k].ScanType = SCAN_ACTIVE; 4528554c0a3aSHans de Goede j++; 4529554c0a3aSHans de Goede k++; 4530554c0a3aSHans de Goede } 4531554c0a3aSHans de Goede } else { 4532554c0a3aSHans de Goede /* keep original STA 5G channel plan */ 4533554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0)) { 4534554c0a3aSHans de Goede chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum; 4535554c0a3aSHans de Goede chplan_new[k].ScanType = chplan_sta[i].ScanType; 4536554c0a3aSHans de Goede i++; 4537554c0a3aSHans de Goede k++; 4538554c0a3aSHans de Goede } 4539554c0a3aSHans de Goede } 4540554c0a3aSHans de Goede 4541554c0a3aSHans de Goede pmlmeext->update_channel_plan_by_ap_done = 1; 4542554c0a3aSHans de Goede } 4543554c0a3aSHans de Goede 4544554c0a3aSHans de Goede /* If channel is used by AP, set channel scan type to active */ 4545554c0a3aSHans de Goede channel = bssid->Configuration.DSConfig; 4546554c0a3aSHans de Goede chplan_new = pmlmeext->channel_set; 4547554c0a3aSHans de Goede i = 0; 4548554c0a3aSHans de Goede while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0)) { 4549554c0a3aSHans de Goede if (chplan_new[i].ChannelNum == channel) { 4550554c0a3aSHans de Goede if (chplan_new[i].ScanType == SCAN_PASSIVE) { 4551554c0a3aSHans de Goede /* 5G Bnad 2, 3 (DFS) doesn't change to active scan */ 4552554c0a3aSHans de Goede if (channel >= 52 && channel <= 144) 4553554c0a3aSHans de Goede break; 4554554c0a3aSHans de Goede 4555554c0a3aSHans de Goede chplan_new[i].ScanType = SCAN_ACTIVE; 4556554c0a3aSHans de Goede } 4557554c0a3aSHans de Goede break; 4558554c0a3aSHans de Goede } 4559554c0a3aSHans de Goede i++; 4560554c0a3aSHans de Goede } 4561554c0a3aSHans de Goede } 4562554c0a3aSHans de Goede 4563554c0a3aSHans de Goede /**************************************************************************** 4564554c0a3aSHans de Goede 4565554c0a3aSHans de Goede Following are the functions to report events 4566554c0a3aSHans de Goede 4567554c0a3aSHans de Goede *****************************************************************************/ 4568554c0a3aSHans de Goede 4569554c0a3aSHans de Goede void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame) 4570554c0a3aSHans de Goede { 4571554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4572554c0a3aSHans de Goede u8 *pevtcmd; 4573554c0a3aSHans de Goede u32 cmdsz; 4574554c0a3aSHans de Goede struct survey_event *psurvey_evt; 4575554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4576554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext; 4577554c0a3aSHans de Goede struct cmd_priv *pcmdpriv; 4578554c0a3aSHans de Goede /* u8 *pframe = precv_frame->u.hdr.rx_data; */ 4579554c0a3aSHans de Goede /* uint len = precv_frame->u.hdr.len; */ 4580554c0a3aSHans de Goede 4581554c0a3aSHans de Goede if (!padapter) 4582554c0a3aSHans de Goede return; 4583554c0a3aSHans de Goede 4584554c0a3aSHans de Goede pmlmeext = &padapter->mlmeextpriv; 4585554c0a3aSHans de Goede pcmdpriv = &padapter->cmdpriv; 4586554c0a3aSHans de Goede 45872ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 458841452327SVatsala Narang if (!pcmd_obj) 4589554c0a3aSHans de Goede return; 4590554c0a3aSHans de Goede 4591554c0a3aSHans de Goede cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header)); 45922ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 459341452327SVatsala Narang if (!pevtcmd) { 45948f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4595554c0a3aSHans de Goede return; 4596554c0a3aSHans de Goede } 4597554c0a3aSHans de Goede 4598554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4599554c0a3aSHans de Goede 4600554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4601554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4602554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4603554c0a3aSHans de Goede 4604554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4605554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4606554c0a3aSHans de Goede 4607554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4608554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct survey_event); 4609554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey); 4610554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4611554c0a3aSHans de Goede 4612554c0a3aSHans de Goede psurvey_evt = (struct survey_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4613554c0a3aSHans de Goede 4614554c0a3aSHans de Goede if (collect_bss_info(padapter, precv_frame, (struct wlan_bssid_ex *)&psurvey_evt->bss) == _FAIL) { 46158f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 46168f24f505SMadhumitha Prabakaran kfree(pevtcmd); 4617554c0a3aSHans de Goede return; 4618554c0a3aSHans de Goede } 4619554c0a3aSHans de Goede 4620554c0a3aSHans de Goede process_80211d(padapter, &psurvey_evt->bss); 4621554c0a3aSHans de Goede 4622554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4623554c0a3aSHans de Goede 4624554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt++; 4625554c0a3aSHans de Goede 4626554c0a3aSHans de Goede return; 4627554c0a3aSHans de Goede 4628554c0a3aSHans de Goede } 4629554c0a3aSHans de Goede 4630554c0a3aSHans de Goede void report_surveydone_event(struct adapter *padapter) 4631554c0a3aSHans de Goede { 4632554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4633554c0a3aSHans de Goede u8 *pevtcmd; 4634554c0a3aSHans de Goede u32 cmdsz; 4635554c0a3aSHans de Goede struct surveydone_event *psurveydone_evt; 4636554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4637554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4638554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4639554c0a3aSHans de Goede 46402ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 464141452327SVatsala Narang if (!pcmd_obj) 4642554c0a3aSHans de Goede return; 4643554c0a3aSHans de Goede 4644554c0a3aSHans de Goede cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header)); 46452ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 464641452327SVatsala Narang if (!pevtcmd) { 46478f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4648554c0a3aSHans de Goede return; 4649554c0a3aSHans de Goede } 4650554c0a3aSHans de Goede 4651554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4652554c0a3aSHans de Goede 4653554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4654554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4655554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4656554c0a3aSHans de Goede 4657554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4658554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4659554c0a3aSHans de Goede 4660554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4661554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct surveydone_event); 4662554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone); 4663554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4664554c0a3aSHans de Goede 4665554c0a3aSHans de Goede psurveydone_evt = (struct surveydone_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4666554c0a3aSHans de Goede psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt; 4667554c0a3aSHans de Goede 4668554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4669554c0a3aSHans de Goede 4670554c0a3aSHans de Goede return; 4671554c0a3aSHans de Goede 4672554c0a3aSHans de Goede } 4673554c0a3aSHans de Goede 4674554c0a3aSHans de Goede void report_join_res(struct adapter *padapter, int res) 4675554c0a3aSHans de Goede { 4676554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4677554c0a3aSHans de Goede u8 *pevtcmd; 4678554c0a3aSHans de Goede u32 cmdsz; 4679554c0a3aSHans de Goede struct joinbss_event *pjoinbss_evt; 4680554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4681554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4682554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4683554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4684554c0a3aSHans de Goede 46852ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 468641452327SVatsala Narang if (!pcmd_obj) 4687554c0a3aSHans de Goede return; 4688554c0a3aSHans de Goede 4689554c0a3aSHans de Goede cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header)); 46902ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 469141452327SVatsala Narang if (!pevtcmd) { 46928f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4693554c0a3aSHans de Goede return; 4694554c0a3aSHans de Goede } 4695554c0a3aSHans de Goede 4696554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4697554c0a3aSHans de Goede 4698554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4699554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4700554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4701554c0a3aSHans de Goede 4702554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4703554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4704554c0a3aSHans de Goede 4705554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4706554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct joinbss_event); 4707554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss); 4708554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4709554c0a3aSHans de Goede 4710554c0a3aSHans de Goede pjoinbss_evt = (struct joinbss_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4711554c0a3aSHans de Goede memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex)); 4712554c0a3aSHans de Goede pjoinbss_evt->network.join_res = pjoinbss_evt->network.aid = res; 4713554c0a3aSHans de Goede 4714554c0a3aSHans de Goede 4715554c0a3aSHans de Goede rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network); 4716554c0a3aSHans de Goede 4717554c0a3aSHans de Goede 4718554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4719554c0a3aSHans de Goede 4720554c0a3aSHans de Goede return; 4721554c0a3aSHans de Goede 4722554c0a3aSHans de Goede } 4723554c0a3aSHans de Goede 4724554c0a3aSHans de Goede void report_wmm_edca_update(struct adapter *padapter) 4725554c0a3aSHans de Goede { 4726554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4727554c0a3aSHans de Goede u8 *pevtcmd; 4728554c0a3aSHans de Goede u32 cmdsz; 4729554c0a3aSHans de Goede struct wmm_event *pwmm_event; 4730554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4731554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4732554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4733554c0a3aSHans de Goede 47342ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 473541452327SVatsala Narang if (!pcmd_obj) 4736554c0a3aSHans de Goede return; 4737554c0a3aSHans de Goede 4738554c0a3aSHans de Goede cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header)); 47392ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 474041452327SVatsala Narang if (!pevtcmd) { 47418f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4742554c0a3aSHans de Goede return; 4743554c0a3aSHans de Goede } 4744554c0a3aSHans de Goede 4745554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4746554c0a3aSHans de Goede 4747554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4748554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4749554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4750554c0a3aSHans de Goede 4751554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4752554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4753554c0a3aSHans de Goede 4754554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4755554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct wmm_event); 4756554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM); 4757554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4758554c0a3aSHans de Goede 4759554c0a3aSHans de Goede pwmm_event = (struct wmm_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4760554c0a3aSHans de Goede pwmm_event->wmm = 0; 4761554c0a3aSHans de Goede 4762554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4763554c0a3aSHans de Goede 4764554c0a3aSHans de Goede return; 4765554c0a3aSHans de Goede 4766554c0a3aSHans de Goede } 4767554c0a3aSHans de Goede 4768554c0a3aSHans de Goede void report_del_sta_event(struct adapter *padapter, unsigned char *MacAddr, unsigned short reason) 4769554c0a3aSHans de Goede { 4770554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4771554c0a3aSHans de Goede u8 *pevtcmd; 4772554c0a3aSHans de Goede u32 cmdsz; 4773554c0a3aSHans de Goede struct sta_info *psta; 4774554c0a3aSHans de Goede int mac_id; 4775554c0a3aSHans de Goede struct stadel_event *pdel_sta_evt; 4776554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4777554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4778554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4779554c0a3aSHans de Goede 47802ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 4781554c0a3aSHans de Goede if (pcmd_obj == NULL) { 4782554c0a3aSHans de Goede return; 4783554c0a3aSHans de Goede } 4784554c0a3aSHans de Goede 4785554c0a3aSHans de Goede cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header)); 47862ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 4787554c0a3aSHans de Goede if (pevtcmd == NULL) { 47888f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4789554c0a3aSHans de Goede return; 4790554c0a3aSHans de Goede } 4791554c0a3aSHans de Goede 4792554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4793554c0a3aSHans de Goede 4794554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4795554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4796554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4797554c0a3aSHans de Goede 4798554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4799554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4800554c0a3aSHans de Goede 4801554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4802554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct stadel_event); 4803554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA); 4804554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4805554c0a3aSHans de Goede 4806554c0a3aSHans de Goede pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4807554c0a3aSHans de Goede memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN); 4808554c0a3aSHans de Goede memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2); 4809554c0a3aSHans de Goede 4810554c0a3aSHans de Goede 4811554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, MacAddr); 4812554c0a3aSHans de Goede if (psta) 4813554c0a3aSHans de Goede mac_id = (int)psta->mac_id; 4814554c0a3aSHans de Goede else 4815554c0a3aSHans de Goede mac_id = (-1); 4816554c0a3aSHans de Goede 4817554c0a3aSHans de Goede pdel_sta_evt->mac_id = mac_id; 4818554c0a3aSHans de Goede 4819554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4820554c0a3aSHans de Goede } 4821554c0a3aSHans de Goede 4822554c0a3aSHans de Goede void report_add_sta_event(struct adapter *padapter, unsigned char *MacAddr, int cam_idx) 4823554c0a3aSHans de Goede { 4824554c0a3aSHans de Goede struct cmd_obj *pcmd_obj; 4825554c0a3aSHans de Goede u8 *pevtcmd; 4826554c0a3aSHans de Goede u32 cmdsz; 4827554c0a3aSHans de Goede struct stassoc_event *padd_sta_evt; 4828554c0a3aSHans de Goede struct C2HEvent_Header *pc2h_evt_hdr; 4829554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4830554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 4831554c0a3aSHans de Goede 48322ef2b7c2SJoe Perches pcmd_obj = rtw_zmalloc(sizeof(struct cmd_obj)); 4833554c0a3aSHans de Goede if (pcmd_obj == NULL) 4834554c0a3aSHans de Goede return; 4835554c0a3aSHans de Goede 4836554c0a3aSHans de Goede cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header)); 48372ef2b7c2SJoe Perches pevtcmd = rtw_zmalloc(cmdsz); 4838554c0a3aSHans de Goede if (pevtcmd == NULL) { 48398f24f505SMadhumitha Prabakaran kfree(pcmd_obj); 4840554c0a3aSHans de Goede return; 4841554c0a3aSHans de Goede } 4842554c0a3aSHans de Goede 4843554c0a3aSHans de Goede INIT_LIST_HEAD(&pcmd_obj->list); 4844554c0a3aSHans de Goede 4845554c0a3aSHans de Goede pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT); 4846554c0a3aSHans de Goede pcmd_obj->cmdsz = cmdsz; 4847554c0a3aSHans de Goede pcmd_obj->parmbuf = pevtcmd; 4848554c0a3aSHans de Goede 4849554c0a3aSHans de Goede pcmd_obj->rsp = NULL; 4850554c0a3aSHans de Goede pcmd_obj->rspsz = 0; 4851554c0a3aSHans de Goede 4852554c0a3aSHans de Goede pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd); 4853554c0a3aSHans de Goede pc2h_evt_hdr->len = sizeof(struct stassoc_event); 4854554c0a3aSHans de Goede pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA); 4855554c0a3aSHans de Goede pc2h_evt_hdr->seq = atomic_inc_return(&pmlmeext->event_seq); 4856554c0a3aSHans de Goede 4857554c0a3aSHans de Goede padd_sta_evt = (struct stassoc_event *)(pevtcmd + sizeof(struct C2HEvent_Header)); 4858554c0a3aSHans de Goede memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN); 4859554c0a3aSHans de Goede padd_sta_evt->cam_id = cam_idx; 4860554c0a3aSHans de Goede 4861554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, pcmd_obj); 4862554c0a3aSHans de Goede } 4863554c0a3aSHans de Goede 4864554c0a3aSHans de Goede /**************************************************************************** 4865554c0a3aSHans de Goede 4866554c0a3aSHans de Goede Following are the event callback functions 4867554c0a3aSHans de Goede 4868554c0a3aSHans de Goede *****************************************************************************/ 4869554c0a3aSHans de Goede 4870554c0a3aSHans de Goede /* for sta/adhoc mode */ 4871554c0a3aSHans de Goede void update_sta_info(struct adapter *padapter, struct sta_info *psta) 4872554c0a3aSHans de Goede { 4873554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); 4874554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4875554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4876554c0a3aSHans de Goede 4877554c0a3aSHans de Goede /* ERP */ 4878554c0a3aSHans de Goede VCS_update(padapter, psta); 4879554c0a3aSHans de Goede 4880554c0a3aSHans de Goede /* HT */ 4881554c0a3aSHans de Goede if (pmlmepriv->htpriv.ht_option) { 4882554c0a3aSHans de Goede psta->htpriv.ht_option = true; 4883554c0a3aSHans de Goede 4884554c0a3aSHans de Goede psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable; 4885554c0a3aSHans de Goede 4886554c0a3aSHans de Goede psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2; 4887554c0a3aSHans de Goede 4888554c0a3aSHans de Goede if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20)) 4889554c0a3aSHans de Goede psta->htpriv.sgi_20m = true; 4890554c0a3aSHans de Goede 4891554c0a3aSHans de Goede if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40)) 4892554c0a3aSHans de Goede psta->htpriv.sgi_40m = true; 4893554c0a3aSHans de Goede 4894554c0a3aSHans de Goede psta->qos_option = true; 4895554c0a3aSHans de Goede 4896554c0a3aSHans de Goede psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap; 4897554c0a3aSHans de Goede psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap; 4898554c0a3aSHans de Goede psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap; 4899554c0a3aSHans de Goede 4900c25d8a7dSRoss Schmidt memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct ieee80211_ht_cap)); 4901554c0a3aSHans de Goede } else { 4902554c0a3aSHans de Goede psta->htpriv.ht_option = false; 4903554c0a3aSHans de Goede 4904554c0a3aSHans de Goede psta->htpriv.ampdu_enable = false; 4905554c0a3aSHans de Goede 4906554c0a3aSHans de Goede psta->htpriv.sgi_20m = false; 4907554c0a3aSHans de Goede psta->htpriv.sgi_40m = false; 4908554c0a3aSHans de Goede psta->qos_option = false; 4909554c0a3aSHans de Goede 4910554c0a3aSHans de Goede } 4911554c0a3aSHans de Goede 4912554c0a3aSHans de Goede psta->htpriv.ch_offset = pmlmeext->cur_ch_offset; 4913554c0a3aSHans de Goede 4914554c0a3aSHans de Goede psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ 4915554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ 4916554c0a3aSHans de Goede 4917554c0a3aSHans de Goede psta->bw_mode = pmlmeext->cur_bwmode; 4918554c0a3aSHans de Goede 4919554c0a3aSHans de Goede /* QoS */ 4920554c0a3aSHans de Goede if (pmlmepriv->qospriv.qos_option) 4921554c0a3aSHans de Goede psta->qos_option = true; 4922554c0a3aSHans de Goede 4923554c0a3aSHans de Goede update_ldpc_stbc_cap(psta); 4924554c0a3aSHans de Goede 4925554c0a3aSHans de Goede spin_lock_bh(&psta->lock); 4926554c0a3aSHans de Goede psta->state = _FW_LINKED; 4927554c0a3aSHans de Goede spin_unlock_bh(&psta->lock); 4928554c0a3aSHans de Goede 4929554c0a3aSHans de Goede } 4930554c0a3aSHans de Goede 4931554c0a3aSHans de Goede static void rtw_mlmeext_disconnect(struct adapter *padapter) 4932554c0a3aSHans de Goede { 4933554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 4934554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4935554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4936554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 4937554c0a3aSHans de Goede 4938554c0a3aSHans de Goede /* set_opmode_cmd(padapter, infra_client_with_mlme); */ 4939554c0a3aSHans de Goede 49404d17363dSAndreas Hellmich /* For safety, prevent from keeping macid sleep. 4941554c0a3aSHans de Goede * If we can sure all power mode enter/leave are paired, 4942554c0a3aSHans de Goede * this check can be removed. 4943554c0a3aSHans de Goede * Lucas@20131113 4944554c0a3aSHans de Goede */ 4945554c0a3aSHans de Goede /* wakeup macid after disconnect. */ 4946554c0a3aSHans de Goede { 4947554c0a3aSHans de Goede struct sta_info *psta; 4948c926f022SSimran Singhal 4949554c0a3aSHans de Goede psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork)); 4950554c0a3aSHans de Goede if (psta) 4951554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 4952554c0a3aSHans de Goede } 4953554c0a3aSHans de Goede 4954554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL); 4955554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); 4956554c0a3aSHans de Goede 4957554c0a3aSHans de Goede /* set MSR to no link state -> infra. mode */ 4958554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_STATION_); 4959554c0a3aSHans de Goede 4960554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 4961554c0a3aSHans de Goede 4962554c0a3aSHans de Goede /* switch to the 20M Hz mode after disconnect */ 4963554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 4964554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 4965554c0a3aSHans de Goede 4966554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 4967554c0a3aSHans de Goede 4968554c0a3aSHans de Goede flush_all_cam_entry(padapter); 4969554c0a3aSHans de Goede 4970554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 4971554c0a3aSHans de Goede 4972554c0a3aSHans de Goede /* pmlmepriv->LinkDetectInfo.TrafficBusyState = false; */ 4973554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0; 4974554c0a3aSHans de Goede pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0; 4975554c0a3aSHans de Goede 4976554c0a3aSHans de Goede } 4977554c0a3aSHans de Goede 4978554c0a3aSHans de Goede void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res) 4979554c0a3aSHans de Goede { 4980554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 4981554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 4982554c0a3aSHans de Goede struct wlan_bssid_ex *cur_network = &(pmlmeinfo->network); 4983554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 4984554c0a3aSHans de Goede u8 join_type; 4985554c0a3aSHans de Goede struct sta_info *psta; 4986c926f022SSimran Singhal 4987554c0a3aSHans de Goede if (join_res < 0) { 4988554c0a3aSHans de Goede join_type = 1; 4989554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 4990554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr); 4991554c0a3aSHans de Goede 499281ff14a3SFabio Aiuto return; 4993554c0a3aSHans de Goede } 4994554c0a3aSHans de Goede 4995554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) 4996554c0a3aSHans de Goede /* update bc/mc sta_info */ 4997554c0a3aSHans de Goede update_bmc_sta(padapter); 4998554c0a3aSHans de Goede 4999554c0a3aSHans de Goede 5000554c0a3aSHans de Goede /* turn on dynamic functions */ 5001554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, true); 5002554c0a3aSHans de Goede 500368468503SAndreas Hellmich /* update IOT-related issue */ 5004554c0a3aSHans de Goede update_IOT_info(padapter); 5005554c0a3aSHans de Goede 5006554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates); 5007554c0a3aSHans de Goede 5008554c0a3aSHans de Goede /* BCN interval */ 5009554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval)); 5010554c0a3aSHans de Goede 501168468503SAndreas Hellmich /* update capability */ 5012554c0a3aSHans de Goede update_capinfo(padapter, pmlmeinfo->capability); 5013554c0a3aSHans de Goede 5014554c0a3aSHans de Goede /* WMM, Update EDCA param */ 5015554c0a3aSHans de Goede WMMOnAssocRsp(padapter); 5016554c0a3aSHans de Goede 5017554c0a3aSHans de Goede /* HT */ 5018554c0a3aSHans de Goede HTOnAssocRsp(padapter); 5019554c0a3aSHans de Goede 5020554c0a3aSHans de Goede /* Set cur_channel&cur_bwmode&cur_ch_offset */ 5021554c0a3aSHans de Goede set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode); 5022554c0a3aSHans de Goede 5023554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress); 5024554c0a3aSHans de Goede if (psta) { /* only for infra. mode */ 5025554c0a3aSHans de Goede 5026554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; 5027554c0a3aSHans de Goede 5028554c0a3aSHans de Goede psta->wireless_mode = pmlmeext->cur_wireless_mode; 5029554c0a3aSHans de Goede 5030554c0a3aSHans de Goede /* set per sta rate after updating HT cap. */ 5031554c0a3aSHans de Goede set_sta_rate(padapter, psta); 5032554c0a3aSHans de Goede 5033554c0a3aSHans de Goede rtw_sta_media_status_rpt(padapter, psta, 1); 5034554c0a3aSHans de Goede 5035554c0a3aSHans de Goede /* wakeup macid after join bss successfully to ensure 5036554c0a3aSHans de Goede the subsequent data frames can be sent out normally */ 5037554c0a3aSHans de Goede rtw_hal_macid_wakeup(padapter, psta->mac_id); 5038554c0a3aSHans de Goede } 5039554c0a3aSHans de Goede 5040554c0a3aSHans de Goede join_type = 2; 5041554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5042554c0a3aSHans de Goede 5043554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) { 5044554c0a3aSHans de Goede /* correcting TSF */ 5045554c0a3aSHans de Goede correct_TSF(padapter, pmlmeext); 5046554c0a3aSHans de Goede 5047554c0a3aSHans de Goede /* set_link_timer(pmlmeext, DISCONNECT_TO); */ 5048554c0a3aSHans de Goede } 5049554c0a3aSHans de Goede 5050554c0a3aSHans de Goede if (get_iface_type(padapter) == IFACE_PORT0) 5051554c0a3aSHans de Goede rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0); 5052554c0a3aSHans de Goede } 5053554c0a3aSHans de Goede 5054554c0a3aSHans de Goede /* currently only adhoc mode will go here */ 5055554c0a3aSHans de Goede void mlmeext_sta_add_event_callback(struct adapter *padapter, struct sta_info *psta) 5056554c0a3aSHans de Goede { 5057554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); 5058554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5059554c0a3aSHans de Goede u8 join_type; 5060554c0a3aSHans de Goede 5061554c0a3aSHans de Goede if ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) { 5062554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { /* adhoc master or sta_count>1 */ 5063554c0a3aSHans de Goede 5064554c0a3aSHans de Goede /* nothing to do */ 5065554c0a3aSHans de Goede } else { /* adhoc client */ 5066554c0a3aSHans de Goede /* update TSF Value */ 5067554c0a3aSHans de Goede /* update_TSF(pmlmeext, pframe, len); */ 5068554c0a3aSHans de Goede 5069554c0a3aSHans de Goede /* correcting TSF */ 5070554c0a3aSHans de Goede correct_TSF(padapter, pmlmeext); 5071554c0a3aSHans de Goede 5072554c0a3aSHans de Goede /* start beacon */ 5073554c0a3aSHans de Goede if (send_beacon(padapter) == _FAIL) { 5074554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].status = 0; 5075554c0a3aSHans de Goede 5076554c0a3aSHans de Goede pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE; 5077554c0a3aSHans de Goede 5078554c0a3aSHans de Goede return; 5079554c0a3aSHans de Goede } 5080554c0a3aSHans de Goede 5081554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS; 5082554c0a3aSHans de Goede 5083554c0a3aSHans de Goede } 5084554c0a3aSHans de Goede 5085554c0a3aSHans de Goede join_type = 2; 5086554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5087554c0a3aSHans de Goede } 5088554c0a3aSHans de Goede 5089554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; 5090554c0a3aSHans de Goede 5091554c0a3aSHans de Goede psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates); 5092554c0a3aSHans de Goede memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen); 5093554c0a3aSHans de Goede 5094554c0a3aSHans de Goede /* update adhoc sta_info */ 5095554c0a3aSHans de Goede update_sta_info(padapter, psta); 5096554c0a3aSHans de Goede 5097554c0a3aSHans de Goede rtw_hal_update_sta_rate_mask(padapter, psta); 5098554c0a3aSHans de Goede 5099554c0a3aSHans de Goede /* ToDo: HT for Ad-hoc */ 5100554c0a3aSHans de Goede psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel); 5101777a4334SNishka Dasgupta psta->raid = networktype_to_raid_ex(padapter, psta); 5102554c0a3aSHans de Goede 5103554c0a3aSHans de Goede /* rate radaptive */ 5104554c0a3aSHans de Goede Update_RA_Entry(padapter, psta); 5105554c0a3aSHans de Goede } 5106554c0a3aSHans de Goede 5107554c0a3aSHans de Goede void mlmeext_sta_del_event_callback(struct adapter *padapter) 5108554c0a3aSHans de Goede { 5109554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter)) 5110554c0a3aSHans de Goede rtw_mlmeext_disconnect(padapter); 5111554c0a3aSHans de Goede } 5112554c0a3aSHans de Goede 5113554c0a3aSHans de Goede /**************************************************************************** 5114554c0a3aSHans de Goede 5115554c0a3aSHans de Goede Following are the functions for the timer handlers 5116554c0a3aSHans de Goede 5117554c0a3aSHans de Goede *****************************************************************************/ 5118554c0a3aSHans de Goede void _linked_info_dump(struct adapter *padapter) 5119554c0a3aSHans de Goede { 5120554c0a3aSHans de Goede int i; 5121554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5122554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5123554c0a3aSHans de Goede int UndecoratedSmoothedPWDB; 5124554c0a3aSHans de Goede struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter); 5125554c0a3aSHans de Goede 5126554c0a3aSHans de Goede if (padapter->bLinkInfoDump) { 5127554c0a3aSHans de Goede 512876dfbca4SFabio M. De Francesco if ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) 5129554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB); 5130554c0a3aSHans de Goede 5131554c0a3aSHans de Goede for (i = 0; i < NUM_STA; i++) { 51320ad02fa8SGeorgiana Chelu if (pdvobj->macid[i]) { 5133554c0a3aSHans de Goede if (i != 1) /* skip bc/mc sta */ 5134554c0a3aSHans de Goede /* tx info ============ */ 5135554c0a3aSHans de Goede rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i); 5136554c0a3aSHans de Goede } 5137554c0a3aSHans de Goede } 5138554c0a3aSHans de Goede rtw_hal_set_def_var(padapter, HAL_DEF_DBG_RX_INFO_DUMP, NULL); 5139554c0a3aSHans de Goede } 5140554c0a3aSHans de Goede } 5141554c0a3aSHans de Goede 5142554c0a3aSHans de Goede static u8 chk_ap_is_alive(struct adapter *padapter, struct sta_info *psta) 5143554c0a3aSHans de Goede { 5144554c0a3aSHans de Goede u8 ret = false; 5145554c0a3aSHans de Goede 5146554c0a3aSHans de Goede if ((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta)) 5147554c0a3aSHans de Goede && sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta) 5148554c0a3aSHans de Goede && sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta) 5149554c0a3aSHans de Goede ) { 5150554c0a3aSHans de Goede ret = false; 5151554c0a3aSHans de Goede } else { 5152554c0a3aSHans de Goede ret = true; 5153554c0a3aSHans de Goede } 5154554c0a3aSHans de Goede 5155554c0a3aSHans de Goede sta_update_last_rx_pkts(psta); 5156554c0a3aSHans de Goede 5157554c0a3aSHans de Goede return ret; 5158554c0a3aSHans de Goede } 5159554c0a3aSHans de Goede 5160554c0a3aSHans de Goede void linked_status_chk(struct adapter *padapter) 5161554c0a3aSHans de Goede { 5162554c0a3aSHans de Goede u32 i; 5163554c0a3aSHans de Goede struct sta_info *psta; 5164554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); 5165554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5166554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5167554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5168554c0a3aSHans de Goede 5169554c0a3aSHans de Goede 5170554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter)) { 5171554c0a3aSHans de Goede /* linked infrastructure client mode */ 5172554c0a3aSHans de Goede 5173554c0a3aSHans de Goede int tx_chk = _SUCCESS, rx_chk = _SUCCESS; 5174554c0a3aSHans de Goede int rx_chk_limit; 5175554c0a3aSHans de Goede int link_count_limit; 5176554c0a3aSHans de Goede 5177554c0a3aSHans de Goede #if defined(DBG_ROAMING_TEST) 5178554c0a3aSHans de Goede rx_chk_limit = 1; 5179554c0a3aSHans de Goede #else 5180554c0a3aSHans de Goede rx_chk_limit = 8; 5181554c0a3aSHans de Goede #endif 5182554c0a3aSHans de Goede link_count_limit = 7; /* 16 sec */ 5183554c0a3aSHans de Goede 5184554c0a3aSHans de Goede /* Marked by Kurt 20130715 */ 5185554c0a3aSHans 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. */ 5186554c0a3aSHans de Goede /* todo: To check why we under miracast session, rx_chk would be false */ 5187554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress); 518834557e23SIzabela Bakollari if (psta) { 5189554c0a3aSHans de Goede if (chk_ap_is_alive(padapter, psta) == false) 5190554c0a3aSHans de Goede rx_chk = _FAIL; 5191554c0a3aSHans de Goede 5192554c0a3aSHans de Goede if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts) 5193554c0a3aSHans de Goede tx_chk = _FAIL; 5194554c0a3aSHans de Goede 5195554c0a3aSHans de Goede { 5196554c0a3aSHans de Goede if (rx_chk != _SUCCESS) { 5197554c0a3aSHans de Goede if (pmlmeext->retry == 0) { 5198554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5199554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5200554c0a3aSHans de Goede issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0); 5201554c0a3aSHans de Goede } 5202554c0a3aSHans de Goede } 5203554c0a3aSHans de Goede 5204af6afdb6SFabio Aiuto if (tx_chk != _SUCCESS && 5205af6afdb6SFabio Aiuto pmlmeinfo->link_count++ == link_count_limit) 5206554c0a3aSHans de Goede tx_chk = issue_nulldata_in_interrupt(padapter, NULL); 5207554c0a3aSHans de Goede } 5208554c0a3aSHans de Goede 5209554c0a3aSHans de Goede if (rx_chk == _FAIL) { 5210554c0a3aSHans de Goede pmlmeext->retry++; 5211554c0a3aSHans de Goede if (pmlmeext->retry > rx_chk_limit) { 521279df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 521379df841bSFabio Aiuto FUNC_ADPT_FMT " disconnect or roaming\n", 5214554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter)); 5215554c0a3aSHans de Goede receive_disconnect(padapter, pmlmeinfo->network.MacAddress 5216554c0a3aSHans de Goede , WLAN_REASON_EXPIRATION_CHK); 5217554c0a3aSHans de Goede return; 5218554c0a3aSHans de Goede } 5219554c0a3aSHans de Goede } else { 5220554c0a3aSHans de Goede pmlmeext->retry = 0; 5221554c0a3aSHans de Goede } 5222554c0a3aSHans de Goede 5223554c0a3aSHans de Goede if (tx_chk == _FAIL) { 5224554c0a3aSHans de Goede pmlmeinfo->link_count %= (link_count_limit+1); 5225554c0a3aSHans de Goede } else { 5226554c0a3aSHans de Goede pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts; 5227554c0a3aSHans de Goede pmlmeinfo->link_count = 0; 5228554c0a3aSHans de Goede } 5229554c0a3aSHans de Goede 5230554c0a3aSHans de Goede } /* end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL) */ 5231554c0a3aSHans de Goede } else if (is_client_associated_to_ibss(padapter)) { 5232554c0a3aSHans de Goede /* linked IBSS mode */ 5233554c0a3aSHans de Goede /* for each assoc list entry to check the rx pkt counter */ 5234554c0a3aSHans de Goede for (i = IBSS_START_MAC_ID; i < NUM_STA; i++) { 5235554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].status == 1) { 5236554c0a3aSHans de Goede psta = pmlmeinfo->FW_sta_info[i].psta; 5237554c0a3aSHans de Goede 5238554c0a3aSHans de Goede if (NULL == psta) 5239554c0a3aSHans de Goede continue; 5240554c0a3aSHans de Goede 5241554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta)) { 5242554c0a3aSHans de Goede 5243554c0a3aSHans de Goede if (pmlmeinfo->FW_sta_info[i].retry < 3) { 5244554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry++; 5245554c0a3aSHans de Goede } else { 5246554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry = 0; 5247554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].status = 0; 5248554c0a3aSHans de Goede report_del_sta_event(padapter, psta->hwaddr 5249554c0a3aSHans de Goede , 65535/* indicate disconnect caused by no rx */ 5250554c0a3aSHans de Goede ); 5251554c0a3aSHans de Goede } 5252554c0a3aSHans de Goede } else { 5253554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].retry = 0; 5254554c0a3aSHans de Goede pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta); 5255554c0a3aSHans de Goede } 5256554c0a3aSHans de Goede } 5257554c0a3aSHans de Goede } 5258554c0a3aSHans de Goede 5259554c0a3aSHans de Goede /* set_link_timer(pmlmeext, DISCONNECT_TO); */ 5260554c0a3aSHans de Goede 5261554c0a3aSHans de Goede } 5262554c0a3aSHans de Goede 5263554c0a3aSHans de Goede } 5264554c0a3aSHans de Goede 5265e8b1844aSKees Cook void survey_timer_hdl(struct timer_list *t) 5266554c0a3aSHans de Goede { 5267e8b1844aSKees Cook struct adapter *padapter = 5268e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.survey_timer); 5269554c0a3aSHans de Goede struct cmd_obj *ph2c; 5270554c0a3aSHans de Goede struct sitesurvey_parm *psurveyPara; 5271554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 5272554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5273554c0a3aSHans de Goede 5274554c0a3aSHans de Goede /* issue rtw_sitesurvey_cmd */ 5275554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state > SCAN_START) { 5276554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) { 5277554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx++; 5278554c0a3aSHans de Goede } 5279554c0a3aSHans de Goede 52800ad02fa8SGeorgiana Chelu if (pmlmeext->scan_abort) { 5281554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = pmlmeext->sitesurvey_res.ch_num; 5282554c0a3aSHans de Goede 5283554c0a3aSHans de Goede pmlmeext->scan_abort = false;/* reset */ 5284554c0a3aSHans de Goede } 5285554c0a3aSHans de Goede 52862ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 5287554c0a3aSHans de Goede if (ph2c == NULL) { 5288554c0a3aSHans de Goede goto exit_survey_timer_hdl; 5289554c0a3aSHans de Goede } 5290554c0a3aSHans de Goede 52912ef2b7c2SJoe Perches psurveyPara = rtw_zmalloc(sizeof(struct sitesurvey_parm)); 5292554c0a3aSHans de Goede if (psurveyPara == NULL) { 52938f24f505SMadhumitha Prabakaran kfree(ph2c); 5294554c0a3aSHans de Goede goto exit_survey_timer_hdl; 5295554c0a3aSHans de Goede } 5296554c0a3aSHans de Goede 5297554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey)); 5298554c0a3aSHans de Goede rtw_enqueue_cmd(pcmdpriv, ph2c); 5299554c0a3aSHans de Goede } 5300554c0a3aSHans de Goede 5301554c0a3aSHans de Goede 5302554c0a3aSHans de Goede exit_survey_timer_hdl: 5303554c0a3aSHans de Goede 5304554c0a3aSHans de Goede return; 5305554c0a3aSHans de Goede } 5306554c0a3aSHans de Goede 5307e8b1844aSKees Cook void link_timer_hdl(struct timer_list *t) 5308554c0a3aSHans de Goede { 5309e8b1844aSKees Cook struct adapter *padapter = 5310e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.link_timer); 5311554c0a3aSHans de Goede /* static unsigned int rx_pkt = 0; */ 5312554c0a3aSHans de Goede /* static u64 tx_cnt = 0; */ 5313554c0a3aSHans de Goede /* struct xmit_priv *pxmitpriv = &(padapter->xmitpriv); */ 5314554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5315554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5316554c0a3aSHans de Goede /* struct sta_priv *pstapriv = &padapter->stapriv; */ 5317554c0a3aSHans de Goede 5318554c0a3aSHans de Goede 5319554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_AUTH_NULL) { 5320554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5321554c0a3aSHans de Goede report_join_res(padapter, -3); 5322554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE) { 5323554c0a3aSHans de Goede /* re-auth timer */ 5324554c0a3aSHans de Goede if (++pmlmeinfo->reauth_count > REAUTH_LIMIT) { 5325554c0a3aSHans de Goede /* if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto) */ 5326554c0a3aSHans de Goede /* */ 5327554c0a3aSHans de Goede pmlmeinfo->state = 0; 5328554c0a3aSHans de Goede report_join_res(padapter, -1); 5329554c0a3aSHans de Goede return; 5330554c0a3aSHans de Goede /* */ 5331554c0a3aSHans de Goede /* else */ 5332554c0a3aSHans de Goede /* */ 5333554c0a3aSHans de Goede /* pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared; */ 5334554c0a3aSHans de Goede /* pmlmeinfo->reauth_count = 0; */ 5335554c0a3aSHans de Goede /* */ 5336554c0a3aSHans de Goede } 5337554c0a3aSHans de Goede 5338554c0a3aSHans de Goede pmlmeinfo->auth_seq = 1; 5339554c0a3aSHans de Goede issue_auth(padapter, NULL, 0); 5340554c0a3aSHans de Goede set_link_timer(pmlmeext, REAUTH_TO); 5341554c0a3aSHans de Goede } else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE) { 5342554c0a3aSHans de Goede /* re-assoc timer */ 5343554c0a3aSHans de Goede if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT) { 5344554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5345554c0a3aSHans de Goede report_join_res(padapter, -2); 5346554c0a3aSHans de Goede return; 5347554c0a3aSHans de Goede } 5348554c0a3aSHans de Goede 5349554c0a3aSHans de Goede issue_assocreq(padapter); 5350554c0a3aSHans de Goede set_link_timer(pmlmeext, REASSOC_TO); 5351554c0a3aSHans de Goede } 5352554c0a3aSHans de Goede } 5353554c0a3aSHans de Goede 5354e8b1844aSKees Cook void addba_timer_hdl(struct timer_list *t) 5355554c0a3aSHans de Goede { 5356e8b1844aSKees Cook struct sta_info *psta = from_timer(psta, t, addba_retry_timer); 5357554c0a3aSHans de Goede struct ht_priv *phtpriv; 5358554c0a3aSHans de Goede 5359554c0a3aSHans de Goede if (!psta) 5360554c0a3aSHans de Goede return; 5361554c0a3aSHans de Goede 5362554c0a3aSHans de Goede phtpriv = &psta->htpriv; 5363554c0a3aSHans de Goede 53640ad02fa8SGeorgiana Chelu if (phtpriv->ht_option && phtpriv->ampdu_enable) { 5365554c0a3aSHans de Goede if (phtpriv->candidate_tid_bitmap) 5366554c0a3aSHans de Goede phtpriv->candidate_tid_bitmap = 0x0; 5367554c0a3aSHans de Goede 5368554c0a3aSHans de Goede } 5369554c0a3aSHans de Goede } 5370554c0a3aSHans de Goede 5371e8b1844aSKees Cook void sa_query_timer_hdl(struct timer_list *t) 5372554c0a3aSHans de Goede { 5373e8b1844aSKees Cook struct adapter *padapter = 5374e8b1844aSKees Cook from_timer(padapter, t, mlmeextpriv.sa_query_timer); 5375554c0a3aSHans de Goede struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 5376554c0a3aSHans de Goede /* disconnect */ 5377554c0a3aSHans de Goede spin_lock_bh(&pmlmepriv->lock); 5378554c0a3aSHans de Goede 53790ad02fa8SGeorgiana Chelu if (check_fwstate(pmlmepriv, _FW_LINKED)) { 5380554c0a3aSHans de Goede rtw_disassoc_cmd(padapter, 0, true); 5381554c0a3aSHans de Goede rtw_indicate_disconnect(padapter); 5382554c0a3aSHans de Goede rtw_free_assoc_resources(padapter, 1); 5383554c0a3aSHans de Goede } 5384554c0a3aSHans de Goede 5385554c0a3aSHans de Goede spin_unlock_bh(&pmlmepriv->lock); 5386554c0a3aSHans de Goede } 5387554c0a3aSHans de Goede 5388554c0a3aSHans de Goede u8 NULL_hdl(struct adapter *padapter, u8 *pbuf) 5389554c0a3aSHans de Goede { 5390554c0a3aSHans de Goede return H2C_SUCCESS; 5391554c0a3aSHans de Goede } 5392554c0a3aSHans de Goede 5393554c0a3aSHans de Goede u8 setopmode_hdl(struct adapter *padapter, u8 *pbuf) 5394554c0a3aSHans de Goede { 5395554c0a3aSHans de Goede u8 type; 5396554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5397554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5398554c0a3aSHans de Goede struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf; 5399554c0a3aSHans de Goede 5400554c0a3aSHans de Goede if (psetop->mode == Ndis802_11APMode) { 5401554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_AP_STATE; 5402554c0a3aSHans de Goede type = _HW_STATE_AP_; 5403554c0a3aSHans de Goede /* start_ap_mode(padapter); */ 5404554c0a3aSHans de Goede } else if (psetop->mode == Ndis802_11Infrastructure) { 5405554c0a3aSHans de Goede pmlmeinfo->state &= ~(BIT(0)|BIT(1));/* clear state */ 5406554c0a3aSHans de Goede pmlmeinfo->state |= WIFI_FW_STATION_STATE;/* set to STATION_STATE */ 5407554c0a3aSHans de Goede type = _HW_STATE_STATION_; 5408554c0a3aSHans de Goede } else if (psetop->mode == Ndis802_11IBSS) { 5409554c0a3aSHans de Goede type = _HW_STATE_ADHOC_; 5410554c0a3aSHans de Goede } else { 5411554c0a3aSHans de Goede type = _HW_STATE_NOLINK_; 5412554c0a3aSHans de Goede } 5413554c0a3aSHans de Goede 5414554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type)); 5415eb569cc0SNishka Dasgupta /* Set_MSR(padapter, type); */ 5416554c0a3aSHans de Goede 5417554c0a3aSHans de Goede if (psetop->mode == Ndis802_11APMode) { 5418554c0a3aSHans de Goede /* Do this after port switch to */ 5419554c0a3aSHans de Goede /* prevent from downloading rsvd page to wrong port */ 5420554c0a3aSHans de Goede rtw_btcoex_MediaStatusNotify(padapter, 1); /* connect */ 5421554c0a3aSHans de Goede } 5422554c0a3aSHans de Goede 5423554c0a3aSHans de Goede return H2C_SUCCESS; 5424554c0a3aSHans de Goede 5425554c0a3aSHans de Goede } 5426554c0a3aSHans de Goede 5427554c0a3aSHans de Goede u8 createbss_hdl(struct adapter *padapter, u8 *pbuf) 5428554c0a3aSHans de Goede { 5429554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5430554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5431554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 5432554c0a3aSHans de Goede struct joinbss_parm *pparm = (struct joinbss_parm *)pbuf; 5433554c0a3aSHans de Goede /* u32 initialgain; */ 5434554c0a3aSHans de Goede 5435554c0a3aSHans de Goede if (pmlmeinfo->state == WIFI_FW_AP_STATE) { 5436cab77590SSaurav Girepunje start_bss_network(padapter); 5437554c0a3aSHans de Goede return H2C_SUCCESS; 5438554c0a3aSHans de Goede } 5439554c0a3aSHans de Goede 5440554c0a3aSHans de Goede /* below is for ad-hoc master */ 5441554c0a3aSHans de Goede if (pparm->network.InfrastructureMode == Ndis802_11IBSS) { 5442554c0a3aSHans de Goede rtw_joinbss_reset(padapter); 5443554c0a3aSHans de Goede 5444554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 5445554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 5446554c0a3aSHans de Goede pmlmeinfo->ERP_enable = 0; 5447554c0a3aSHans de Goede pmlmeinfo->WMM_enable = 0; 5448554c0a3aSHans de Goede pmlmeinfo->HT_enable = 0; 5449554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 0; 5450554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 0; 5451554c0a3aSHans de Goede pmlmeinfo->agg_enable_bitmap = 0; 5452554c0a3aSHans de Goede pmlmeinfo->candidate_tid_bitmap = 0; 5453554c0a3aSHans de Goede 5454554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 5455554c0a3aSHans de Goede Save_DM_Func_Flag(padapter); 5456554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); 5457554c0a3aSHans de Goede 5458554c0a3aSHans de Goede /* config the initial gain under linking, need to write the BB registers */ 5459554c0a3aSHans de Goede /* initialgain = 0x1E; */ 5460554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */ 5461554c0a3aSHans de Goede 5462554c0a3aSHans de Goede /* cancel link timer */ 5463554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 5464554c0a3aSHans de Goede 5465554c0a3aSHans de Goede /* clear CAM */ 5466554c0a3aSHans de Goede flush_all_cam_entry(padapter); 5467554c0a3aSHans de Goede 5468554c0a3aSHans de Goede memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength)); 5469554c0a3aSHans de Goede pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength; 5470554c0a3aSHans de Goede 5471554c0a3aSHans de Goede if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ 5472554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 5473554c0a3aSHans de Goede 5474554c0a3aSHans de Goede memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength); 5475554c0a3aSHans de Goede 5476554c0a3aSHans de Goede start_create_ibss(padapter); 5477554c0a3aSHans de Goede 5478554c0a3aSHans de Goede } 5479554c0a3aSHans de Goede 5480554c0a3aSHans de Goede return H2C_SUCCESS; 5481554c0a3aSHans de Goede 5482554c0a3aSHans de Goede } 5483554c0a3aSHans de Goede 5484554c0a3aSHans de Goede u8 join_cmd_hdl(struct adapter *padapter, u8 *pbuf) 5485554c0a3aSHans de Goede { 5486554c0a3aSHans de Goede u8 join_type; 5487554c0a3aSHans de Goede struct ndis_80211_var_ie *pIE; 5488554c0a3aSHans de Goede struct registry_priv *pregpriv = &padapter->registrypriv; 5489554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5490554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5491554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 5492554c0a3aSHans de Goede u32 i; 5493554c0a3aSHans de Goede u8 cbw40_enable = 0; 5494554c0a3aSHans de Goede /* u32 initialgain; */ 5495554c0a3aSHans de Goede /* u32 acparm; */ 5496554c0a3aSHans de Goede u8 ch, bw, offset; 5497554c0a3aSHans de Goede 5498554c0a3aSHans de Goede /* check already connecting to AP or not */ 5499554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) { 5500554c0a3aSHans de Goede if (pmlmeinfo->state & WIFI_FW_STATION_STATE) { 5501554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100); 5502554c0a3aSHans de Goede } 5503554c0a3aSHans de Goede pmlmeinfo->state = WIFI_FW_NULL_STATE; 5504554c0a3aSHans de Goede 5505554c0a3aSHans de Goede /* clear CAM */ 5506554c0a3aSHans de Goede flush_all_cam_entry(padapter); 5507554c0a3aSHans de Goede 5508554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 5509554c0a3aSHans de Goede 5510554c0a3aSHans de Goede /* set MSR to nolink -> infra. mode */ 5511554c0a3aSHans de Goede /* Set_MSR(padapter, _HW_STATE_NOLINK_); */ 5512554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_STATION_); 5513554c0a3aSHans de Goede 5514554c0a3aSHans de Goede 5515554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, NULL); 5516554c0a3aSHans de Goede } 5517554c0a3aSHans de Goede 5518554c0a3aSHans de Goede rtw_joinbss_reset(padapter); 5519554c0a3aSHans de Goede 5520554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 5521554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 5522554c0a3aSHans de Goede pmlmeinfo->ERP_enable = 0; 5523554c0a3aSHans de Goede pmlmeinfo->WMM_enable = 0; 5524554c0a3aSHans de Goede pmlmeinfo->HT_enable = 0; 5525554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 0; 5526554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 0; 5527554c0a3aSHans de Goede pmlmeinfo->agg_enable_bitmap = 0; 5528554c0a3aSHans de Goede pmlmeinfo->candidate_tid_bitmap = 0; 5529554c0a3aSHans de Goede pmlmeinfo->bwmode_updated = false; 5530554c0a3aSHans de Goede /* pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX; */ 5531554c0a3aSHans de Goede pmlmeinfo->VHT_enable = 0; 5532554c0a3aSHans de Goede 5533554c0a3aSHans de Goede memcpy(pnetwork, pbuf, FIELD_OFFSET(struct wlan_bssid_ex, IELength)); 5534554c0a3aSHans de Goede pnetwork->IELength = ((struct wlan_bssid_ex *)pbuf)->IELength; 5535554c0a3aSHans de Goede 5536554c0a3aSHans de Goede if (pnetwork->IELength > MAX_IE_SZ)/* Check pbuf->IELength */ 5537554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 5538554c0a3aSHans de Goede 5539554c0a3aSHans de Goede memcpy(pnetwork->IEs, ((struct wlan_bssid_ex *)pbuf)->IEs, pnetwork->IELength); 5540554c0a3aSHans de Goede 5541554c0a3aSHans de Goede pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig; 5542554c0a3aSHans de Goede pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork); 5543554c0a3aSHans de Goede 5544554c0a3aSHans de Goede /* Check AP vendor to move rtw_joinbss_cmd() */ 5545554c0a3aSHans de Goede /* pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength); */ 5546554c0a3aSHans de Goede 5547554c0a3aSHans de Goede /* sizeof(struct ndis_802_11_fix_ie) */ 5548554c0a3aSHans de Goede for (i = _FIXED_IE_LENGTH_; i < pnetwork->IELength;) { 5549554c0a3aSHans de Goede pIE = (struct ndis_80211_var_ie *)(pnetwork->IEs + i); 5550554c0a3aSHans de Goede 5551554c0a3aSHans de Goede switch (pIE->ElementID) { 5552b05cc3a9SRoss Schmidt case WLAN_EID_VENDOR_SPECIFIC:/* Get WMM IE. */ 5553554c0a3aSHans de Goede if (!memcmp(pIE->data, WMM_OUI, 4)) 5554554c0a3aSHans de Goede WMM_param_handler(padapter, pIE); 5555554c0a3aSHans de Goede break; 5556554c0a3aSHans de Goede 5557fc6a6528SRoss Schmidt case WLAN_EID_HT_CAPABILITY: /* Get HT Cap IE. */ 5558554c0a3aSHans de Goede pmlmeinfo->HT_caps_enable = 1; 5559554c0a3aSHans de Goede break; 5560554c0a3aSHans de Goede 5561332ec9dbSRoss Schmidt case WLAN_EID_HT_OPERATION: /* Get HT Info IE. */ 5562554c0a3aSHans de Goede pmlmeinfo->HT_info_enable = 1; 5563554c0a3aSHans de Goede 5564554c0a3aSHans de Goede /* spec case only for cisco's ap because cisco's ap issue assoc rsp using mcs rate @40MHz or @20MHz */ 5565554c0a3aSHans de Goede { 5566554c0a3aSHans de Goede struct HT_info_element *pht_info = (struct HT_info_element *)(pIE->data); 5567554c0a3aSHans de Goede 5568554c0a3aSHans de Goede if (pnetwork->Configuration.DSConfig > 14) { 5569554c0a3aSHans de Goede if ((pregpriv->bw_mode >> 4) > CHANNEL_WIDTH_20) 5570554c0a3aSHans de Goede cbw40_enable = 1; 5571554c0a3aSHans de Goede } else { 5572554c0a3aSHans de Goede if ((pregpriv->bw_mode & 0x0f) > CHANNEL_WIDTH_20) 5573554c0a3aSHans de Goede cbw40_enable = 1; 5574554c0a3aSHans de Goede } 5575554c0a3aSHans de Goede 5576554c0a3aSHans de Goede if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) { 5577554c0a3aSHans de Goede /* switch to the 40M Hz mode according to the AP */ 5578554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_40; 5579554c0a3aSHans de Goede switch (pht_info->infos[0] & 0x3) { 5580554c0a3aSHans de Goede case 1: 5581554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; 5582554c0a3aSHans de Goede break; 5583554c0a3aSHans de Goede 5584554c0a3aSHans de Goede case 3: 5585554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; 5586554c0a3aSHans de Goede break; 5587554c0a3aSHans de Goede 5588554c0a3aSHans de Goede default: 5589554c0a3aSHans de Goede pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 5590554c0a3aSHans de Goede pmlmeext->cur_bwmode = CHANNEL_WIDTH_20; 5591554c0a3aSHans de Goede break; 5592554c0a3aSHans de Goede } 5593554c0a3aSHans de Goede } 5594554c0a3aSHans de Goede } 5595554c0a3aSHans de Goede break; 5596554c0a3aSHans de Goede default: 5597554c0a3aSHans de Goede break; 5598554c0a3aSHans de Goede } 5599554c0a3aSHans de Goede 5600554c0a3aSHans de Goede i += (pIE->Length + 2); 5601554c0a3aSHans de Goede } 5602554c0a3aSHans de Goede 5603554c0a3aSHans de Goede /* check channel, bandwidth, offset and switch */ 5604554c0a3aSHans de Goede if (rtw_chk_start_clnt_join(padapter, &ch, &bw, &offset) == _FAIL) { 5605554c0a3aSHans de Goede report_join_res(padapter, (-4)); 5606554c0a3aSHans de Goede return H2C_SUCCESS; 5607554c0a3aSHans de Goede } 5608554c0a3aSHans de Goede 5609554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 5610554c0a3aSHans de Goede /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */ 5611554c0a3aSHans de Goede 5612554c0a3aSHans de Goede /* config the initial gain under linking, need to write the BB registers */ 5613554c0a3aSHans de Goede /* initialgain = 0x1E; */ 5614554c0a3aSHans de Goede /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */ 5615554c0a3aSHans de Goede 5616554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress); 5617554c0a3aSHans de Goede join_type = 0; 5618554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type)); 5619554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK, NULL); 5620554c0a3aSHans de Goede 5621554c0a3aSHans de Goede set_channel_bwmode(padapter, ch, offset, bw); 5622554c0a3aSHans de Goede 5623554c0a3aSHans de Goede /* cancel link timer */ 5624554c0a3aSHans de Goede del_timer_sync(&pmlmeext->link_timer); 5625554c0a3aSHans de Goede 5626554c0a3aSHans de Goede start_clnt_join(padapter); 5627554c0a3aSHans de Goede 5628554c0a3aSHans de Goede return H2C_SUCCESS; 5629554c0a3aSHans de Goede 5630554c0a3aSHans de Goede } 5631554c0a3aSHans de Goede 5632554c0a3aSHans de Goede u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf) 5633554c0a3aSHans de Goede { 5634554c0a3aSHans de Goede struct disconnect_parm *param = (struct disconnect_parm *)pbuf; 5635554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5636554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5637554c0a3aSHans de Goede struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)(&(pmlmeinfo->network)); 5638554c0a3aSHans de Goede u8 val8; 5639554c0a3aSHans de Goede 5640554c0a3aSHans de Goede if (is_client_associated_to_ap(padapter)) { 5641554c0a3aSHans de Goede issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100); 5642554c0a3aSHans de Goede } 5643554c0a3aSHans de Goede 5644554c0a3aSHans de Goede if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) { 5645554c0a3aSHans de Goede /* Stop BCN */ 5646554c0a3aSHans de Goede val8 = 0; 5647554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8)); 5648554c0a3aSHans de Goede } 5649554c0a3aSHans de Goede 5650554c0a3aSHans de Goede rtw_mlmeext_disconnect(padapter); 5651554c0a3aSHans de Goede 5652554c0a3aSHans de Goede rtw_free_uc_swdec_pending_queue(padapter); 5653554c0a3aSHans de Goede 5654554c0a3aSHans de Goede return H2C_SUCCESS; 5655554c0a3aSHans de Goede } 5656554c0a3aSHans de Goede 5657554c0a3aSHans de Goede static int rtw_scan_ch_decision(struct adapter *padapter, struct rtw_ieee80211_channel *out, 5658554c0a3aSHans de Goede u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num) 5659554c0a3aSHans de Goede { 5660554c0a3aSHans de Goede int i, j; 5661554c0a3aSHans de Goede int set_idx; 5662554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5663554c0a3aSHans de Goede 5664554c0a3aSHans de Goede /* clear first */ 5665554c0a3aSHans de Goede memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num); 5666554c0a3aSHans de Goede 5667554c0a3aSHans de Goede /* acquire channels from in */ 5668554c0a3aSHans de Goede j = 0; 5669554c0a3aSHans de Goede for (i = 0; i < in_num; i++) { 5670554c0a3aSHans de Goede 5671554c0a3aSHans de Goede set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value); 5672554c0a3aSHans de Goede if (in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED) 5673554c0a3aSHans de Goede && set_idx >= 0 56740ad02fa8SGeorgiana Chelu && rtw_mlme_band_check(padapter, in[i].hw_value) 5675554c0a3aSHans de Goede ) { 5676554c0a3aSHans de Goede if (j >= out_num) { 567779df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 567879df841bSFabio Aiuto FUNC_ADPT_FMT " out_num:%u not enough\n", 5679554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), out_num); 5680554c0a3aSHans de Goede break; 5681554c0a3aSHans de Goede } 5682554c0a3aSHans de Goede 5683554c0a3aSHans de Goede memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel)); 5684554c0a3aSHans de Goede 5685554c0a3aSHans de Goede if (pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE) 5686554c0a3aSHans de Goede out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; 5687554c0a3aSHans de Goede 5688554c0a3aSHans de Goede j++; 5689554c0a3aSHans de Goede } 5690554c0a3aSHans de Goede if (j >= out_num) 5691554c0a3aSHans de Goede break; 5692554c0a3aSHans de Goede } 5693554c0a3aSHans de Goede 5694554c0a3aSHans de Goede /* if out is empty, use channel_set as default */ 5695554c0a3aSHans de Goede if (j == 0) { 5696554c0a3aSHans de Goede for (i = 0; i < pmlmeext->max_chan_nums; i++) { 5697554c0a3aSHans de Goede 56980ad02fa8SGeorgiana Chelu if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum)) { 5699554c0a3aSHans de Goede 5700554c0a3aSHans de Goede if (j >= out_num) { 570179df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 570279df841bSFabio Aiuto FUNC_ADPT_FMT " out_num:%u not enough\n", 570379df841bSFabio Aiuto FUNC_ADPT_ARG(padapter), 570479df841bSFabio Aiuto out_num); 5705554c0a3aSHans de Goede break; 5706554c0a3aSHans de Goede } 5707554c0a3aSHans de Goede 5708554c0a3aSHans de Goede out[j].hw_value = pmlmeext->channel_set[i].ChannelNum; 5709554c0a3aSHans de Goede 5710554c0a3aSHans de Goede if (pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE) 5711554c0a3aSHans de Goede out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN; 5712554c0a3aSHans de Goede 5713554c0a3aSHans de Goede j++; 5714554c0a3aSHans de Goede } 5715554c0a3aSHans de Goede } 5716554c0a3aSHans de Goede } 5717554c0a3aSHans de Goede 5718554c0a3aSHans de Goede return j; 5719554c0a3aSHans de Goede } 5720554c0a3aSHans de Goede 5721554c0a3aSHans de Goede u8 sitesurvey_cmd_hdl(struct adapter *padapter, u8 *pbuf) 5722554c0a3aSHans de Goede { 5723554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5724554c0a3aSHans de Goede struct sitesurvey_parm *pparm = (struct sitesurvey_parm *)pbuf; 5725554c0a3aSHans de Goede u8 bdelayscan = false; 5726554c0a3aSHans de Goede u8 val8; 5727554c0a3aSHans de Goede u32 initialgain; 5728554c0a3aSHans de Goede u32 i; 5729554c0a3aSHans de Goede 5730554c0a3aSHans de Goede if (pmlmeext->sitesurvey_res.state == SCAN_DISABLE) { 5731554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_START; 5732554c0a3aSHans de Goede pmlmeext->sitesurvey_res.bss_cnt = 0; 5733554c0a3aSHans de Goede pmlmeext->sitesurvey_res.channel_idx = 0; 5734554c0a3aSHans de Goede 5735554c0a3aSHans de Goede for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) { 5736554c0a3aSHans de Goede if (pparm->ssid[i].SsidLength) { 5737554c0a3aSHans de Goede memcpy(pmlmeext->sitesurvey_res.ssid[i].Ssid, pparm->ssid[i].Ssid, IW_ESSID_MAX_SIZE); 5738554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ssid[i].SsidLength = pparm->ssid[i].SsidLength; 5739554c0a3aSHans de Goede } else { 5740554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ssid[i].SsidLength = 0; 5741554c0a3aSHans de Goede } 5742554c0a3aSHans de Goede } 5743554c0a3aSHans de Goede 5744554c0a3aSHans de Goede pmlmeext->sitesurvey_res.ch_num = rtw_scan_ch_decision(padapter 5745554c0a3aSHans de Goede , pmlmeext->sitesurvey_res.ch, RTW_CHANNEL_SCAN_AMOUNT 5746554c0a3aSHans de Goede , pparm->ch, pparm->ch_num 5747554c0a3aSHans de Goede ); 5748554c0a3aSHans de Goede 5749554c0a3aSHans de Goede pmlmeext->sitesurvey_res.scan_mode = pparm->scan_mode; 5750554c0a3aSHans de Goede 5751554c0a3aSHans de Goede /* issue null data if associating to the AP */ 57520ad02fa8SGeorgiana Chelu if (is_client_associated_to_ap(padapter)) { 5753554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_TXNULL; 5754554c0a3aSHans de Goede 5755554c0a3aSHans de Goede issue_nulldata(padapter, NULL, 1, 3, 500); 5756554c0a3aSHans de Goede 5757554c0a3aSHans de Goede bdelayscan = true; 5758554c0a3aSHans de Goede } 5759554c0a3aSHans de Goede if (bdelayscan) { 5760554c0a3aSHans de Goede /* delay 50ms to protect nulldata(1). */ 5761554c0a3aSHans de Goede set_survey_timer(pmlmeext, 50); 5762554c0a3aSHans de Goede return H2C_SUCCESS; 5763554c0a3aSHans de Goede } 5764554c0a3aSHans de Goede } 5765554c0a3aSHans de Goede 5766554c0a3aSHans de Goede if ((pmlmeext->sitesurvey_res.state == SCAN_START) || (pmlmeext->sitesurvey_res.state == SCAN_TXNULL)) { 5767554c0a3aSHans de Goede /* disable dynamic functions, such as high power, DIG */ 5768554c0a3aSHans de Goede Save_DM_Func_Flag(padapter); 5769554c0a3aSHans de Goede Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); 5770554c0a3aSHans de Goede 57714d17363dSAndreas Hellmich /* config the initial gain under scanning, need to write the BB 57724d17363dSAndreas Hellmich * registers 57734d17363dSAndreas Hellmich */ 5774554c0a3aSHans de Goede initialgain = 0x1e; 5775554c0a3aSHans de Goede 5776554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); 5777554c0a3aSHans de Goede 5778554c0a3aSHans de Goede /* set MSR to no link state */ 5779554c0a3aSHans de Goede Set_MSR(padapter, _HW_STATE_NOLINK_); 5780554c0a3aSHans de Goede 5781554c0a3aSHans de Goede val8 = 1; /* under site survey */ 5782554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8)); 5783554c0a3aSHans de Goede 5784554c0a3aSHans de Goede pmlmeext->sitesurvey_res.state = SCAN_PROCESS; 5785554c0a3aSHans de Goede } 5786554c0a3aSHans de Goede 5787554c0a3aSHans de Goede site_survey(padapter); 5788554c0a3aSHans de Goede 5789554c0a3aSHans de Goede return H2C_SUCCESS; 5790554c0a3aSHans de Goede 5791554c0a3aSHans de Goede } 5792554c0a3aSHans de Goede 5793554c0a3aSHans de Goede u8 setauth_hdl(struct adapter *padapter, unsigned char *pbuf) 5794554c0a3aSHans de Goede { 5795554c0a3aSHans de Goede struct setauth_parm *pparm = (struct setauth_parm *)pbuf; 5796554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5797554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5798554c0a3aSHans de Goede 5799a65f0d18SVatsala Narang if (pparm->mode < 4) 5800554c0a3aSHans de Goede pmlmeinfo->auth_algo = pparm->mode; 5801554c0a3aSHans de Goede 5802554c0a3aSHans de Goede return H2C_SUCCESS; 5803554c0a3aSHans de Goede } 5804554c0a3aSHans de Goede 5805554c0a3aSHans de Goede u8 setkey_hdl(struct adapter *padapter, u8 *pbuf) 5806554c0a3aSHans de Goede { 5807554c0a3aSHans de Goede u16 ctrl = 0; 5808554c0a3aSHans de Goede s16 cam_id = 0; 5809554c0a3aSHans de Goede struct setkey_parm *pparm = (struct setkey_parm *)pbuf; 5810554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5811554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5812554c0a3aSHans de Goede unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 5813554c0a3aSHans de Goede u8 *addr; 5814554c0a3aSHans de Goede 5815554c0a3aSHans de Goede /* main tx key for wep. */ 5816554c0a3aSHans de Goede if (pparm->set_tx) 5817554c0a3aSHans de Goede pmlmeinfo->key_index = pparm->keyid; 5818554c0a3aSHans de Goede 5819554c0a3aSHans de Goede cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid); 5820554c0a3aSHans de Goede 5821554c0a3aSHans de Goede if (cam_id < 0) { 5822554c0a3aSHans de Goede } else { 5823554c0a3aSHans de Goede if (cam_id > 3) /* not default key, searched by A2 */ 5824554c0a3aSHans de Goede addr = get_bssid(&padapter->mlmepriv); 5825554c0a3aSHans de Goede else 5826554c0a3aSHans de Goede addr = null_addr; 5827554c0a3aSHans de Goede 5828554c0a3aSHans de Goede ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid; 5829554c0a3aSHans de Goede write_cam(padapter, cam_id, ctrl, addr, pparm->key); 583079df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 583179df841bSFabio Aiuto "set group key camid:%d, addr:%pM, kid:%d, type:%s\n", 583279df841bSFabio Aiuto cam_id, MAC_ARG(addr), pparm->keyid, 583379df841bSFabio Aiuto security_type_str(pparm->algorithm)); 5834554c0a3aSHans de Goede } 5835554c0a3aSHans de Goede 5836554c0a3aSHans de Goede if (cam_id >= 0 && cam_id <= 3) 5837554c0a3aSHans de Goede rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true); 5838554c0a3aSHans de Goede 5839554c0a3aSHans de Goede /* allow multicast packets to driver */ 5840554c0a3aSHans de Goede padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr); 5841554c0a3aSHans de Goede 5842554c0a3aSHans de Goede return H2C_SUCCESS; 5843554c0a3aSHans de Goede } 5844554c0a3aSHans de Goede 5845554c0a3aSHans de Goede u8 set_stakey_hdl(struct adapter *padapter, u8 *pbuf) 5846554c0a3aSHans de Goede { 5847554c0a3aSHans de Goede u16 ctrl = 0; 5848554c0a3aSHans de Goede s16 cam_id = 0; 5849554c0a3aSHans de Goede u8 ret = H2C_SUCCESS; 5850554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5851554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5852554c0a3aSHans de Goede struct set_stakey_parm *pparm = (struct set_stakey_parm *)pbuf; 5853554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 5854554c0a3aSHans de Goede struct sta_info *psta; 5855554c0a3aSHans de Goede 5856554c0a3aSHans de Goede if (pparm->algorithm == _NO_PRIVACY_) 5857554c0a3aSHans de Goede goto write_to_cam; 5858554c0a3aSHans de Goede 5859554c0a3aSHans de Goede psta = rtw_get_stainfo(pstapriv, pparm->addr); 5860554c0a3aSHans de Goede if (!psta) { 586179df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, "%s sta:%pM not found\n", 586279df841bSFabio Aiuto __func__, MAC_ARG(pparm->addr)); 5863554c0a3aSHans de Goede ret = H2C_REJECTED; 5864554c0a3aSHans de Goede goto exit; 5865554c0a3aSHans de Goede } 5866554c0a3aSHans de Goede 5867554c0a3aSHans de Goede pmlmeinfo->enc_algo = pparm->algorithm; 5868554c0a3aSHans de Goede cam_id = rtw_camid_alloc(padapter, psta, 0); 5869554c0a3aSHans de Goede if (cam_id < 0) 5870554c0a3aSHans de Goede goto exit; 5871554c0a3aSHans de Goede 5872554c0a3aSHans de Goede write_to_cam: 5873554c0a3aSHans de Goede if (pparm->algorithm == _NO_PRIVACY_) { 5874554c0a3aSHans de Goede while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1)) >= 0) { 587579df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 587679df841bSFabio Aiuto "clear key for addr:%pM, camid:%d\n", 587779df841bSFabio Aiuto MAC_ARG(pparm->addr), cam_id); 5878554c0a3aSHans de Goede clear_cam_entry(padapter, cam_id); 5879554c0a3aSHans de Goede rtw_camid_free(padapter, cam_id); 5880554c0a3aSHans de Goede } 5881554c0a3aSHans de Goede } else { 588279df841bSFabio Aiuto netdev_dbg(padapter->pnetdev, 588379df841bSFabio Aiuto "set pairwise key camid:%d, addr:%pM, kid:%d, type:%s\n", 588479df841bSFabio Aiuto cam_id, MAC_ARG(pparm->addr), pparm->keyid, 588579df841bSFabio Aiuto security_type_str(pparm->algorithm)); 5886554c0a3aSHans de Goede ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid; 5887554c0a3aSHans de Goede write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key); 5888554c0a3aSHans de Goede } 5889554c0a3aSHans de Goede ret = H2C_SUCCESS_RSP; 5890554c0a3aSHans de Goede 5891554c0a3aSHans de Goede exit: 5892554c0a3aSHans de Goede return ret; 5893554c0a3aSHans de Goede } 5894554c0a3aSHans de Goede 5895554c0a3aSHans de Goede u8 add_ba_hdl(struct adapter *padapter, unsigned char *pbuf) 5896554c0a3aSHans de Goede { 5897554c0a3aSHans de Goede struct addBaReq_parm *pparm = (struct addBaReq_parm *)pbuf; 5898554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5899554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5900554c0a3aSHans de Goede 5901554c0a3aSHans de Goede struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr); 5902554c0a3aSHans de Goede 5903554c0a3aSHans de Goede if (!psta) 5904554c0a3aSHans de Goede return H2C_SUCCESS; 5905554c0a3aSHans de Goede 5906554c0a3aSHans de Goede if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) || 5907554c0a3aSHans de Goede ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) { 5908554c0a3aSHans de Goede /* pmlmeinfo->ADDBA_retry_count = 0; */ 5909554c0a3aSHans de Goede /* pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid); */ 5910554c0a3aSHans de Goede /* psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid); */ 5911f4acd33cSRoss Schmidt issue_action_BA(padapter, pparm->addr, WLAN_ACTION_ADDBA_REQ, (u16)pparm->tid); 5912554c0a3aSHans de Goede /* _set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO); */ 5913554c0a3aSHans de Goede _set_timer(&psta->addba_retry_timer, ADDBA_TO); 5914554c0a3aSHans de Goede } else { 5915554c0a3aSHans de Goede psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid); 5916554c0a3aSHans de Goede } 5917554c0a3aSHans de Goede return H2C_SUCCESS; 5918554c0a3aSHans de Goede } 5919554c0a3aSHans de Goede 5920554c0a3aSHans de Goede 5921554c0a3aSHans de Goede u8 chk_bmc_sleepq_cmd(struct adapter *padapter) 5922554c0a3aSHans de Goede { 5923554c0a3aSHans de Goede struct cmd_obj *ph2c; 5924554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 5925554c0a3aSHans de Goede u8 res = _SUCCESS; 5926554c0a3aSHans de Goede 59272ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 5928554c0a3aSHans de Goede if (ph2c == NULL) { 5929554c0a3aSHans de Goede res = _FAIL; 5930554c0a3aSHans de Goede goto exit; 5931554c0a3aSHans de Goede } 5932554c0a3aSHans de Goede 5933554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq)); 5934554c0a3aSHans de Goede 5935554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 5936554c0a3aSHans de Goede 5937554c0a3aSHans de Goede exit: 5938554c0a3aSHans de Goede return res; 5939554c0a3aSHans de Goede } 5940554c0a3aSHans de Goede 5941554c0a3aSHans de Goede u8 set_tx_beacon_cmd(struct adapter *padapter) 5942554c0a3aSHans de Goede { 5943554c0a3aSHans de Goede struct cmd_obj *ph2c; 5944554c0a3aSHans de Goede struct Tx_Beacon_param *ptxBeacon_parm; 5945554c0a3aSHans de Goede struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 5946554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 5947554c0a3aSHans de Goede struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); 5948554c0a3aSHans de Goede u8 res = _SUCCESS; 5949554c0a3aSHans de Goede int len_diff = 0; 5950554c0a3aSHans de Goede 59512ef2b7c2SJoe Perches ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); 5952554c0a3aSHans de Goede if (ph2c == NULL) { 5953554c0a3aSHans de Goede res = _FAIL; 5954554c0a3aSHans de Goede goto exit; 5955554c0a3aSHans de Goede } 5956554c0a3aSHans de Goede 59572ef2b7c2SJoe Perches ptxBeacon_parm = rtw_zmalloc(sizeof(struct Tx_Beacon_param)); 5958554c0a3aSHans de Goede if (ptxBeacon_parm == NULL) { 59598f24f505SMadhumitha Prabakaran kfree(ph2c); 5960554c0a3aSHans de Goede res = _FAIL; 5961554c0a3aSHans de Goede goto exit; 5962554c0a3aSHans de Goede } 5963554c0a3aSHans de Goede 5964554c0a3aSHans de Goede memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(struct wlan_bssid_ex)); 5965554c0a3aSHans de Goede 59665641eeecSRoss Schmidt len_diff = update_hidden_ssid(ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_, 59675641eeecSRoss Schmidt ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_, 59685641eeecSRoss Schmidt pmlmeinfo->hidden_ssid_mode); 5969554c0a3aSHans de Goede ptxBeacon_parm->network.IELength += len_diff; 5970554c0a3aSHans de Goede 5971554c0a3aSHans de Goede init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon)); 5972554c0a3aSHans de Goede 5973554c0a3aSHans de Goede res = rtw_enqueue_cmd(pcmdpriv, ph2c); 5974554c0a3aSHans de Goede 5975554c0a3aSHans de Goede exit: 5976554c0a3aSHans de Goede return res; 5977554c0a3aSHans de Goede } 5978554c0a3aSHans de Goede 5979ffc49b55SFabio Aiuto static struct fwevent wlanevents[] = { 5980ffc49b55SFabio Aiuto {0, rtw_dummy_event_callback}, /*0*/ 5981ffc49b55SFabio Aiuto {0, NULL}, 5982ffc49b55SFabio Aiuto {0, NULL}, 5983ffc49b55SFabio Aiuto {0, NULL}, 5984ffc49b55SFabio Aiuto {0, NULL}, 5985ffc49b55SFabio Aiuto {0, NULL}, 5986ffc49b55SFabio Aiuto {0, NULL}, 5987ffc49b55SFabio Aiuto {0, NULL}, 5988ffc49b55SFabio Aiuto {0, &rtw_survey_event_callback}, /*8*/ 5989ffc49b55SFabio Aiuto {sizeof(struct surveydone_event), &rtw_surveydone_event_callback}, /*9*/ 5990ffc49b55SFabio Aiuto 5991ffc49b55SFabio Aiuto {0, &rtw_joinbss_event_callback}, /*10*/ 5992ffc49b55SFabio Aiuto {sizeof(struct stassoc_event), &rtw_stassoc_event_callback}, 5993ffc49b55SFabio Aiuto {sizeof(struct stadel_event), &rtw_stadel_event_callback}, 5994ffc49b55SFabio Aiuto {0, &rtw_atimdone_event_callback}, 5995ffc49b55SFabio Aiuto {0, rtw_dummy_event_callback}, 5996ffc49b55SFabio Aiuto {0, NULL}, /*15*/ 5997ffc49b55SFabio Aiuto {0, NULL}, 5998ffc49b55SFabio Aiuto {0, NULL}, 5999ffc49b55SFabio Aiuto {0, NULL}, 6000ffc49b55SFabio Aiuto {0, rtw_fwdbg_event_callback}, 6001ffc49b55SFabio Aiuto {0, NULL}, /*20*/ 6002ffc49b55SFabio Aiuto {0, NULL}, 6003ffc49b55SFabio Aiuto {0, NULL}, 6004ffc49b55SFabio Aiuto {0, &rtw_cpwm_event_callback}, 6005ffc49b55SFabio Aiuto {0, NULL}, 6006ffc49b55SFabio Aiuto {0, &rtw_wmm_event_callback}, 6007ffc49b55SFabio Aiuto 6008ffc49b55SFabio Aiuto }; 6009554c0a3aSHans de Goede 6010554c0a3aSHans de Goede u8 mlme_evt_hdl(struct adapter *padapter, unsigned char *pbuf) 6011554c0a3aSHans de Goede { 6012554c0a3aSHans de Goede u8 evt_code, evt_seq; 6013554c0a3aSHans de Goede u16 evt_sz; 6014554c0a3aSHans de Goede uint *peventbuf; 6015554c0a3aSHans de Goede void (*event_callback)(struct adapter *dev, u8 *pbuf); 6016554c0a3aSHans de Goede struct evt_priv *pevt_priv = &(padapter->evtpriv); 6017554c0a3aSHans de Goede 6018554c0a3aSHans de Goede if (pbuf == NULL) 6019554c0a3aSHans de Goede goto _abort_event_; 6020554c0a3aSHans de Goede 6021554c0a3aSHans de Goede peventbuf = (uint *)pbuf; 6022554c0a3aSHans de Goede evt_sz = (u16)(*peventbuf&0xffff); 6023554c0a3aSHans de Goede evt_seq = (u8)((*peventbuf>>24)&0x7f); 6024554c0a3aSHans de Goede evt_code = (u8)((*peventbuf>>16)&0xff); 6025554c0a3aSHans de Goede 6026554c0a3aSHans de Goede 6027554c0a3aSHans de Goede #ifdef CHECK_EVENT_SEQ 6028554c0a3aSHans de Goede /* checking event sequence... */ 6029554c0a3aSHans de Goede if (evt_seq != (atomic_read(&pevt_priv->event_seq) & 0x7f)) { 6030554c0a3aSHans de Goede pevt_priv->event_seq = (evt_seq+1)&0x7f; 6031554c0a3aSHans de Goede 6032554c0a3aSHans de Goede goto _abort_event_; 6033554c0a3aSHans de Goede } 6034554c0a3aSHans de Goede #endif 6035554c0a3aSHans de Goede 6036554c0a3aSHans de Goede /* checking if event code is valid */ 60370ac666f8SFabio Aiuto if (evt_code >= MAX_C2HEVT) 6038554c0a3aSHans de Goede goto _abort_event_; 6039554c0a3aSHans de Goede 6040554c0a3aSHans de Goede /* checking if event size match the event parm size */ 6041554c0a3aSHans de Goede if ((wlanevents[evt_code].parmsize != 0) && 60420ac666f8SFabio Aiuto (wlanevents[evt_code].parmsize != evt_sz)) 6043554c0a3aSHans de Goede goto _abort_event_; 6044554c0a3aSHans de Goede 6045554c0a3aSHans de Goede atomic_inc(&pevt_priv->event_seq); 6046554c0a3aSHans de Goede 6047554c0a3aSHans de Goede peventbuf += 2; 6048554c0a3aSHans de Goede 6049554c0a3aSHans de Goede if (peventbuf) { 6050554c0a3aSHans de Goede event_callback = wlanevents[evt_code].event_callback; 6051554c0a3aSHans de Goede event_callback(padapter, (u8 *)peventbuf); 6052554c0a3aSHans de Goede 6053554c0a3aSHans de Goede pevt_priv->evt_done_cnt++; 6054554c0a3aSHans de Goede } 6055554c0a3aSHans de Goede 6056554c0a3aSHans de Goede 6057554c0a3aSHans de Goede _abort_event_: 6058554c0a3aSHans de Goede 6059554c0a3aSHans de Goede 6060554c0a3aSHans de Goede return H2C_SUCCESS; 6061554c0a3aSHans de Goede 6062554c0a3aSHans de Goede } 6063554c0a3aSHans de Goede 6064554c0a3aSHans de Goede u8 h2c_msg_hdl(struct adapter *padapter, unsigned char *pbuf) 6065554c0a3aSHans de Goede { 6066554c0a3aSHans de Goede if (!pbuf) 6067554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6068554c0a3aSHans de Goede 6069554c0a3aSHans de Goede return H2C_SUCCESS; 6070554c0a3aSHans de Goede } 6071554c0a3aSHans de Goede 6072554c0a3aSHans de Goede u8 chk_bmc_sleepq_hdl(struct adapter *padapter, unsigned char *pbuf) 6073554c0a3aSHans de Goede { 6074554c0a3aSHans de Goede struct sta_info *psta_bmc; 6075554c0a3aSHans de Goede struct list_head *xmitframe_plist, *xmitframe_phead; 6076554c0a3aSHans de Goede struct xmit_frame *pxmitframe = NULL; 6077554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 6078554c0a3aSHans de Goede struct sta_priv *pstapriv = &padapter->stapriv; 6079554c0a3aSHans de Goede 6080554c0a3aSHans de Goede /* for BC/MC Frames */ 6081554c0a3aSHans de Goede psta_bmc = rtw_get_bcmc_stainfo(padapter); 6082554c0a3aSHans de Goede if (!psta_bmc) 6083554c0a3aSHans de Goede return H2C_SUCCESS; 6084554c0a3aSHans de Goede 6085554c0a3aSHans de Goede if ((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len > 0)) { 6086554c0a3aSHans de Goede msleep(10);/* 10ms, ATIM(HIQ) Windows */ 6087554c0a3aSHans de Goede 6088554c0a3aSHans de Goede /* spin_lock_bh(&psta_bmc->sleep_q.lock); */ 6089554c0a3aSHans de Goede spin_lock_bh(&pxmitpriv->lock); 6090554c0a3aSHans de Goede 6091554c0a3aSHans de Goede xmitframe_phead = get_list_head(&psta_bmc->sleep_q); 6092b3cd518cSGuenter Roeck list_for_each(xmitframe_plist, xmitframe_phead) { 6093b3cd518cSGuenter Roeck pxmitframe = list_entry(xmitframe_plist, 6094b3cd518cSGuenter Roeck struct xmit_frame, list); 6095554c0a3aSHans de Goede 6096554c0a3aSHans de Goede list_del_init(&pxmitframe->list); 6097554c0a3aSHans de Goede 6098554c0a3aSHans de Goede psta_bmc->sleepq_len--; 6099554c0a3aSHans de Goede if (psta_bmc->sleepq_len > 0) 6100554c0a3aSHans de Goede pxmitframe->attrib.mdata = 1; 6101554c0a3aSHans de Goede else 6102554c0a3aSHans de Goede pxmitframe->attrib.mdata = 0; 6103554c0a3aSHans de Goede 6104554c0a3aSHans de Goede pxmitframe->attrib.triggered = 1; 6105554c0a3aSHans de Goede 61060ad02fa8SGeorgiana Chelu if (xmitframe_hiq_filter(pxmitframe)) 6107554c0a3aSHans de Goede pxmitframe->attrib.qsel = 0x11;/* HIQ */ 6108554c0a3aSHans de Goede 6109554c0a3aSHans de Goede rtw_hal_xmitframe_enqueue(padapter, pxmitframe); 6110554c0a3aSHans de Goede } 6111554c0a3aSHans de Goede 6112554c0a3aSHans de Goede /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ 6113554c0a3aSHans de Goede spin_unlock_bh(&pxmitpriv->lock); 6114554c0a3aSHans de Goede 6115554c0a3aSHans de Goede /* check hi queue and bmc_sleepq */ 6116554c0a3aSHans de Goede rtw_chk_hi_queue_cmd(padapter); 6117554c0a3aSHans de Goede } 6118554c0a3aSHans de Goede 6119554c0a3aSHans de Goede return H2C_SUCCESS; 6120554c0a3aSHans de Goede } 6121554c0a3aSHans de Goede 6122554c0a3aSHans de Goede u8 tx_beacon_hdl(struct adapter *padapter, unsigned char *pbuf) 6123554c0a3aSHans de Goede { 6124709c8e49SFabio Aiuto if (send_beacon(padapter) == _FAIL) 6125554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6126554c0a3aSHans de Goede 6127554c0a3aSHans de Goede /* tx bc/mc frames after update TIM */ 6128554c0a3aSHans de Goede chk_bmc_sleepq_hdl(padapter, NULL); 6129554c0a3aSHans de Goede 6130554c0a3aSHans de Goede return H2C_SUCCESS; 6131554c0a3aSHans de Goede } 6132554c0a3aSHans de Goede 6133554c0a3aSHans de Goede int rtw_chk_start_clnt_join(struct adapter *padapter, u8 *ch, u8 *bw, u8 *offset) 6134554c0a3aSHans de Goede { 6135554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6136554c0a3aSHans de Goede unsigned char cur_ch = pmlmeext->cur_channel; 6137554c0a3aSHans de Goede unsigned char cur_bw = pmlmeext->cur_bwmode; 6138554c0a3aSHans de Goede unsigned char cur_ch_offset = pmlmeext->cur_ch_offset; 6139554c0a3aSHans de Goede bool connect_allow = true; 6140554c0a3aSHans de Goede 6141554c0a3aSHans de Goede if (!ch || !bw || !offset) { 6142554c0a3aSHans de Goede rtw_warn_on(1); 6143554c0a3aSHans de Goede connect_allow = false; 6144554c0a3aSHans de Goede } 6145554c0a3aSHans de Goede 61460ad02fa8SGeorgiana Chelu if (connect_allow) { 6147554c0a3aSHans de Goede *ch = cur_ch; 6148554c0a3aSHans de Goede *bw = cur_bw; 6149554c0a3aSHans de Goede *offset = cur_ch_offset; 6150554c0a3aSHans de Goede } 6151554c0a3aSHans de Goede 615263a9c3edSJeeeun Evans return connect_allow ? _SUCCESS : _FAIL; 6153554c0a3aSHans de Goede } 6154554c0a3aSHans de Goede 6155554c0a3aSHans de Goede /* Find union about ch, bw, ch_offset of all linked/linking interfaces */ 6156554c0a3aSHans de Goede int rtw_get_ch_setting_union(struct adapter *adapter, u8 *ch, u8 *bw, u8 *offset) 6157554c0a3aSHans de Goede { 6158554c0a3aSHans de Goede struct dvobj_priv *dvobj = adapter_to_dvobj(adapter); 6159554c0a3aSHans de Goede struct adapter *iface; 6160554c0a3aSHans de Goede 6161554c0a3aSHans de Goede if (ch) 6162554c0a3aSHans de Goede *ch = 0; 6163554c0a3aSHans de Goede if (bw) 6164554c0a3aSHans de Goede *bw = CHANNEL_WIDTH_20; 6165554c0a3aSHans de Goede if (offset) 6166554c0a3aSHans de Goede *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; 6167554c0a3aSHans de Goede 6168554c0a3aSHans de Goede iface = dvobj->padapters; 6169554c0a3aSHans de Goede 6170554c0a3aSHans de Goede if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING)) 6171554c0a3aSHans de Goede return 0; 6172554c0a3aSHans de Goede 6173554c0a3aSHans de Goede return 1; 6174554c0a3aSHans de Goede } 6175554c0a3aSHans de Goede 6176554c0a3aSHans de Goede u8 set_ch_hdl(struct adapter *padapter, u8 *pbuf) 6177554c0a3aSHans de Goede { 6178554c0a3aSHans de Goede struct set_ch_parm *set_ch_parm; 6179554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6180554c0a3aSHans de Goede 6181554c0a3aSHans de Goede if (!pbuf) 6182554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6183554c0a3aSHans de Goede 6184554c0a3aSHans de Goede set_ch_parm = (struct set_ch_parm *)pbuf; 6185554c0a3aSHans de Goede 6186554c0a3aSHans de Goede pmlmeext->cur_channel = set_ch_parm->ch; 6187554c0a3aSHans de Goede pmlmeext->cur_ch_offset = set_ch_parm->ch_offset; 6188554c0a3aSHans de Goede pmlmeext->cur_bwmode = set_ch_parm->bw; 6189554c0a3aSHans de Goede 6190554c0a3aSHans de Goede set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw); 6191554c0a3aSHans de Goede 6192554c0a3aSHans de Goede return H2C_SUCCESS; 6193554c0a3aSHans de Goede } 6194554c0a3aSHans de Goede 6195554c0a3aSHans de Goede u8 set_chplan_hdl(struct adapter *padapter, unsigned char *pbuf) 6196554c0a3aSHans de Goede { 6197554c0a3aSHans de Goede struct SetChannelPlan_param *setChannelPlan_param; 6198554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 6199554c0a3aSHans de Goede 6200554c0a3aSHans de Goede if (!pbuf) 6201554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6202554c0a3aSHans de Goede 6203554c0a3aSHans de Goede setChannelPlan_param = (struct SetChannelPlan_param *)pbuf; 6204554c0a3aSHans de Goede 6205554c0a3aSHans de Goede pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set); 6206554c0a3aSHans de Goede init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list); 6207554c0a3aSHans de Goede 620834557e23SIzabela Bakollari if (padapter->rtw_wdev && padapter->rtw_wdev->wiphy) { 6209554c0a3aSHans de Goede struct regulatory_request request; 6210c926f022SSimran Singhal 6211554c0a3aSHans de Goede request.initiator = NL80211_REGDOM_SET_BY_DRIVER; 6212554c0a3aSHans de Goede rtw_reg_notifier(padapter->rtw_wdev->wiphy, &request); 6213554c0a3aSHans de Goede } 6214554c0a3aSHans de Goede 6215554c0a3aSHans de Goede return H2C_SUCCESS; 6216554c0a3aSHans de Goede } 6217554c0a3aSHans de Goede 6218554c0a3aSHans de Goede u8 set_csa_hdl(struct adapter *padapter, unsigned char *pbuf) 6219554c0a3aSHans de Goede { 6220554c0a3aSHans de Goede return H2C_REJECTED; 6221554c0a3aSHans de Goede } 6222554c0a3aSHans de Goede 6223554c0a3aSHans de Goede /* TDLS_ESTABLISHED : write RCR DATA BIT */ 6224554c0a3aSHans de Goede /* TDLS_CS_OFF : go back to the channel linked with AP, terminating channel switch procedure */ 6225554c0a3aSHans de Goede /* TDLS_INIT_CH_SEN : init channel sensing, receive all data and mgnt frame */ 6226554c0a3aSHans de Goede /* TDLS_DONE_CH_SEN: channel sensing and report candidate channel */ 6227554c0a3aSHans de Goede /* TDLS_OFF_CH : first time set channel to off channel */ 6228554c0a3aSHans de Goede /* TDLS_BASE_CH : go back tp the channel linked with AP when set base channel as target channel */ 6229554c0a3aSHans de Goede /* TDLS_P_OFF_CH : periodically go to off channel */ 6230554c0a3aSHans de Goede /* TDLS_P_BASE_CH : periodically go back to base channel */ 6231554c0a3aSHans de Goede /* TDLS_RS_RCR : restore RCR */ 6232554c0a3aSHans de Goede /* TDLS_TEAR_STA : free tdls sta */ 6233554c0a3aSHans de Goede u8 tdls_hdl(struct adapter *padapter, unsigned char *pbuf) 6234554c0a3aSHans de Goede { 6235554c0a3aSHans de Goede return H2C_REJECTED; 6236554c0a3aSHans de Goede } 6237554c0a3aSHans de Goede 6238554c0a3aSHans de Goede u8 run_in_thread_hdl(struct adapter *padapter, u8 *pbuf) 6239554c0a3aSHans de Goede { 6240554c0a3aSHans de Goede struct RunInThread_param *p; 6241554c0a3aSHans de Goede 6242554c0a3aSHans de Goede 6243554c0a3aSHans de Goede if (NULL == pbuf) 6244554c0a3aSHans de Goede return H2C_PARAMETERS_ERROR; 6245554c0a3aSHans de Goede p = (struct RunInThread_param *)pbuf; 6246554c0a3aSHans de Goede 6247554c0a3aSHans de Goede if (p->func) 6248554c0a3aSHans de Goede p->func(p->context); 6249554c0a3aSHans de Goede 6250554c0a3aSHans de Goede return H2C_SUCCESS; 6251554c0a3aSHans de Goede } 6252