| /* |
| * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. |
| * |
| * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| * |
| * |
| * Permission to use, copy, modify, and/or distribute this software for |
| * any purpose with or without fee is hereby granted, provided that the |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| |
| /* |
| * This file was originally distributed by Qualcomm Atheros, Inc. |
| * under proprietary terms before Copyright ownership was assigned |
| * to the Linux Foundation. |
| */ |
| |
| |
| /** ------------------------------------------------------------------------ * |
| ------------------------------------------------------------------------ * |
| |
| |
| \file wlan_hdd_wext.c |
| |
| \brief Airgo Linux Wireless Extensions Common Control Plane Types and |
| interfaces. |
| |
| $Id: wlan_hdd_wext.c,v 1.34 2007/04/14 01:49:23 jimz Exp jimz $This file defines all of the types that are utilized by the CCP module |
| of the "Portable" HDD. This file also includes the underlying Linux |
| Wireless Extensions Data types referred to by CCP. |
| |
| ======================================================================== */ |
| |
| #include <linux/version.h> |
| #include <linux/module.h> |
| #include <linux/kernel.h> |
| #include <linux/init.h> |
| #include <linux/wireless.h> |
| #include <macTrace.h> |
| #include <wlan_hdd_includes.h> |
| #include <wlan_nlink_common.h> |
| #include <vos_api.h> |
| #include <net/arp.h> |
| #include "ccmApi.h" |
| #include "sirParams.h" |
| #include "csrApi.h" |
| #include "csrInsideApi.h" |
| #if defined WLAN_FEATURE_VOWIFI |
| #include "smeRrmInternal.h" |
| #endif |
| #include <aniGlobal.h> |
| #include "dot11f.h" |
| #include <wlan_hdd_wowl.h> |
| #include <wlan_hdd_cfg.h> |
| #include <wlan_hdd_wmm.h> |
| #include "utilsApi.h" |
| #include "wlan_hdd_p2p.h" |
| #ifdef FEATURE_WLAN_TDLS |
| #include "wlan_hdd_tdls.h" |
| #endif |
| |
| #include "ieee80211_common.h" |
| #include "ol_if_athvar.h" |
| #include "dbglog_host.h" |
| #include "wma.h" |
| |
| #ifdef CONFIG_HAS_EARLYSUSPEND |
| #include <linux/earlysuspend.h> |
| #endif |
| #include "wlan_hdd_power.h" |
| #include "qwlan_version.h" |
| #include "wlan_hdd_host_offload.h" |
| #include "wlan_hdd_keep_alive.h" |
| #ifdef WLAN_FEATURE_PACKET_FILTERING |
| #include "wlan_hdd_packet_filtering.h" |
| #endif |
| |
| #include <linux/wireless.h> |
| #include <net/cfg80211.h> |
| #include "wlan_qct_tl.h" |
| |
| #include "wlan_hdd_misc.h" |
| |
| #include "wlan_hdd_dev_pwr.h" |
| #include "qc_sap_ioctl.h" |
| #include "sme_Api.h" |
| #include "wlan_qct_wda.h" |
| #include "vos_trace.h" |
| #include "wlan_hdd_assoc.h" |
| #include "adf_trace.h" |
| |
| #ifdef QCA_PKT_PROTO_TRACE |
| #include "vos_packet.h" |
| #endif /* QCA_PKT_PROTO_TRACE */ |
| |
| #ifdef CONFIG_HAS_EARLYSUSPEND |
| #include "wlan_hdd_cfg80211.h" |
| #endif |
| |
| #include "wlan_hdd_ocb.h" |
| #include "wlan_hdd_tsf.h" |
| #include "vos_nvitem.h" |
| #include "wlan_hdd_oemdata.h" |
| |
| #define HDD_FINISH_ULA_TIME_OUT 800 |
| #define HDD_SET_MCBC_FILTERS_TO_FW 1 |
| #define HDD_DELETE_MCBC_FILTERS_FROM_FW 0 |
| |
| static int ioctl_debug; |
| module_param(ioctl_debug, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); |
| |
| /* To Validate Channel against the Frequency and Vice-Versa */ |
| static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, |
| {2422, 3}, {2427, 4}, {2432, 5}, {2437, 6}, {2442, 7}, {2447, 8}, |
| {2452, 9}, {2457, 10}, {2462, 11}, {2467 ,12}, {2472, 13}, |
| {2484, 14}, {5180, 36}, {5200, 40}, {5220, 44}, |
| {5240, 48}, {5260, 52}, {5280, 56}, {5300, 60}, {5320, 64}, {5500, 100}, |
| {5520, 104}, {5540, 108}, {5560, 112}, {5580, 116}, {5600, 120}, |
| {5620, 124}, {5640, 128}, {5660, 132}, {5680, 136}, {5700, 140}, |
| {5720, 144}, {5745, 149}, {5765, 153}, {5785, 157}, {5805, 161}, |
| {5825, 165}, {5852, 170}, {5855, 171}, {5860, 172}, {5865, 173}, |
| {5870, 174}, {5875, 175}, {5880, 176}, {5885, 177}, {5890, 178}, |
| {5895, 179}, {5900, 180}, {5905, 181}, {5910, 182}, {5915, 183}, |
| {5920, 184} }; |
| |
| #define FREQ_CHAN_MAP_TABLE_SIZE (sizeof(freq_chan_map)/sizeof(freq_chan_map[0])) |
| |
| #define RC_2_RATE_IDX(_rc) ((_rc) & 0x7) |
| #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) |
| |
| #define RC_2_RATE_IDX_11AC(_rc) ((_rc) & 0xf) |
| #define HT_RC_2_STREAMS_11AC(_rc) ((((_rc) & 0x30) >> 4) + 1) |
| |
| /* Private ioctls and their sub-ioctls */ |
| #define WLAN_PRIV_SET_INT_GET_NONE (SIOCIWFIRSTPRIV + 0) |
| #define WE_SET_11D_STATE 1 |
| #define WE_WOWL 2 |
| #define WE_SET_POWER 3 |
| #define WE_SET_MAX_ASSOC 4 |
| #define WE_SET_SAP_AUTO_CHANNEL_SELECTION 5 |
| #define WE_SET_DATA_INACTIVITY_TO 6 |
| #define WE_SET_MAX_TX_POWER 7 |
| #define WE_SET_HIGHER_DTIM_TRANSITION 8 |
| #define WE_SET_TM_LEVEL 9 |
| #define WE_SET_PHYMODE 10 |
| #define WE_SET_NSS 11 |
| #define WE_SET_LDPC 12 |
| #define WE_SET_TX_STBC 13 |
| #define WE_SET_RX_STBC 14 |
| #define WE_SET_SHORT_GI 15 |
| #define WE_SET_RTSCTS 16 |
| #define WE_SET_CHWIDTH 17 |
| #define WE_SET_ANI_EN_DIS 18 |
| #define WE_SET_ANI_POLL_PERIOD 19 |
| #define WE_SET_ANI_LISTEN_PERIOD 20 |
| #define WE_SET_ANI_OFDM_LEVEL 21 |
| #define WE_SET_ANI_CCK_LEVEL 22 |
| #define WE_SET_DYNAMIC_BW 23 |
| #define WE_SET_TX_CHAINMASK 24 |
| #define WE_SET_RX_CHAINMASK 25 |
| #define WE_SET_11N_RATE 26 |
| #define WE_SET_AMPDU 27 |
| #define WE_SET_AMSDU 28 |
| #define WE_SET_TXPOW_2G 29 |
| #define WE_SET_TXPOW_5G 30 |
| /* Private ioctl for firmware debug log */ |
| #define WE_DBGLOG_LOG_LEVEL 31 |
| #define WE_DBGLOG_VAP_ENABLE 32 |
| #define WE_DBGLOG_VAP_DISABLE 33 |
| #define WE_DBGLOG_MODULE_ENABLE 34 |
| #define WE_DBGLOG_MODULE_DISABLE 35 |
| #define WE_DBGLOG_MOD_LOG_LEVEL 36 |
| #define WE_DBGLOG_TYPE 37 |
| #define WE_SET_TXRX_FWSTATS 38 |
| #define WE_SET_VHT_RATE 39 |
| #define WE_DBGLOG_REPORT_ENABLE 40 |
| #define WE_TXRX_FWSTATS_RESET 41 |
| #define WE_SET_MAX_TX_POWER_2_4 42 |
| #define WE_SET_MAX_TX_POWER_5_0 43 |
| /* 44 is unused */ |
| /* Private ioctl for packet power save */ |
| #define WE_PPS_PAID_MATCH 45 |
| #define WE_PPS_GID_MATCH 46 |
| #define WE_PPS_EARLY_TIM_CLEAR 47 |
| #define WE_PPS_EARLY_DTIM_CLEAR 48 |
| #define WE_PPS_EOF_PAD_DELIM 49 |
| #define WE_PPS_MACADDR_MISMATCH 50 |
| #define WE_PPS_DELIM_CRC_FAIL 51 |
| #define WE_PPS_GID_NSTS_ZERO 52 |
| #define WE_PPS_RSSI_CHECK 53 |
| /* 54 is unused */ |
| #define WE_SET_HTSMPS 55 |
| /* Private ioctl for QPower */ |
| #define WE_SET_QPOWER_MAX_PSPOLL_COUNT 56 |
| #define WE_SET_QPOWER_MAX_TX_BEFORE_WAKE 57 |
| #define WE_SET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL 58 |
| #define WE_SET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL 59 |
| |
| #define WE_SET_BURST_ENABLE 60 |
| #define WE_SET_BURST_DUR 61 |
| /* GTX Commands */ |
| #define WE_SET_GTX_HT_MCS 62 |
| #define WE_SET_GTX_VHT_MCS 63 |
| #define WE_SET_GTX_USRCFG 64 |
| #define WE_SET_GTX_THRE 65 |
| #define WE_SET_GTX_MARGIN 66 |
| #define WE_SET_GTX_STEP 67 |
| #define WE_SET_GTX_MINTPC 68 |
| #define WE_SET_GTX_BWMASK 69 |
| /* Private ioctl to configure MCC home channels time quota and latency */ |
| #define WE_MCC_CONFIG_LATENCY 70 |
| #define WE_MCC_CONFIG_QUOTA 71 |
| /* Private IOCTL for debug connection issues */ |
| #define WE_SET_DEBUG_LOG 72 |
| #define WE_SET_SCAN_BAND_PREFERENCE 73 |
| #ifdef WE_SET_TX_POWER |
| #undef WE_SET_TX_POWER |
| #endif |
| #define WE_SET_TX_POWER 74 |
| /* Private ioctl for earlyrx power save feature */ |
| #define WE_SET_EARLY_RX_ADJUST_ENABLE 75 |
| #define WE_SET_EARLY_RX_TGT_BMISS_NUM 76 |
| #define WE_SET_EARLY_RX_BMISS_SAMPLE_CYCLE 77 |
| #define WE_SET_EARLY_RX_SLOP_STEP 78 |
| #define WE_SET_EARLY_RX_INIT_SLOP 79 |
| #define WE_SET_EARLY_RX_ADJUST_PAUSE 80 |
| #define WE_SET_MC_RATE 81 |
| #define WE_SET_EARLY_RX_DRIFT_SAMPLE 82 |
| /* Private ioctl for packet power save */ |
| #define WE_PPS_5G_EBT 83 |
| #define WE_SET_CTS_CBW 84 |
| #define WE_DUMP_STATS 85 |
| #define WE_CLEAR_STATS 86 |
| #define WE_SET_CHANNEL 87 |
| |
| #define WE_SET_MODULATED_DTIM 88 |
| |
| #define WE_SET_MON_FILTER 89 |
| typedef enum eMonFilterType{ |
| MON_MGMT_PKT, |
| MON_CTRL_PKT, |
| MON_DATA_PKT, |
| MON_ALL_PKT, |
| } tMonFilterType; |
| |
| /* Private ioctls and their sub-ioctls */ |
| #define WLAN_PRIV_SET_NONE_GET_INT (SIOCIWFIRSTPRIV + 1) |
| #define WE_GET_11D_STATE 1 |
| #define WE_IBSS_STATUS 2 |
| #define WE_SET_SAP_CHANNELS 3 |
| #define WE_GET_WLAN_DBG 4 |
| #define WE_GET_MAX_ASSOC 6 |
| /* 7 is unused */ |
| #define WE_GET_SAP_AUTO_CHANNEL_SELECTION 8 |
| #define WE_GET_CONCURRENCY_MODE 9 |
| #define WE_GET_NSS 11 |
| #define WE_GET_LDPC 12 |
| #define WE_GET_TX_STBC 13 |
| #define WE_GET_RX_STBC 14 |
| #define WE_GET_SHORT_GI 15 |
| #define WE_GET_RTSCTS 16 |
| #define WE_GET_CHWIDTH 17 |
| #define WE_GET_ANI_EN_DIS 18 |
| #define WE_GET_ANI_POLL_PERIOD 19 |
| #define WE_GET_ANI_LISTEN_PERIOD 20 |
| #define WE_GET_ANI_OFDM_LEVEL 21 |
| #define WE_GET_ANI_CCK_LEVEL 22 |
| #define WE_GET_DYNAMIC_BW 23 |
| #define WE_GET_TX_CHAINMASK 24 |
| #define WE_GET_RX_CHAINMASK 25 |
| #define WE_GET_11N_RATE 26 |
| #define WE_GET_AMPDU 27 |
| #define WE_GET_AMSDU 28 |
| #define WE_GET_TXPOW_2G 29 |
| #define WE_GET_TXPOW_5G 30 |
| /* 31 is unused */ |
| #define WE_GET_PPS_PAID_MATCH 32 |
| #define WE_GET_PPS_GID_MATCH 33 |
| #define WE_GET_PPS_EARLY_TIM_CLEAR 34 |
| #define WE_GET_PPS_EARLY_DTIM_CLEAR 35 |
| #define WE_GET_PPS_EOF_PAD_DELIM 36 |
| #define WE_GET_PPS_MACADDR_MISMATCH 37 |
| #define WE_GET_PPS_DELIM_CRC_FAIL 38 |
| #define WE_GET_PPS_GID_NSTS_ZERO 39 |
| #define WE_GET_PPS_RSSI_CHECK 40 |
| /* Private ioctl for QPower */ |
| #define WE_GET_QPOWER_MAX_PSPOLL_COUNT 41 |
| #define WE_GET_QPOWER_MAX_TX_BEFORE_WAKE 42 |
| #define WE_GET_QPOWER_SPEC_PSPOLL_WAKE_INTERVAL 43 |
| #define WE_GET_QPOWER_SPEC_MAX_SPEC_NODATA_PSPOLL 44 |
| #define WE_GET_BURST_ENABLE 45 |
| #define WE_GET_BURST_DUR 46 |
| /* GTX Commands */ |
| #define WE_GET_GTX_HT_MCS 47 |
| #define WE_GET_GTX_VHT_MCS 48 |
| #define WE_GET_GTX_USRCFG 49 |
| #define WE_GET_GTX_THRE 50 |
| #define WE_GET_GTX_MARGIN 51 |
| #define WE_GET_GTX_STEP 52 |
| #define WE_GET_GTX_MINTPC 53 |
| #define WE_GET_GTX_BWMASK 54 |
| #define WE_GET_SCAN_BAND_PREFERENCE 55 |
| #define WE_GET_TEMPERATURE 56 |
| #define WE_GET_FW_STATUS 57 |
| #define WE_CAP_TSF 58 |
| |
| /* Private ioctls and their sub-ioctls */ |
| #define WLAN_PRIV_SET_INT_GET_INT (SIOCIWFIRSTPRIV + 2) |
| |
| /* Private ioctls and their sub-ioctls */ |
| #define WLAN_PRIV_SET_CHAR_GET_NONE (SIOCIWFIRSTPRIV + 3) |
| #define WE_WOWL_ADD_PTRN 1 |
| #define WE_WOWL_DEL_PTRN 2 |
| #if defined WLAN_FEATURE_VOWIFI |
| #define WE_NEIGHBOR_REPORT_REQUEST 3 |
| #endif |
| #define WE_SET_AP_WPS_IE 4 //This is called in station mode to set probe rsp ie. |
| #define WE_SET_CONFIG 5 |
| |
| /* Private ioctls and their sub-ioctls */ |
| #define WLAN_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV + 4) |
| #define WE_SET_WLAN_DBG 1 |
| #define WE_SET_DP_TRACE 2 |
| #define WE_SET_SAP_CHANNELS 3 |
| |
| /* Private ioctls and their sub-ioctls */ |
| #define WLAN_PRIV_GET_CHAR_SET_NONE (SIOCIWFIRSTPRIV + 5) |
| #define WE_WLAN_VERSION 1 |
| #define WE_GET_STATS 2 |
| #define WE_GET_CFG 3 |
| #define WE_GET_WMM_STATUS 4 |
| #define WE_GET_CHANNEL_LIST 5 |
| #ifdef WLAN_FEATURE_11AC |
| #define WE_GET_RSSI 6 |
| #endif |
| #ifdef FEATURE_WLAN_TDLS |
| #define WE_GET_TDLS_PEERS 8 |
| #endif |
| #ifdef WLAN_FEATURE_11W |
| #define WE_GET_11W_INFO 9 |
| #endif |
| #define WE_GET_STATES 10 |
| #define WE_GET_IBSS_STA_INFO 11 |
| #define WE_GET_PHYMODE 12 |
| #ifdef FEATURE_OEM_DATA_SUPPORT |
| #define WE_GET_OEM_DATA_CAP 13 |
| #endif |
| #define WE_GET_SNR 14 |
| |
| /* Private ioctls and their sub-ioctls */ |
| #define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6) |
| #define WE_ENABLE_DXE_STALL_DETECT 6 |
| #define WE_DISPLAY_DXE_SNAP_SHOT 7 |
| #define WE_SET_REASSOC_TRIGGER 8 |
| #define WE_DISPLAY_DATAPATH_SNAP_SHOT 9 |
| #define WE_IBSS_GET_PEER_INFO_ALL 10 |
| #define WE_DUMP_AGC_START 11 |
| #define WE_DUMP_AGC 12 |
| #define WE_DUMP_CHANINFO_START 13 |
| #define WE_DUMP_CHANINFO 14 |
| #define WE_DUMP_WATCHDOG 15 |
| #ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG |
| #define WE_DUMP_PCIE_LOG 16 |
| #endif |
| #define WE_GET_RECOVERY_STAT 17 |
| |
| /* Private ioctls and their sub-ioctls */ |
| #define WLAN_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV + 7) |
| #define WE_LOG_DUMP_CMD 1 |
| |
| #define WE_P2P_NOA_CMD 2 |
| //IOCTL to configure MCC params |
| #define WE_MCC_CONFIG_CREDENTIAL 3 |
| #define WE_MCC_CONFIG_PARAMS 4 |
| |
| #ifdef FEATURE_WLAN_TDLS |
| #define WE_TDLS_CONFIG_PARAMS 5 |
| #endif |
| #define WE_IBSS_GET_PEER_INFO 6 |
| #define WE_UNIT_TEST_CMD 7 |
| |
| #define WE_MTRACE_DUMP_CMD 8 |
| #define WE_MTRACE_SELECTIVE_MODULE_LOG_ENABLE_CMD 9 |
| |
| #ifdef WLAN_FEATURE_GPIO_LED_FLASHING |
| #define WE_LED_FLASHING_PARAM 10 |
| #endif |
| #ifdef MEMORY_DEBUG |
| #define WE_MEM_TRACE_DUMP 11 |
| #endif |
| #ifdef FEATURE_WLAN_TDLS |
| #undef MAX_VAR_ARGS |
| #define MAX_VAR_ARGS 11 |
| #else |
| #define MAX_VAR_ARGS 7 |
| #endif |
| |
| /* Private ioctls (with no sub-ioctls) */ |
| /* note that they must be odd so that they have "get" semantics */ |
| #define WLAN_PRIV_ADD_TSPEC (SIOCIWFIRSTPRIV + 9) |
| #define WLAN_PRIV_DEL_TSPEC (SIOCIWFIRSTPRIV + 11) |
| #define WLAN_PRIV_GET_TSPEC (SIOCIWFIRSTPRIV + 13) |
| |
| /* (SIOCIWFIRSTPRIV + 8) is currently unused */ |
| /* (SIOCIWFIRSTPRIV + 16) is currently unused */ |
| /* (SIOCIWFIRSTPRIV + 10) is currently unused */ |
| /* (SIOCIWFIRSTPRIV + 12) is currently unused */ |
| /* (SIOCIWFIRSTPRIV + 14) is currently unused */ |
| |
| #define WLAN_PRIV_SET_NONE_GET_THREE_INT (SIOCIWFIRSTPRIV + 15) |
| #define WE_GET_TSF 1 |
| |
| /* (SIOCIWFIRSTPRIV + 17) is currently unused */ |
| |
| #define WLAN_GET_ISOLATION (SIOCIWFIRSTPRIV + 19) |
| |
| #ifdef WLAN_FEATURE_VOWIFI_11R |
| #define WLAN_PRIV_SET_FTIES (SIOCIWFIRSTPRIV + 20) |
| #endif |
| |
| /* Private ioctl for setting the host offload feature */ |
| #define WLAN_PRIV_SET_HOST_OFFLOAD (SIOCIWFIRSTPRIV + 18) |
| |
| /* Private ioctl to get the statistics */ |
| #define WLAN_GET_WLAN_STATISTICS (SIOCIWFIRSTPRIV + 21) |
| |
| /* Private ioctl to set the Keep Alive Params */ |
| #define WLAN_SET_KEEPALIVE_PARAMS (SIOCIWFIRSTPRIV + 22) |
| #ifdef WLAN_FEATURE_PACKET_FILTERING |
| /* Private ioctl to set the Packet Filtering Params */ |
| #define WLAN_SET_PACKET_FILTER_PARAMS (SIOCIWFIRSTPRIV + 23) |
| #endif |
| |
| #ifdef FEATURE_WLAN_SCAN_PNO |
| /* Private ioctl to get the statistics */ |
| #define WLAN_SET_PNO (SIOCIWFIRSTPRIV + 24) |
| #endif |
| |
| #define WLAN_SET_BAND_CONFIG (SIOCIWFIRSTPRIV + 25) /*Don't change this number*/ |
| |
| #define WLAN_PRIV_SET_MCBC_FILTER (SIOCIWFIRSTPRIV + 26) |
| #define WLAN_PRIV_CLEAR_MCBC_FILTER (SIOCIWFIRSTPRIV + 27) |
| /* Private ioctl to trigger reassociation */ |
| |
| #define WLAN_SET_POWER_PARAMS (SIOCIWFIRSTPRIV + 29) |
| |
| /* 802.11p IOCTL */ |
| #define WLAN_SET_DOT11P_CHANNEL_SCHED (SIOCIWFIRSTPRIV + 30) |
| |
| #define WLAN_GET_LINK_SPEED (SIOCIWFIRSTPRIV + 31) |
| |
| /* Private ioctls and their sub-ioctls */ |
| #define WLAN_PRIV_SET_TWO_INT_GET_NONE (SIOCIWFIRSTPRIV + 28) |
| #define WE_SET_SMPS_PARAM 1 |
| #ifdef WLAN_DEBUG |
| #define WE_SET_FW_CRASH_INJECT 2 |
| #endif |
| #define WE_SET_MON_MODE_CHAN 3 |
| #define WE_DUMP_DP_TRACE_LEVEL 4 |
| |
| #define WLAN_STATS_INVALID 0 |
| #define WLAN_STATS_RETRY_CNT 1 |
| #define WLAN_STATS_MUL_RETRY_CNT 2 |
| #define WLAN_STATS_TX_FRM_CNT 3 |
| #define WLAN_STATS_RX_FRM_CNT 4 |
| #define WLAN_STATS_FRM_DUP_CNT 5 |
| #define WLAN_STATS_FAIL_CNT 6 |
| #define WLAN_STATS_RTS_FAIL_CNT 7 |
| #define WLAN_STATS_ACK_FAIL_CNT 8 |
| #define WLAN_STATS_RTS_SUC_CNT 9 |
| #define WLAN_STATS_RX_DISCARD_CNT 10 |
| #define WLAN_STATS_RX_ERROR_CNT 11 |
| #define WLAN_STATS_TX_BYTE_CNT 12 |
| |
| #define WLAN_STATS_RX_BYTE_CNT 13 |
| #define WLAN_STATS_RX_RATE 14 |
| #define WLAN_STATS_TX_RATE 15 |
| |
| #define WLAN_STATS_RX_UC_BYTE_CNT 16 |
| #define WLAN_STATS_RX_MC_BYTE_CNT 17 |
| #define WLAN_STATS_RX_BC_BYTE_CNT 18 |
| #define WLAN_STATS_TX_UC_BYTE_CNT 19 |
| #define WLAN_STATS_TX_MC_BYTE_CNT 20 |
| #define WLAN_STATS_TX_BC_BYTE_CNT 21 |
| |
| #define FILL_TLV(__p, __type, __size, __val, __tlen) do { \ |
| if ((__tlen + __size + 2) < WE_MAX_STR_LEN) \ |
| { \ |
| *__p++ = __type; \ |
| *__p++ = __size; \ |
| memcpy(__p, __val, __size); \ |
| __p += __size; \ |
| __tlen += __size + 2; \ |
| } \ |
| else \ |
| { \ |
| hddLog(VOS_TRACE_LEVEL_ERROR, "FILL_TLV Failed!!!"); \ |
| } \ |
| } while(0); |
| |
| #define VERSION_VALUE_MAX_LEN 32 |
| |
| #define TX_PER_TRACKING_DEFAULT_RATIO 5 |
| #define TX_PER_TRACKING_MAX_RATIO 10 |
| #define TX_PER_TRACKING_DEFAULT_WATERMARK 5 |
| |
| #define WLAN_ADAPTER 0 |
| #define P2P_ADAPTER 1 |
| |
| /*MCC Configuration parameters */ |
| enum { |
| MCC_SCHEDULE_TIME_SLICE_CFG_PARAM = 1, |
| MCC_MAX_NULL_SEND_TIME_CFG_PARAM, |
| MCC_TX_EARLY_STOP_TIME_CFG_PARAM, |
| MCC_RX_DRAIN_TIME_CFG_PARAM, |
| MCC_CHANNEL_SWITCH_TIME_CFG_PARAM, |
| MCC_MIN_CHANNEL_TIME_CFG_PARAM, |
| MCC_PARK_BEFORE_TBTT_CFG_PARAM, |
| MCC_MIN_AFTER_DTIM_CFG_PARAM, |
| MCC_TOO_CLOSE_MARGIN_CFG_PARAM, |
| }; |
| |
| static const struct qwlan_hw qwlan_hw_list[] = { |
| { |
| .id = AR6320_REV1_VERSION, |
| .subid = 0, |
| .name = "QCA6174_REV1", |
| }, |
| { |
| .id = AR6320_REV1_1_VERSION, |
| .subid = 0x1, |
| .name = "QCA6174_REV1_1", |
| }, |
| { |
| .id = AR6320_REV1_3_VERSION, |
| .subid = 0x2, |
| .name = "QCA6174_REV1_3", |
| }, |
| { |
| .id = AR6320_REV2_1_VERSION, |
| .subid = 0x4, |
| .name = "QCA6174_REV2_1", |
| }, |
| { |
| .id = AR6320_REV2_1_VERSION, |
| .subid = 0x5, |
| .name = "QCA6174_REV2_2", |
| }, |
| { |
| .id = AR6320_REV3_VERSION, |
| .subid = 0x6, |
| .name = "QCA6174_REV2.3", |
| }, |
| { |
| .id = AR6320_REV3_VERSION, |
| .subid = 0x8, |
| .name = "QCA6174_REV3", |
| }, |
| { |
| .id = AR6320_REV3_VERSION, |
| .subid = 0x9, |
| .name = "QCA6174_REV3_1", |
| }, |
| { |
| .id = AR6320_REV3_2_VERSION, |
| .subid = 0xA, |
| .name = "QCA6174_REV3_2", |
| }, |
| { |
| .id = AR6320_REV3_VERSION, |
| .subid = 0x0, |
| .name = "QCA9377_REV1", |
| }, |
| { |
| .id = QCA9377_REV1_1_VERSION, |
| .subid = 0x1, |
| .name = "QCA93x7_REV1_1", |
| }, |
| { |
| .id = QCA9379_REV1_VERSION, |
| .subid = 0xC, |
| .name = "QCA9379_REV1", |
| }, |
| { |
| .id = QCA9379_REV1_VERSION, |
| .subid = 0xD, |
| .name = "QCA9379_REV1_1", |
| } |
| }; |
| |
| int hdd_validate_mcc_config(hdd_adapter_t *pAdapter, v_UINT_t staId, |
| v_UINT_t arg1, v_UINT_t arg2, v_UINT_t arg3); |
| |
| #ifdef WLAN_FEATURE_PACKET_FILTERING |
| int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, |
| v_U8_t sessionId); |
| #endif |
| |
| /**--------------------------------------------------------------------------- |
| |
| \brief mem_alloc_copy_from_user_helper - |
| |
| Helper function to allocate buffer and copy user data. |
| |
| \param - wrqu - Pointer to IOCTL Data. |
| len - size |
| |
| \return - On Success pointer to buffer, On failure NULL |
| |
| --------------------------------------------------------------------------*/ |
| void *mem_alloc_copy_from_user_helper(const void *wrqu_data, size_t len) |
| { |
| u8 *ptr = NULL; |
| |
| /* in order to protect the code, an extra byte is post appended to the buffer |
| * and the null termination is added. However, when allocating (len+1) byte |
| * of memory, we need to make sure that there is no uint overflow when doing |
| * addition. In theory check len < UINT_MAX protects the uint overflow. For |
| * wlan private ioctl, the buffer size is much less than UINT_MAX, as a good |
| * guess, now, it is assumed that the private command buffer size is no |
| * greater than 4K (4096 bytes). So we use 4096 as the upper boundary for now. |
| */ |
| if (len > MAX_USER_COMMAND_SIZE) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "Invalid length"); |
| return NULL; |
| } |
| |
| |
| ptr = vos_mem_malloc(len + 1); |
| if (NULL == ptr) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "unable to allocate memory"); |
| return NULL; |
| } |
| |
| if (copy_from_user(ptr, wrqu_data, len)) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: failed to copy data to user buffer", __func__); |
| vos_mem_free(ptr); |
| return NULL; |
| } |
| ptr[len] = '\0'; |
| return ptr; |
| } |
| |
| /**--------------------------------------------------------------------------- |
| |
| \brief hdd_priv_get_data - |
| |
| Helper function to get compatible struct iw_point passed to ioctl |
| |
| \param - p_priv_data - pointer to iw_point struct to be filled |
| wrqu - Pointer to IOCTL Data received from user space |
| |
| \return - 0 if p_priv_data successfully filled |
| error otherwise |
| |
| --------------------------------------------------------------------------*/ |
| int hdd_priv_get_data(struct iw_point *p_priv_data, |
| union iwreq_data *wrqu) |
| { |
| if ((NULL == p_priv_data) || (NULL == wrqu)) { |
| return -EINVAL; |
| } |
| |
| #ifdef CONFIG_COMPAT |
| #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0)) && defined(CONFIG_X86_64) |
| if (in_compat_syscall()) { |
| #else |
| if (is_compat_task()) { |
| #endif |
| struct compat_iw_point *p_compat_priv_data; |
| |
| /* Compat task: typecast to compat structure and copy the members. */ |
| p_compat_priv_data = (struct compat_iw_point *) &wrqu->data; |
| |
| p_priv_data->pointer = compat_ptr(p_compat_priv_data->pointer); |
| p_priv_data->length = p_compat_priv_data->length; |
| p_priv_data->flags = p_compat_priv_data->flags; |
| } else { |
| #endif /* #ifdef CONFIG_COMPAT */ |
| |
| /* Non compat task: directly copy the structure. */ |
| memcpy(p_priv_data, &wrqu->data, sizeof(struct iw_point)); |
| |
| #ifdef CONFIG_COMPAT |
| } |
| #endif /* #ifdef CONFIG_COMPAT */ |
| |
| return 0; |
| } |
| |
| #define WLAN_HDD_MAX_BW_VALUE 5 |
| |
| /** |
| * wlan_hdd_validate_mon_channel() - check channel number is valid or not |
| * @channel: channel number |
| * |
| * @return: VOS_STATUS |
| */ |
| VOS_STATUS wlan_hdd_validate_mon_channel(int channel) |
| { |
| uint8_t fValidChannel = FALSE, count = 0; |
| |
| for (count = RF_CHAN_1; count <= RF_CHAN_165; count++) |
| { |
| if ( channel == rfChannels[count].channelNum ) |
| { |
| fValidChannel = TRUE; |
| break; |
| } |
| } |
| if (fValidChannel != TRUE) |
| { |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| "%s: Invalid Channel [%d]", __func__, channel); |
| return VOS_STATUS_E_FAILURE; |
| } |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| /** |
| * wlan_hdd_validate_mon_bw() - check bandwidth value is valid or not |
| * @bw: bandwidth value |
| * |
| * @return: VOS_STATUS |
| */ |
| VOS_STATUS wlan_hdd_validate_mon_bw(int bw) |
| { |
| if (bw >= 0 && bw <= WLAN_HDD_MAX_BW_VALUE) |
| return VOS_STATUS_SUCCESS; |
| |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| /**--------------------------------------------------------------------------- |
| |
| \brief hdd_wlan_get_stats - |
| |
| Helper function to get stats |
| |
| \param - pAdapter Pointer to the adapter. |
| wrqu - Pointer to IOCTL REQUEST Data. |
| extra - Pointer to char |
| |
| |
| \return - zero on success, non zero value on failure |
| |
| --------------------------------------------------------------------------*/ |
| int hdd_wlan_get_stats(hdd_adapter_t *pAdapter, v_U16_t *length, |
| char *buffer, v_U16_t buf_len) |
| { |
| hdd_tx_rx_stats_t *pStats = &pAdapter->hdd_stats.hddTxRxStats; |
| v_U32_t len; |
| __u32 total_rxPkt = 0, total_rxDropped = 0; |
| __u32 total_rxDelv = 0, total_rxRefused = 0; |
| int i = 0, ret; |
| VOS_STATUS status; |
| |
| for (; i < NUM_CPUS; i++) { |
| total_rxPkt += pStats->rxPackets[i]; |
| total_rxDropped += pStats->rxDropped[i]; |
| total_rxDelv += pStats->rxDelivered[i]; |
| total_rxRefused += pStats->rxRefused[i]; |
| } |
| |
| len = snprintf(buffer, buf_len, |
| "\nTransmit" |
| "\n called %u, dropped %u," |
| "\n dropped BK %u, BE %u, VI %u, VO %u" |
| "\n classified BK %u, BE %u, VI %u, VO %u" |
| "\n completed %u," |
| "\n\nReceive Total" |
| "\n packets %u, dropped %u, delivered %u, refused %u" |
| "\n", |
| pStats->txXmitCalled, |
| pStats->txXmitDropped, |
| |
| pStats->txXmitDroppedAC[WLANTL_AC_BK], |
| pStats->txXmitDroppedAC[WLANTL_AC_BE], |
| pStats->txXmitDroppedAC[WLANTL_AC_VI], |
| pStats->txXmitDroppedAC[WLANTL_AC_VO], |
| |
| pStats->txXmitClassifiedAC[WLANTL_AC_BK], |
| pStats->txXmitClassifiedAC[WLANTL_AC_BE], |
| pStats->txXmitClassifiedAC[WLANTL_AC_VI], |
| pStats->txXmitClassifiedAC[WLANTL_AC_VO], |
| |
| pStats->txCompleted, |
| total_rxPkt, total_rxDropped, total_rxDelv, total_rxRefused); |
| |
| if (len >= buf_len) { |
| hddLog(LOGE,FL("Insufficient buffer:%d, %d"), buf_len, len); |
| return -E2BIG; |
| } |
| |
| for (i = 0; i < NUM_CPUS; i++) { |
| ret = snprintf(buffer+len, buf_len-len, |
| "\nReceive CPU: %d" |
| "\n packets %u, dropped %u, delivered %u, refused %u", |
| i, pStats->rxPackets[i], pStats->rxDropped[i], |
| pStats->rxDelivered[i], pStats->rxRefused[i]); |
| if (ret >= (buf_len-len)) { |
| hddLog(LOGE,FL("Insufficient buffer:%d, %d"), (buf_len-len), ret); |
| return -E2BIG; |
| } |
| len += ret; |
| } |
| ret = snprintf(buffer+len, buf_len-len, |
| "\n\nTX_FLOW" |
| "\nCurrent status %s" |
| "\ntx-flow timer start count %u" |
| "\npause count %u, unpause count %u\n", |
| (pStats->is_txflow_paused == TRUE ? "PAUSED" : "UNPAUSED"), |
| pStats->txflow_timer_cnt, |
| pStats->txflow_pause_cnt, |
| pStats->txflow_unpause_cnt |
| ); |
| |
| if (ret >= (buf_len-len)) { |
| hddLog(LOGE,FL("Insufficient buffer:%d, %d"), (buf_len-len), ret); |
| return -E2BIG; |
| } |
| len += ret; |
| |
| status = WLANTL_Get_llStats(pAdapter->sessionId, |
| &buffer[len], (buf_len - len)); |
| if (!VOS_IS_STATUS_SUCCESS(status)) { |
| hddLog(LOGE,FL("Error in getting stats:%d"), ret); |
| ret = (status == VOS_STATUS_E_NOMEM) ? -E2BIG: -EINVAL; |
| return ret; |
| } |
| |
| *length = strlen(buffer) + 1; |
| |
| return 0; |
| } |
| |
| /**--------------------------------------------------------------------------- |
| |
| \brief hdd_wlan_dump_stats - |
| |
| Helper function to dump stats |
| |
| \param - pAdapter Pointer to the adapter. |
| value - value given by user |
| |
| \return - none |
| |
| --------------------------------------------------------------------------*/ |
| void hdd_wlan_dump_stats(hdd_adapter_t *pAdapter, int value) |
| { |
| hdd_context_t* hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| |
| switch(value) |
| { |
| case WLAN_TXRX_HIST_STATS: |
| wlan_hdd_display_tx_rx_histogram(hdd_ctx); |
| break; |
| case WLAN_HDD_NETIF_OPER_HISTORY: |
| wlan_hdd_display_netif_queue_history(hdd_ctx); |
| break; |
| default: |
| WLANTL_display_datapath_stats(hdd_ctx->pvosContext, value); |
| break; |
| } |
| } |
| |
| /**--------------------------------------------------------------------------- |
| |
| \brief hdd_wlan_get_version() - |
| |
| This function use to get Wlan Driver, Firmware, & Hardware Version. |
| |
| \param - pAdapter Pointer to the adapter. |
| wrqu - Pointer to IOCTL REQUEST Data. |
| extra - Pointer to char |
| |
| \return - none |
| |
| --------------------------------------------------------------------------*/ |
| void hdd_wlan_get_version(hdd_adapter_t *pAdapter, union iwreq_data *wrqu, |
| char *extra) |
| { |
| tSirVersionString wcnss_SW_version; |
| const char *pSWversion; |
| const char *pHWversion; |
| v_U32_t MSPId = 0, mSPId = 0, SIId = 0, CRMId = 0; |
| |
| hdd_context_t *pHddContext; |
| int i = 0; |
| |
| pHddContext = WLAN_HDD_GET_CTX(pAdapter); |
| if (!pHddContext) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s:Invalid context, HDD context is null", __func__); |
| goto error; |
| } |
| |
| snprintf(wcnss_SW_version, sizeof(tSirVersionString), "%08x", |
| pHddContext->target_fw_version); |
| |
| pSWversion = wcnss_SW_version; |
| MSPId = (pHddContext->target_fw_version & 0xf0000000) >> 28; |
| mSPId = (pHddContext->target_fw_version & 0xf000000) >> 24; |
| SIId = (pHddContext->target_fw_version & 0xf00000) >> 20; |
| CRMId = pHddContext->target_fw_version & 0x7fff; |
| |
| for (i = 0; i < ARRAY_SIZE(qwlan_hw_list); i++) { |
| if (pHddContext->target_hw_version == qwlan_hw_list[i].id && |
| pHddContext->target_hw_revision == qwlan_hw_list[i].subid) { |
| pHWversion = qwlan_hw_list[i].name; |
| break; |
| } |
| } |
| |
| if (i == ARRAY_SIZE(qwlan_hw_list)) |
| pHWversion = "Unknown"; |
| pHddContext->target_hw_name = pHWversion; |
| |
| if (wrqu) { |
| wrqu->data.length = scnprintf(extra, WE_MAX_STR_LEN, |
| "Host SW:%s, FW:%d.%d.%d.%d, HW:%s", |
| QWLAN_VERSIONSTR, |
| MSPId, |
| mSPId, |
| SIId, |
| CRMId, |
| pHWversion); |
| } else { |
| pr_info("Host SW:%s, FW:%d.%d.%d.%d, HW:%s\n", |
| QWLAN_VERSIONSTR, |
| MSPId, |
| mSPId, |
| SIId, |
| CRMId, |
| pHWversion); |
| } |
| error: |
| return; |
| } |
| |
| v_MACADDR_t* hdd_wlan_get_ibss_mac_addr_from_staid(hdd_adapter_t *pAdapter, v_U8_t staIdx) |
| { |
| v_U8_t idx; |
| hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| |
| for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ ) |
| { |
| if ( 0 != pHddStaCtx->conn_info.staId[ idx ] && |
| staIdx == pHddStaCtx->conn_info.staId[ idx ]) |
| { |
| return (&pHddStaCtx->conn_info.peerMacAddress[ idx ]); |
| } |
| } |
| return NULL; |
| } |
| |
| eHalStatus hdd_wlan_get_ibss_peer_info(hdd_adapter_t *pAdapter, v_U8_t staIdx) |
| { |
| eHalStatus status = eHAL_STATUS_FAILURE; |
| tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); |
| hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| tSirPeerInfoRspParams *pPeerInfo = &pStaCtx->ibss_peer_info; |
| |
| status = sme_RequestIBSSPeerInfo(hHal, pAdapter, hdd_get_ibss_peer_info_cb, |
| VOS_FALSE, staIdx); |
| |
| INIT_COMPLETION(pAdapter->ibss_peer_info_comp); |
| |
| if (eHAL_STATUS_SUCCESS == status) |
| { |
| unsigned long rc; |
| rc = wait_for_completion_timeout |
| (&pAdapter->ibss_peer_info_comp, |
| msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT)); |
| if (!rc) { |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| FL("failed wait on ibss_peer_info_comp")); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| /** Print the peer info */ |
| pr_info("pPeerInfo->numIBSSPeers = %d ", pPeerInfo->numPeers); |
| pr_info("============================================================"); |
| { |
| uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; |
| uint32_t tx_rate = pPeerInfo->peerInfoParams[0].txRate; |
| |
| vos_mem_copy(mac_addr, pPeerInfo->peerInfoParams[0].mac_addr, |
| sizeof(mac_addr)); |
| pr_info("PEER ADDR : %pM TxRate: %d Mbps RSSI: %d", |
| mac_addr, (int)tx_rate, (int)pPeerInfo->peerInfoParams[0].rssi); |
| } |
| } |
| else |
| { |
| hddLog(VOS_TRACE_LEVEL_WARN, |
| "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__); |
| } |
| |
| return status; |
| } |
| |
| eHalStatus hdd_wlan_get_ibss_peer_info_all(hdd_adapter_t *pAdapter) |
| { |
| eHalStatus status = eHAL_STATUS_FAILURE; |
| tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); |
| hdd_station_ctx_t *pStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| tSirPeerInfoRspParams *pPeerInfo = &pStaCtx->ibss_peer_info; |
| int i; |
| |
| status = sme_RequestIBSSPeerInfo(hHal, pAdapter, hdd_get_ibss_peer_info_cb, |
| VOS_TRUE, 0xFF); |
| INIT_COMPLETION(pAdapter->ibss_peer_info_comp); |
| |
| if (eHAL_STATUS_SUCCESS == status) |
| { |
| unsigned long rc; |
| rc = wait_for_completion_timeout |
| (&pAdapter->ibss_peer_info_comp, |
| msecs_to_jiffies(IBSS_PEER_INFO_REQ_TIMOEUT)); |
| if (!rc) { |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| FL("failed wait on ibss_peer_info_comp")); |
| return eHAL_STATUS_FAILURE; |
| } |
| |
| /** Print the peer info */ |
| pr_info("pPeerInfo->numIBSSPeers = %d ", (int)pPeerInfo->numPeers); |
| pr_info("============================================================"); |
| for (i = 0; i < pPeerInfo->numPeers; i++) { |
| uint8_t mac_addr[VOS_MAC_ADDR_SIZE]; |
| uint32_t tx_rate; |
| |
| tx_rate = pPeerInfo->peerInfoParams[i].txRate; |
| vos_mem_copy(mac_addr, pPeerInfo->peerInfoParams[i].mac_addr, |
| sizeof(mac_addr)); |
| |
| pr_info(" PEER ADDR : %pM TxRate: %d Mbps RSSI: %d", |
| mac_addr, (int)tx_rate, (int)pPeerInfo->peerInfoParams[i].rssi); |
| } |
| } |
| else |
| { |
| hddLog(VOS_TRACE_LEVEL_WARN, |
| "%s: Warning: sme_RequestIBSSPeerInfo Request failed", __func__); |
| } |
| |
| return status; |
| } |
| |
| int hdd_wlan_get_rts_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) |
| { |
| tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); |
| v_U32_t threshold = 0; |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| if (NULL == pAdapter) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: Adapter is NULL", __func__); |
| return -EINVAL; |
| } |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| |
| if ( eHAL_STATUS_SUCCESS != |
| ccmCfgGetInt(hHal, WNI_CFG_RTS_THRESHOLD, &threshold) ) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, |
| FL("failed to get ini parameter, WNI_CFG_RTS_THRESHOLD")); |
| return -EIO; |
| } |
| wrqu->rts.value = threshold; |
| |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, |
| ("Rts-Threshold=%d!!"), wrqu->rts.value); |
| |
| EXIT(); |
| |
| return 0; |
| } |
| int hdd_wlan_get_frag_threshold(hdd_adapter_t *pAdapter, union iwreq_data *wrqu) |
| { |
| tHalHandle hHal; |
| v_U32_t threshold = 0, ret; |
| hdd_context_t *hdd_ctx; |
| |
| ENTER(); |
| |
| if (NULL == pAdapter) { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: Adapter is NULL", __func__); |
| return -EINVAL; |
| } |
| |
| hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| |
| if ( ccmCfgGetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, &threshold) |
| != eHAL_STATUS_SUCCESS ) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, |
| FL("failed to get ini parameter, WNI_CFG_FRAGMENTATION_THRESHOLD")); |
| return -EIO; |
| } |
| wrqu->frag.value = threshold; |
| |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, |
| ("Frag-Threshold=%d!!"), wrqu->frag.value); |
| |
| EXIT(); |
| |
| return 0; |
| } |
| |
| int hdd_wlan_get_freq(v_U32_t channel, v_U32_t *pfreq) |
| { |
| int i; |
| if (channel > 0) |
| { |
| for (i=0; i < FREQ_CHAN_MAP_TABLE_SIZE; i++) |
| { |
| if (channel == freq_chan_map[i].chan) |
| { |
| *pfreq = freq_chan_map[i].freq; |
| return 1; |
| } |
| } |
| } |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, |
| ("Invalid channel no=%d!!"), channel); |
| return -EINVAL; |
| } |
| |
| static v_BOOL_t |
| hdd_IsAuthTypeRSN( tHalHandle halHandle, eCsrAuthType authType) |
| { |
| v_BOOL_t rsnType = VOS_FALSE; |
| // is the authType supported? |
| switch (authType) |
| { |
| case eCSR_AUTH_TYPE_NONE: //never used |
| rsnType = eANI_BOOLEAN_FALSE; |
| break; |
| // MAC layer authentication types |
| case eCSR_AUTH_TYPE_OPEN_SYSTEM: |
| rsnType = eANI_BOOLEAN_FALSE; |
| break; |
| case eCSR_AUTH_TYPE_SHARED_KEY: |
| rsnType = eANI_BOOLEAN_FALSE; |
| break; |
| case eCSR_AUTH_TYPE_AUTOSWITCH: |
| rsnType = eANI_BOOLEAN_FALSE; |
| break; |
| |
| // Upper layer authentication types |
| case eCSR_AUTH_TYPE_WPA: |
| rsnType = eANI_BOOLEAN_TRUE; |
| break; |
| case eCSR_AUTH_TYPE_WPA_PSK: |
| rsnType = eANI_BOOLEAN_TRUE; |
| break; |
| case eCSR_AUTH_TYPE_WPA_NONE: |
| rsnType = eANI_BOOLEAN_TRUE; |
| break; |
| #ifdef WLAN_FEATURE_VOWIFI_11R |
| case eCSR_AUTH_TYPE_FT_RSN: |
| #endif |
| case eCSR_AUTH_TYPE_RSN: |
| rsnType = eANI_BOOLEAN_TRUE; |
| break; |
| #ifdef WLAN_FEATURE_VOWIFI_11R |
| case eCSR_AUTH_TYPE_FT_RSN_PSK: |
| #endif |
| case eCSR_AUTH_TYPE_RSN_PSK: |
| #ifdef WLAN_FEATURE_11W |
| case eCSR_AUTH_TYPE_RSN_PSK_SHA256: |
| case eCSR_AUTH_TYPE_RSN_8021X_SHA256: |
| #endif |
| rsnType = eANI_BOOLEAN_TRUE; |
| break; |
| //case eCSR_AUTH_TYPE_FAILED: |
| case eCSR_AUTH_TYPE_UNKNOWN: |
| rsnType = eANI_BOOLEAN_FALSE; |
| break; |
| default: |
| hddLog(LOGE, FL("%s called with unknown authType - default to Open, None"), |
| __func__); |
| rsnType = eANI_BOOLEAN_FALSE; |
| break; |
| } |
| hddLog(LOGE, FL("%s called with authType: %d, returned: %d"), |
| __func__, authType, rsnType); |
| return rsnType; |
| } |
| |
| static void hdd_GetRssiCB( v_S7_t rssi, tANI_U32 staId, void *pContext ) |
| { |
| struct statsContext *pStatsContext; |
| hdd_adapter_t *pAdapter; |
| |
| if (ioctl_debug) |
| { |
| pr_info("%s: rssi [%d] STA [%d] pContext [%pK]\n", |
| __func__, (int)rssi, (int)staId, pContext); |
| } |
| |
| if (NULL == pContext) |
| { |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| "%s: Bad param, pContext [%pK]", |
| __func__, pContext); |
| return; |
| } |
| |
| pStatsContext = pContext; |
| pAdapter = pStatsContext->pAdapter; |
| |
| /* there is a race condition that exists between this callback |
| function and the caller since the caller could time out either |
| before or while this code is executing. we use a spinlock to |
| serialize these actions */ |
| spin_lock(&hdd_context_lock); |
| |
| if ((NULL == pAdapter) || (PEER_INFO_CONTEXT_MAGIC != pStatsContext->magic)) |
| { |
| /* the caller presumably timed out so there is nothing we can do */ |
| spin_unlock(&hdd_context_lock); |
| hddLog(VOS_TRACE_LEVEL_WARN, |
| "%s: Invalid context, pAdapter [%pK] magic [%08x]", |
| __func__, pAdapter, pStatsContext->magic); |
| if (ioctl_debug) |
| { |
| pr_info("%s: Invalid context, pAdapter [%pK] magic [%08x]\n", |
| __func__, pAdapter, pStatsContext->magic); |
| } |
| return; |
| } |
| |
| /* context is valid so caller is still waiting */ |
| |
| /* paranoia: invalidate the magic */ |
| pStatsContext->magic = 0; |
| |
| /* copy over the rssi */ |
| pAdapter->rssi = rssi; |
| |
| if (pAdapter->rssi > 0) |
| pAdapter->rssi = 0; |
| /* notify the caller */ |
| complete(&pStatsContext->completion); |
| |
| /* serialization is complete */ |
| spin_unlock(&hdd_context_lock); |
| } |
| |
| static void hdd_GetSnrCB(tANI_S8 snr, tANI_U32 staId, void *pContext) |
| { |
| struct statsContext *pStatsContext; |
| hdd_adapter_t *pAdapter; |
| |
| if (ioctl_debug) |
| { |
| pr_info("%s: snr [%d] STA [%d] pContext [%pK]\n", |
| __func__, (int)snr, (int)staId, pContext); |
| } |
| |
| if (NULL == pContext) |
| { |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| "%s: Bad param, pContext [%pK]", |
| __func__, pContext); |
| return; |
| } |
| |
| pStatsContext = pContext; |
| pAdapter = pStatsContext->pAdapter; |
| |
| /* there is a race condition that exists between this callback |
| function and the caller since the caller could time out either |
| before or while this code is executing. we use a spinlock to |
| serialize these actions */ |
| spin_lock(&hdd_context_lock); |
| |
| if ((NULL == pAdapter) || (SNR_CONTEXT_MAGIC != pStatsContext->magic)) |
| { |
| /* the caller presumably timed out so there is nothing we can do */ |
| spin_unlock(&hdd_context_lock); |
| hddLog(VOS_TRACE_LEVEL_WARN, |
| "%s: Invalid context, pAdapter [%pK] magic [%08x]", |
| __func__, pAdapter, pStatsContext->magic); |
| if (ioctl_debug) |
| { |
| pr_info("%s: Invalid context, pAdapter [%pK] magic [%08x]\n", |
| __func__, pAdapter, pStatsContext->magic); |
| } |
| return; |
| } |
| |
| /* context is valid so caller is still waiting */ |
| |
| /* paranoia: invalidate the magic */ |
| pStatsContext->magic = 0; |
| |
| /* copy over the snr */ |
| pAdapter->snr = snr; |
| |
| /* notify the caller */ |
| complete(&pStatsContext->completion); |
| |
| /* serialization is complete */ |
| spin_unlock(&hdd_context_lock); |
| } |
| |
| VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value) |
| { |
| struct statsContext context; |
| hdd_context_t *pHddCtx; |
| hdd_station_ctx_t *pHddStaCtx; |
| eHalStatus hstatus; |
| unsigned long rc; |
| |
| if (NULL == pAdapter) |
| { |
| hddLog(VOS_TRACE_LEVEL_WARN, |
| "%s: Invalid context, pAdapter", __func__); |
| return VOS_STATUS_E_FAULT; |
| } |
| if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!",__func__); |
| /* return a cached value */ |
| *rssi_value = pAdapter->rssi; |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| pHddCtx = WLAN_HDD_GET_CTX(pAdapter); |
| pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| |
| if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { |
| hddLog(LOG1, "%s: Not associated, rssi on disconnect %d", |
| __func__, pAdapter->rssi_on_disconnect); |
| *rssi_value = pAdapter->rssi_on_disconnect; |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| if (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, |
| "%s: Roaming in progress, return cached RSSI", __func__); |
| *rssi_value = pAdapter->rssi; |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| init_completion(&context.completion); |
| context.pAdapter = pAdapter; |
| context.magic = PEER_INFO_CONTEXT_MAGIC; |
| |
| hstatus = sme_GetRssi(pHddCtx->hHal, hdd_GetRssiCB, |
| pHddStaCtx->conn_info.staId[ 0 ], |
| pHddStaCtx->conn_info.bssId, pAdapter->rssi, |
| &context, pHddCtx->pvosContext); |
| if (eHAL_STATUS_SUCCESS != hstatus) |
| { |
| hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI", |
| __func__); |
| /* we'll returned a cached value below */ |
| } |
| else |
| { |
| /* request was sent -- wait for the response */ |
| rc = wait_for_completion_timeout(&context.completion, |
| msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); |
| if (!rc) { |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| FL("SME timed out while retrieving RSSI")); |
| /* we'll now returned a cached value below */ |
| } |
| } |
| |
| /* either we never sent a request, we sent a request and received a |
| response or we sent a request and timed out. if we never sent a |
| request or if we sent a request and got a response, we want to |
| clear the magic out of paranoia. if we timed out there is a |
| race condition such that the callback function could be |
| executing at the same time we are. of primary concern is if the |
| callback function had already verified the "magic" but had not |
| yet set the completion variable when a timeout occurred. we |
| serialize these activities by invalidating the magic while |
| holding a shared spinlock which will cause us to block if the |
| callback is currently executing */ |
| spin_lock(&hdd_context_lock); |
| context.magic = 0; |
| spin_unlock(&hdd_context_lock); |
| |
| *rssi_value = pAdapter->rssi; |
| hddLog(LOG1, FL("RSSI = %d"), *rssi_value); |
| |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| VOS_STATUS wlan_hdd_get_snr(hdd_adapter_t *pAdapter, v_S7_t *snr) |
| { |
| struct statsContext context; |
| hdd_context_t *pHddCtx; |
| hdd_station_ctx_t *pHddStaCtx; |
| eHalStatus hstatus; |
| unsigned long rc; |
| int valid; |
| |
| ENTER(); |
| if (NULL == pAdapter) |
| { |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| "%s: Invalid context, pAdapter", __func__); |
| return VOS_STATUS_E_FAULT; |
| } |
| |
| pHddCtx = WLAN_HDD_GET_CTX(pAdapter); |
| valid = wlan_hdd_validate_context(pHddCtx); |
| if (0 != valid) |
| return VOS_STATUS_E_FAULT; |
| |
| pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| |
| init_completion(&context.completion); |
| context.pAdapter = pAdapter; |
| context.magic = SNR_CONTEXT_MAGIC; |
| |
| hstatus = sme_GetSnr(pHddCtx->hHal, hdd_GetSnrCB, |
| pHddStaCtx->conn_info.staId[ 0 ], |
| pHddStaCtx->conn_info.bssId, |
| &context); |
| if (eHAL_STATUS_SUCCESS != hstatus) |
| { |
| hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Unable to retrieve RSSI", |
| __func__); |
| /* we'll returned a cached value below */ |
| } |
| else |
| { |
| /* request was sent -- wait for the response */ |
| rc = wait_for_completion_timeout(&context.completion, |
| msecs_to_jiffies(WLAN_WAIT_TIME_STATS)); |
| if (!rc) { |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| FL("SME timed out while retrieving SNR")); |
| /* we'll now returned a cached value below */ |
| } |
| } |
| |
| /* either we never sent a request, we sent a request and received a |
| response or we sent a request and timed out. if we never sent a |
| request or if we sent a request and got a response, we want to |
| clear the magic out of paranoia. if we timed out there is a |
| race condition such that the callback function could be |
| executing at the same time we are. of primary concern is if the |
| callback function had already verified the "magic" but had not |
| yet set the completion variable when a timeout occurred. we |
| serialize these activities by invalidating the magic while |
| holding a shared spinlock which will cause us to block if the |
| callback is currently executing */ |
| spin_lock(&hdd_context_lock); |
| context.magic = 0; |
| spin_unlock(&hdd_context_lock); |
| |
| *snr = pAdapter->snr; |
| EXIT(); |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| void hdd_StatisticsCB( void *pStats, void *pContext ) |
| { |
| hdd_adapter_t *pAdapter = (hdd_adapter_t *)pContext; |
| hdd_stats_t *pStatsCache = NULL; |
| hdd_wext_state_t *pWextState; |
| VOS_STATUS vos_status = VOS_STATUS_SUCCESS; |
| |
| tCsrSummaryStatsInfo *pSummaryStats = NULL; |
| tCsrGlobalClassAStatsInfo *pClassAStats = NULL; |
| tCsrGlobalClassBStatsInfo *pClassBStats = NULL; |
| tCsrGlobalClassCStatsInfo *pClassCStats = NULL; |
| tCsrGlobalClassDStatsInfo *pClassDStats = NULL; |
| tCsrPerStaStatsInfo *pPerStaStats = NULL; |
| |
| if (pAdapter!= NULL) |
| pStatsCache = &pAdapter->hdd_stats; |
| |
| |
| pSummaryStats = (tCsrSummaryStatsInfo *)pStats; |
| pClassAStats = (tCsrGlobalClassAStatsInfo *)( pSummaryStats + 1 ); |
| pClassBStats = (tCsrGlobalClassBStatsInfo *)( pClassAStats + 1 ); |
| pClassCStats = (tCsrGlobalClassCStatsInfo *)( pClassBStats + 1 ); |
| pClassDStats = (tCsrGlobalClassDStatsInfo *)( pClassCStats + 1 ); |
| pPerStaStats = (tCsrPerStaStatsInfo *)( pClassDStats + 1 ); |
| |
| if (pStatsCache!=NULL) |
| { |
| // and copy the stats into the cache we keep in the adapter instance structure |
| vos_mem_copy( &pStatsCache->summary_stat, pSummaryStats, sizeof( pStatsCache->summary_stat ) ); |
| vos_mem_copy( &pStatsCache->ClassA_stat, pClassAStats, sizeof( pStatsCache->ClassA_stat ) ); |
| vos_mem_copy( &pStatsCache->ClassB_stat, pClassBStats, sizeof( pStatsCache->ClassB_stat ) ); |
| vos_mem_copy( &pStatsCache->ClassC_stat, pClassCStats, sizeof( pStatsCache->ClassC_stat ) ); |
| vos_mem_copy( &pStatsCache->ClassD_stat, pClassDStats, sizeof( pStatsCache->ClassD_stat ) ); |
| vos_mem_copy( &pStatsCache->perStaStats, pPerStaStats, sizeof( pStatsCache->perStaStats ) ); |
| } |
| |
| if (pAdapter) { |
| pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| vos_status = vos_event_set(&pWextState->vosevent); |
| if (!VOS_IS_STATUS_SUCCESS(vos_status)) { |
| hddLog(LOGE, FL("vos_event_set failed")); |
| return; |
| } |
| } |
| } |
| |
| void ccmCfgSetCallback(tHalHandle halHandle, tANI_S32 result) |
| { |
| v_CONTEXT_t pVosContext; |
| hdd_context_t *pHddCtx; |
| VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx ); |
| #if 0 |
| hdd_wext_state_t *pWextState; |
| v_U32_t roamId; |
| #endif |
| |
| ENTER(); |
| |
| pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS,NULL); |
| |
| pHddCtx = (hdd_context_t*) vos_get_context(VOS_MODULE_ID_HDD,pVosContext); |
| if (NULL == pHddCtx) |
| { |
| hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid pHddCtx", __func__); |
| return; |
| } |
| #if 0 |
| pWextState = pAdapter->pWextState; |
| #endif |
| |
| if (WNI_CFG_NEED_RESTART == result || WNI_CFG_NEED_RELOAD == result) |
| { |
| //TODO Verify is this is really used. If yes need to fix it. |
| hdd_reconnect_all_adapters( pHddCtx ); |
| #if 0 |
| pAdapter->conn_info.connState = eConnectionState_NotConnected; |
| INIT_COMPLETION(pAdapter->disconnect_comp_var); |
| vosStatus = sme_RoamDisconnect(halHandle, pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED); |
| |
| if(VOS_STATUS_SUCCESS == vosStatus) |
| wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, |
| msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); |
| |
| sme_RoamConnect(halHandle, |
| pAdapter->sessionId, &(pWextState->roamProfile), |
| &roamId); |
| #endif |
| } |
| |
| EXIT(); |
| |
| } |
| |
| /* hdd_clearRoamProfileIe() - Clear roam profile IEs |
| * @pAdapter: Adapter handle |
| * |
| * Clears roam profile information elements |
| * Returns: none |
| */ |
| void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter) |
| { |
| int i = 0; |
| hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| |
| ENTER(); |
| |
| if (!pWextState) { |
| hddLog(LOGE, FL("ERROR: pWextState not found")); |
| return; |
| } |
| /* clear WPA/RSN/WSC IE information in the profile */ |
| pWextState->roamProfile.nWPAReqIELength = 0; |
| pWextState->roamProfile.pWPAReqIE = (tANI_U8 *)NULL; |
| pWextState->roamProfile.nRSNReqIELength = 0; |
| pWextState->roamProfile.pRSNReqIE = (tANI_U8 *)NULL; |
| |
| #ifdef FEATURE_WLAN_WAPI |
| pWextState->roamProfile.nWAPIReqIELength = 0; |
| pWextState->roamProfile.pWAPIReqIE = (tANI_U8 *)NULL; |
| #endif |
| |
| pWextState->roamProfile.bWPSAssociation = VOS_FALSE; |
| pWextState->roamProfile.bOSENAssociation = VOS_FALSE; |
| pWextState->roamProfile.pAddIEScan = (tANI_U8 *)NULL; |
| pWextState->roamProfile.nAddIEScanLength = 0; |
| pWextState->roamProfile.pAddIEAssoc = (tANI_U8 *)NULL; |
| pWextState->roamProfile.nAddIEAssocLength = 0; |
| |
| pWextState->roamProfile.EncryptionType.numEntries = 1; |
| pWextState->roamProfile.EncryptionType.encryptionType[0] |
| = eCSR_ENCRYPT_TYPE_NONE; |
| |
| pWextState->roamProfile.mcEncryptionType.numEntries = 1; |
| pWextState->roamProfile.mcEncryptionType.encryptionType[0] |
| = eCSR_ENCRYPT_TYPE_NONE; |
| |
| pWextState->roamProfile.AuthType.numEntries = 1; |
| pWextState->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM; |
| |
| vos_mem_zero((pWextState->roamProfile.bssid_hint), VOS_MAC_ADDR_SIZE); |
| |
| #ifdef WLAN_FEATURE_11W |
| pWextState->roamProfile.MFPEnabled = eANI_BOOLEAN_FALSE; |
| pWextState->roamProfile.MFPRequired = 0; |
| pWextState->roamProfile.MFPCapable = 0; |
| #endif |
| |
| pWextState->authKeyMgmt = 0; |
| |
| for (i=0; i < CSR_MAX_NUM_KEY; i++) |
| pWextState->roamProfile.Keys.KeyLength[i] = 0; |
| |
| #ifdef FEATURE_WLAN_WAPI |
| pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_OPEN; |
| pAdapter->wapi_info.nWapiMode = 0; |
| #endif |
| |
| vos_mem_zero((void *)(pWextState->req_bssId), VOS_MAC_ADDR_SIZE); |
| EXIT(); |
| } |
| |
| void wlan_hdd_ula_done_cb(v_VOID_t *callbackContext) |
| { |
| hdd_adapter_t *pAdapter = (hdd_adapter_t*)callbackContext; |
| |
| if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "%s: Invalid pAdapter magic", __func__); |
| } |
| else |
| { |
| complete(&pAdapter->ula_complete); |
| } |
| } |
| |
| VOS_STATUS wlan_hdd_check_ula_done(hdd_adapter_t *pAdapter) |
| { |
| hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| VOS_STATUS vos_status; |
| unsigned long rc; |
| |
| if (VOS_FALSE == pHddStaCtx->conn_info.uIsAuthenticated) |
| { |
| INIT_COMPLETION(pAdapter->ula_complete); |
| |
| /*To avoid race condition between the set key and the last EAPOL |
| packet, notify TL to finish upper layer authentication incase if the |
| last EAPOL packet pending in the TL queue.*/ |
| vos_status = WLANTL_Finish_ULA(wlan_hdd_ula_done_cb, pAdapter); |
| |
| if ( vos_status != VOS_STATUS_SUCCESS ) |
| { |
| VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "[%4d] WLANTL_Finish_ULA returned ERROR status= %d", |
| __LINE__, vos_status ); |
| return vos_status; |
| |
| } |
| |
| rc = wait_for_completion_timeout(&pAdapter->ula_complete, |
| msecs_to_jiffies(HDD_FINISH_ULA_TIME_OUT)); |
| if (rc <= 0) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| FL("failure wait on ULA to complete %ld"), rc); |
| /* we'll still fall through and return success since the |
| * connection may still get established but is just taking |
| * too long for us to wait */ |
| } |
| } |
| return VOS_STATUS_SUCCESS; |
| } |
| |
| v_U8_t* wlan_hdd_get_vendor_oui_ie_ptr(v_U8_t *oui, v_U8_t oui_size, v_U8_t *ie, int ie_len) |
| { |
| |
| int left = ie_len; |
| v_U8_t *ptr = ie; |
| v_U8_t elem_id,elem_len; |
| v_U8_t eid = 0xDD; |
| |
| if ( NULL == ie || 0 == ie_len ) |
| return NULL; |
| |
| while(left >= 2) |
| { |
| elem_id = ptr[0]; |
| elem_len = ptr[1]; |
| left -= 2; |
| if(elem_len > left) |
| { |
| hddLog(VOS_TRACE_LEVEL_FATAL, |
| FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), |
| eid,elem_len,left); |
| return NULL; |
| } |
| if ((elem_id == eid) && (elem_len >= oui_size)) |
| { |
| if(memcmp( &ptr[2], oui, oui_size)==0) |
| return ptr; |
| } |
| |
| left -= elem_len; |
| ptr += (elem_len + 2); |
| } |
| return NULL; |
| } |
| |
| /** |
| * hdd_get_ldpc() - Get adapter LDPC |
| * @adapter: adapter being queried |
| * @value: where to store the value |
| * |
| * Return: 0 on success, negative errno on failure |
| */ |
| int hdd_get_ldpc(hdd_adapter_t *adapter, int *value) |
| { |
| tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); |
| int ret; |
| |
| ENTER(); |
| ret = sme_GetHTConfig(hal, adapter->sessionId, |
| WNI_CFG_HT_CAP_INFO_ADVANCE_CODING); |
| if (ret < 0) { |
| hddLog(LOGE, FL("Failed to get LDPC value")); |
| } else { |
| *value = ret; |
| ret = 0; |
| } |
| return ret; |
| } |
| |
| /** |
| * hdd_set_ldpc() - Set adapter LDPC |
| * @adapter: adapter being modified |
| * @value: new LDPC value |
| * |
| * Return: 0 on success, negative errno on failure |
| */ |
| int hdd_set_ldpc(hdd_adapter_t *adapter, int value) |
| { |
| tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); |
| int ret; |
| |
| hddLog(LOG1, FL("%d"), value); |
| if (value) { |
| /* make sure HT capabilities allow this */ |
| eHalStatus status; |
| uint32_t cfg_value; |
| union { |
| uint16_t cfg_value16; |
| tSirMacHTCapabilityInfo ht_cap_info; |
| } u; |
| |
| status = ccmCfgGetInt(hal, WNI_CFG_HT_CAP_INFO, &cfg_value); |
| if (eHAL_STATUS_SUCCESS != status) { |
| hddLog(LOGE, FL("Failed to get HT capability info")); |
| return -EIO; |
| } |
| u.cfg_value16 = cfg_value & 0xFFFF; |
| if (!u.ht_cap_info.advCodingCap) { |
| hddLog(LOGE, FL("LDCP not supported")); |
| return -EINVAL; |
| } |
| } |
| |
| ret = sme_UpdateHTConfig(hal, adapter->sessionId, |
| WNI_CFG_HT_CAP_INFO_ADVANCE_CODING, |
| value); |
| if (ret) |
| hddLog(LOGE, FL("Failed to set LDPC value")); |
| |
| return ret; |
| } |
| |
| /** |
| * hdd_get_tx_stbc() - Get adapter TX STBC |
| * @adapter: adapter being queried |
| * @value: where to store the value |
| * |
| * Return: 0 on success, negative errno on failure |
| */ |
| int hdd_get_tx_stbc(hdd_adapter_t *adapter, int *value) |
| { |
| tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); |
| int ret; |
| |
| ENTER(); |
| ret = sme_GetHTConfig(hal, adapter->sessionId, |
| WNI_CFG_HT_CAP_INFO_TX_STBC); |
| if (ret < 0) { |
| hddLog(LOGE, FL("Failed to get TX STBC value")); |
| } else { |
| *value = ret; |
| ret = 0; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * hdd_set_tx_stbc() - Set adapter TX STBC |
| * @adapter: adapter being modified |
| * @value: new TX STBC value |
| * |
| * Return: 0 on success, negative errno on failure |
| */ |
| int hdd_set_tx_stbc(hdd_adapter_t *adapter, int value) |
| { |
| tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); |
| int ret; |
| |
| hddLog(LOG1, FL("%d"), value); |
| if (value) { |
| /* make sure HT capabilities allow this */ |
| eHalStatus status; |
| uint32_t cfg_value; |
| union { |
| uint16_t cfg_value16; |
| tSirMacHTCapabilityInfo ht_cap_info; |
| } u; |
| |
| status = ccmCfgGetInt(hal, WNI_CFG_HT_CAP_INFO, &cfg_value); |
| if (eHAL_STATUS_SUCCESS != status) { |
| hddLog(LOGE, FL("Failed to get HT capability info")); |
| return -EIO; |
| } |
| u.cfg_value16 = cfg_value & 0xFFFF; |
| if (!u.ht_cap_info.txSTBC) { |
| hddLog(LOGE, FL("TX STBC not supported")); |
| return -EINVAL; |
| } |
| } |
| ret = sme_UpdateHTConfig(hal, adapter->sessionId, |
| WNI_CFG_HT_CAP_INFO_TX_STBC, |
| value); |
| if (ret) |
| hddLog(LOGE, FL("Failed to set TX STBC value")); |
| |
| return ret; |
| } |
| |
| /** |
| * hdd_get_rx_stbc() - Get adapter RX STBC |
| * @adapter: adapter being queried |
| * @value: where to store the value |
| * |
| * Return: 0 on success, negative errno on failure |
| */ |
| int hdd_get_rx_stbc(hdd_adapter_t *adapter, int *value) |
| { |
| tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); |
| int ret; |
| |
| ENTER(); |
| ret = sme_GetHTConfig(hal, adapter->sessionId, |
| WNI_CFG_HT_CAP_INFO_RX_STBC); |
| if (ret < 0) { |
| hddLog(LOGE, FL("Failed to get RX STBC value")); |
| } else { |
| *value = ret; |
| ret = 0; |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * hdd_set_rx_stbc() - Set adapter RX STBC |
| * @adapter: adapter being modified |
| * @value: new RX STBC value |
| * |
| * Return: 0 on success, negative errno on failure |
| */ |
| int hdd_set_rx_stbc(hdd_adapter_t *adapter, int value) |
| { |
| tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); |
| int ret; |
| |
| hddLog(LOG1, FL("%d"), value); |
| if (value) { |
| /* make sure HT capabilities allow this */ |
| eHalStatus status; |
| uint32_t cfg_value; |
| union { |
| uint16_t cfg_value16; |
| tSirMacHTCapabilityInfo ht_cap_info; |
| } u; |
| |
| status = ccmCfgGetInt(hal, WNI_CFG_HT_CAP_INFO, &cfg_value); |
| if (eHAL_STATUS_SUCCESS != status) { |
| hddLog(LOGE, FL("Failed to get HT capability info")); |
| return -EIO; |
| } |
| u.cfg_value16 = cfg_value & 0xFFFF; |
| if (!u.ht_cap_info.rxSTBC) { |
| hddLog(LOGE, FL("RX STBC not supported")); |
| return -EINVAL; |
| } |
| } |
| ret = sme_UpdateHTConfig(hal, adapter->sessionId, |
| WNI_CFG_HT_CAP_INFO_RX_STBC, |
| value); |
| if (ret) |
| hddLog(LOGE, FL("Failed to set RX STBC value")); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_set_commit() - set commit |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: extra |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int __iw_set_commit(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| hdd_adapter_t *adapter; |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| adapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| hdd_ctx = WLAN_HDD_GET_CTX(adapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| /* Do nothing for now */ |
| return 0; |
| } |
| |
| /** |
| * iw_set_commit() - SSR wrapper function for __iw_set_commit |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: extra |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| int iw_set_commit(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_set_commit(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_get_name() - get name |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: extra |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int __iw_get_name(struct net_device *dev, |
| struct iw_request_info *info, |
| char *wrqu, char *extra) |
| { |
| ENTER(); |
| strlcpy(wrqu, "Qcom:802.11n", IFNAMSIZ); |
| EXIT(); |
| return 0; |
| } |
| |
| /** |
| * __iw_get_name() - SSR wrapper for __iw_get_name |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: extra |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_get_name(struct net_device *dev, |
| struct iw_request_info *info, |
| char *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_get_name(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| |
| /** |
| * __iw_set_mode() - SIOCSIWMODE ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_set_mode(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| hdd_wext_state_t *pWextState; |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| tCsrRoamProfile *pRoamProfile; |
| eCsrRoamBssType LastBSSType; |
| eMib_dot11DesiredBssType connectedBssType; |
| hdd_config_t *pConfig; |
| struct wireless_dev *wdev; |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| wdev = dev->ieee80211_ptr; |
| pRoamProfile = &pWextState->roamProfile; |
| LastBSSType = pRoamProfile->BSSType; |
| |
| hddLog(LOG1, "%s Old Bss type = %d", __func__, LastBSSType); |
| |
| switch (wrqu->mode) |
| { |
| case IW_MODE_ADHOC: |
| hddLog(LOG1, "%s Setting AP Mode as IW_MODE_ADHOC", __func__); |
| pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS; |
| // Set the phymode correctly for IBSS. |
| pConfig = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; |
| pWextState->roamProfile.phyMode = hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); |
| pAdapter->device_mode = WLAN_HDD_IBSS; |
| wdev->iftype = NL80211_IFTYPE_ADHOC; |
| break; |
| case IW_MODE_INFRA: |
| hddLog(LOG1, "%s Setting AP Mode as IW_MODE_INFRA", __func__); |
| pRoamProfile->BSSType = eCSR_BSS_TYPE_INFRASTRUCTURE; |
| wdev->iftype = NL80211_IFTYPE_STATION; |
| break; |
| case IW_MODE_AUTO: |
| hddLog(LOG1, "%s Setting AP Mode as IW_MODE_AUTO", __func__); |
| pRoamProfile->BSSType = eCSR_BSS_TYPE_ANY; |
| break; |
| default: |
| hddLog(LOGE, "%s Unknown AP Mode value %d ", __func__, wrqu->mode); |
| return -EOPNOTSUPP; |
| } |
| |
| if ( LastBSSType != pRoamProfile->BSSType ) |
| { |
| //the BSS mode changed |
| // We need to issue disconnect if connected or in IBSS disconnect state |
| if ( hdd_connGetConnectedBssType( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), &connectedBssType ) || |
| ( eCSR_BSS_TYPE_START_IBSS == LastBSSType ) ) |
| { |
| VOS_STATUS vosStatus; |
| // need to issue a disconnect to CSR. |
| INIT_COMPLETION(pAdapter->disconnect_comp_var); |
| vosStatus = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), |
| pAdapter->sessionId, |
| eCSR_DISCONNECT_REASON_IBSS_LEAVE ); |
| if(VOS_STATUS_SUCCESS == vosStatus) |
| { |
| unsigned long rc; |
| rc = wait_for_completion_timeout( |
| &pAdapter->disconnect_comp_var, |
| msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); |
| if (!rc) |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| FL("failed wait on disconnect_comp_var")); |
| } |
| } |
| } |
| |
| EXIT(); |
| return 0; |
| } |
| |
| /** |
| * iw_set_mode() - SSR wrapper for __iw_set_mode() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_set_mode(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_set_mode(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_get_mode() - SIOCGIWMODE ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int |
| __iw_get_mode(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| hdd_wext_state_t *pWextState; |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| |
| switch (pWextState->roamProfile.BSSType) { |
| case eCSR_BSS_TYPE_INFRASTRUCTURE: |
| hddLog(LOG1, FL("returns IW_MODE_INFRA")); |
| wrqu->mode = IW_MODE_INFRA; |
| break; |
| case eCSR_BSS_TYPE_IBSS: |
| case eCSR_BSS_TYPE_START_IBSS: |
| hddLog(LOG1, FL("returns IW_MODE_ADHOC")); |
| wrqu->mode = IW_MODE_ADHOC; |
| break; |
| case eCSR_BSS_TYPE_ANY: |
| default: |
| hddLog(LOG1, FL("returns IW_MODE_AUTO")); |
| wrqu->mode = IW_MODE_AUTO; |
| break; |
| } |
| |
| EXIT(); |
| return 0; |
| } |
| |
| /** |
| * iw_get_mode() - SSR wrapper for __iw_get_mode() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_get_mode(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_get_mode(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_set_freq() - SIOCSIWFREQ ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_set_freq(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| v_U32_t numChans = 0; |
| v_U8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; |
| v_U32_t indx = 0; |
| hdd_wext_state_t *pWextState; |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); |
| hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| tCsrRoamProfile * pRoamProfile; |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| |
| pRoamProfile = &pWextState->roamProfile; |
| |
| hddLog(LOG1,"setCHANNEL ioctl"); |
| |
| /* Link is up then return cant set channel*/ |
| if(eConnectionState_IbssConnected == pHddStaCtx->conn_info.connState || |
| eConnectionState_Associated == pHddStaCtx->conn_info.connState) |
| { |
| hddLog( LOGE, "IBSS Associated"); |
| return -EOPNOTSUPP; |
| } |
| |
| /* Settings by Frequency as input */ |
| if((wrqu->freq.e == 1) && (wrqu->freq.m >= (tANI_U32)2.412e8) && |
| (wrqu->freq.m <= (tANI_U32)5.825e8)) |
| { |
| tANI_U32 freq = wrqu->freq.m / 100000; |
| |
| while ((indx < FREQ_CHAN_MAP_TABLE_SIZE) && (freq != freq_chan_map[indx].freq)) |
| indx++; |
| if (indx >= FREQ_CHAN_MAP_TABLE_SIZE) |
| { |
| return -EINVAL; |
| } |
| wrqu->freq.e = 0; |
| wrqu->freq.m = freq_chan_map[indx].chan; |
| |
| } |
| |
| if (wrqu->freq.e == 0) |
| { |
| if((wrqu->freq.m < WNI_CFG_CURRENT_CHANNEL_STAMIN) || |
| (wrqu->freq.m > WNI_CFG_CURRENT_CHANNEL_STAMAX)) |
| { |
| hddLog(LOG1,"%s: Channel [%d] is outside valid range from %d to %d", |
| __func__, wrqu->freq.m, WNI_CFG_CURRENT_CHANNEL_STAMIN, |
| WNI_CFG_CURRENT_CHANNEL_STAMAX); |
| return -EINVAL; |
| } |
| |
| numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN; |
| |
| if (ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST, |
| validChan, &numChans) != eHAL_STATUS_SUCCESS){ |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, |
| FL("failed to get ini parameter, WNI_CFG_VALID_CHANNEL_LIST")); |
| return -EIO; |
| } |
| |
| for (indx = 0; indx < numChans; indx++) { |
| if (wrqu->freq.m == validChan[indx]){ |
| break; |
| } |
| } |
| } |
| else{ |
| |
| return -EINVAL; |
| } |
| |
| if(indx >= numChans) |
| { |
| return -EINVAL; |
| } |
| |
| /* Set the Operational Channel */ |
| numChans = pRoamProfile->ChannelInfo.numOfChannels = 1; |
| pHddStaCtx->conn_info.operationChannel = wrqu->freq.m; |
| pRoamProfile->ChannelInfo.ChannelList = &pHddStaCtx->conn_info.operationChannel; |
| |
| hddLog(LOG1,"pRoamProfile->operationChannel = %d", wrqu->freq.m); |
| |
| EXIT(); |
| |
| return ret; |
| } |
| |
| /** |
| * iw_set_freq() - SSR wrapper for __iw_set_freq() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_set_freq(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_set_freq(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_get_freq() - SIOCGIWFREQ ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @fwrq: ioctl frequency data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_get_freq(struct net_device *dev, struct iw_request_info *info, |
| struct iw_freq *fwrq, char *extra) |
| { |
| v_U32_t status = FALSE, channel = 0, freq = 0; |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| tHalHandle hHal; |
| hdd_wext_state_t *pWextState; |
| tCsrRoamProfile * pRoamProfile; |
| hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); |
| |
| pRoamProfile = &pWextState->roamProfile; |
| |
| if( pHddStaCtx->conn_info.connState== eConnectionState_Associated ) |
| { |
| if (sme_GetOperationChannel(hHal, &channel, pAdapter->sessionId) != eHAL_STATUS_SUCCESS) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| FL("failed to get operating channel %u"), pAdapter->sessionId); |
| return -EIO; |
| } |
| else |
| { |
| status = hdd_wlan_get_freq(channel, &freq); |
| if( TRUE == status ) |
| { |
| /* Set Exponent parameter as 6 (MHZ) in struct iw_freq |
| * iwlist & iwconfig command shows frequency into proper |
| * format (2.412 GHz instead of 246.2 MHz)*/ |
| fwrq->m = freq; |
| fwrq->e = MHZ; |
| } |
| } |
| } |
| else |
| { |
| /* Set Exponent parameter as 6 (MHZ) in struct iw_freq |
| * iwlist & iwconfig command shows frequency into proper |
| * format (2.412 GHz instead of 246.2 MHz)*/ |
| fwrq->m = 0; |
| fwrq->e = MHZ; |
| } |
| return 0; |
| } |
| |
| /** |
| * iw_get_freq() - SSR wrapper for __iw_get_freq() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @fwrq: pointer to frequency data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_get_freq(struct net_device *dev, struct iw_request_info *info, |
| struct iw_freq *fwrq, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_get_freq(dev, info, fwrq, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_get_tx_power() - SIOCGIWTXPOW ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_get_tx_power(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); |
| hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| int ret; |
| |
| ENTER(); |
| |
| ret = wlan_hdd_validate_context(pHddCtx); |
| if (0 != ret) |
| return ret; |
| |
| if(eConnectionState_Associated != pHddStaCtx->conn_info.connState) |
| { |
| wrqu->txpower.value = 0; |
| return 0; |
| } |
| wlan_hdd_get_classAstats(pAdapter); |
| wrqu->txpower.value = pAdapter->hdd_stats.ClassA_stat.max_pwr; |
| |
| return 0; |
| } |
| |
| /** |
| * iw_get_tx_power() - SSR wrapper for __iw_get_tx_power() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_get_tx_power(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_get_tx_power(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_set_tx_power() - SIOCSIWTXPOW ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_set_tx_power(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| if ( ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, wrqu->txpower.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| FL("failed to set ini parameter, WNI_CFG_CURRENT_TX_POWER_LEVEL")); |
| return -EIO; |
| } |
| |
| EXIT(); |
| |
| return 0; |
| } |
| |
| /** |
| * iw_set_tx_power() - SSR wrapper for __iw_set_tx_power() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_set_tx_power(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_set_tx_power(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_get_bitrate() - SIOCGIWRATE ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_get_bitrate(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| VOS_STATUS vos_status = VOS_STATUS_SUCCESS; |
| eHalStatus status = eHAL_STATUS_SUCCESS; |
| hdd_wext_state_t *pWextState; |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| if(eConnectionState_Associated != pHddStaCtx->conn_info.connState) { |
| wrqu->bitrate.value = 0; |
| } |
| else { |
| status = sme_GetStatistics( WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_HDD, |
| SME_SUMMARY_STATS | |
| SME_GLOBAL_CLASSA_STATS | |
| SME_GLOBAL_CLASSB_STATS | |
| SME_GLOBAL_CLASSC_STATS | |
| SME_GLOBAL_CLASSD_STATS | |
| SME_PER_STA_STATS, |
| hdd_StatisticsCB, 0, FALSE, |
| pHddStaCtx->conn_info.staId[0], pAdapter, |
| pAdapter->sessionId ); |
| |
| if(eHAL_STATUS_SUCCESS != status) |
| { |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| "%s: Unable to retrieve statistics", |
| __func__); |
| return status; |
| } |
| |
| pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| |
| vos_status = vos_wait_single_event(&pWextState->vosevent, WLAN_WAIT_TIME_STATS); |
| |
| if (!VOS_IS_STATUS_SUCCESS(vos_status)) |
| { |
| hddLog(VOS_TRACE_LEVEL_ERROR, |
| "%s: SME timeout while retrieving statistics", |
| __func__); |
| return VOS_STATUS_E_FAILURE; |
| } |
| |
| wrqu->bitrate.value = pAdapter->hdd_stats.ClassA_stat.tx_rate*500*1000; |
| } |
| |
| EXIT(); |
| |
| return vos_status; |
| } |
| |
| /** |
| * iw_get_bitrate() - SSR wrapper for __iw_get_bitrate() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_get_bitrate(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_get_bitrate(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_set_bitrate() - SIOCSIWRATE ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_set_bitrate(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, |
| char *extra) |
| { |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| hdd_wext_state_t *pWextState; |
| hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| v_U8_t supp_rates[WNI_CFG_SUPPORTED_RATES_11A_LEN]; |
| v_U32_t a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; |
| v_U32_t b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; |
| v_U32_t i, rate; |
| v_U32_t valid_rate = FALSE, active_phy_mode = 0; |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| |
| if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) |
| { |
| return -ENXIO ; |
| } |
| |
| rate = wrqu->bitrate.value; |
| |
| if (rate == -1) |
| { |
| rate = WNI_CFG_FIXED_RATE_AUTO; |
| valid_rate = TRUE; |
| } |
| else if (ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), |
| WNI_CFG_DOT11_MODE, &active_phy_mode) == eHAL_STATUS_SUCCESS) |
| { |
| if (active_phy_mode == WNI_CFG_DOT11_MODE_11A || active_phy_mode == WNI_CFG_DOT11_MODE_11G |
| || active_phy_mode == WNI_CFG_DOT11_MODE_11B) |
| { |
| if ((ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), |
| WNI_CFG_SUPPORTED_RATES_11A, |
| supp_rates, &a_len) == eHAL_STATUS_SUCCESS) && |
| (ccmCfgGetStr(WLAN_HDD_GET_HAL_CTX(pAdapter), |
| WNI_CFG_SUPPORTED_RATES_11B, |
| supp_rates, &b_len) == eHAL_STATUS_SUCCESS)) |
| { |
| for (i = 0; i < (b_len + a_len); ++i) |
| { |
| /* supported rates returned is double the actual rate so we divide it by 2 */ |
| if ((supp_rates[i]&0x7F)/2 == rate) |
| { |
| valid_rate = TRUE; |
| rate = i + WNI_CFG_FIXED_RATE_1MBPS; |
| break; |
| } |
| } |
| } |
| } |
| } |
| if (valid_rate != TRUE) |
| { |
| return -EINVAL; |
| } |
| if (ccmCfgSetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), |
| WNI_CFG_FIXED_RATE, rate, |
| ccmCfgSetCallback,eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| FL("failed to set ini parameter, WNI_CFG_FIXED_RATE")); |
| return -EIO; |
| } |
| return 0; |
| } |
| |
| /** |
| * iw_set_bitrate() - SSR wrapper for __iw_set_bitrate() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_set_bitrate(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_set_bitrate(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_set_genie() - SIOCSIWGENIE ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_set_genie(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| u_int8_t *genie = NULL; |
| u_int8_t *base_genie = NULL; |
| v_U16_t remLen; |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| if (!wrqu->data.length) { |
| hdd_clearRoamProfileIe(pAdapter); |
| EXIT(); |
| return 0; |
| } |
| |
| base_genie = mem_alloc_copy_from_user_helper(wrqu->data.pointer, |
| wrqu->data.length); |
| if (NULL == base_genie) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| "mem_alloc_copy_from_user_helper fail"); |
| return -ENOMEM; |
| } |
| |
| genie = base_genie; |
| |
| remLen = wrqu->data.length; |
| |
| hddLog(LOG1,"iw_set_genie ioctl IE[0x%X], LEN[%d]", genie[0], genie[1]); |
| |
| /* clear any previous genIE before this call */ |
| memset( &pWextState->genIE, 0, sizeof(pWextState->genIE) ); |
| |
| while (remLen >= 2) |
| { |
| v_U16_t eLen = 0; |
| v_U8_t elementId; |
| elementId = *genie++; |
| eLen = *genie++; |
| remLen -= 2; |
| |
| hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]", |
| __func__, elementId, eLen); |
| |
| if (remLen < eLen) { |
| hddLog(LOGE, "Remaining len: %u less than ie len: %u", |
| remLen, eLen); |
| ret = -EINVAL; |
| goto exit; |
| } |
| |
| switch ( elementId ) |
| { |
| case IE_EID_VENDOR: |
| if ((IE_LEN_SIZE+IE_EID_SIZE+IE_VENDOR_OUI_SIZE) > eLen) /* should have at least OUI */ |
| { |
| ret = -EINVAL; |
| goto exit; |
| } |
| |
| if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) |
| { |
| v_U16_t curGenIELen = pWextState->genIE.length; |
| hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS OUI(%02x %02x %02x %02x) IE(len %d)", |
| __func__, genie[0], genie[1], genie[2], genie[3], eLen + 2); |
| |
| if( SIR_MAC_MAX_IE_LENGTH < (pWextState->genIE.length + eLen) ) |
| { |
| hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. " |
| "Need bigger buffer space"); |
| VOS_ASSERT(0); |
| ret = -EINVAL; |
| goto exit; |
| } |
| // save to Additional IE ; it should be accumulated to handle WPS IE + other IE |
| memcpy( pWextState->genIE.addIEdata + curGenIELen, genie - 2, eLen + 2); |
| pWextState->genIE.length += eLen + 2; |
| } |
| else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) |
| { |
| hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2); |
| if ((eLen + 2) > (sizeof(pWextState->WPARSNIE))) |
| { |
| hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. " |
| "Need bigger buffer space"); |
| ret = -EINVAL; |
| VOS_ASSERT(0); |
| goto exit; |
| } |
| memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); |
| memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)); |
| pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE; |
| pWextState->roamProfile.nWPAReqIELength = eLen + 2; |
| } |
| else /* any vendorId except WPA IE should be accumulated to genIE */ |
| { |
| v_U16_t curGenIELen = pWextState->genIE.length; |
| hddLog (VOS_TRACE_LEVEL_INFO, "%s Set OUI(%02x %02x %02x %02x) IE(len %d)", |
| __func__, genie[0], genie[1], genie[2], genie[3], eLen + 2); |
| |
| if( SIR_MAC_MAX_IE_LENGTH < (pWextState->genIE.length + eLen) ) |
| { |
| hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. " |
| "Need bigger buffer space"); |
| VOS_ASSERT(0); |
| ret = -ENOMEM; |
| goto exit; |
| } |
| // save to Additional IE ; it should be accumulated to handle WPS IE + other IE |
| memcpy( pWextState->genIE.addIEdata + curGenIELen, genie - 2, eLen + 2); |
| pWextState->genIE.length += eLen + 2; |
| } |
| break; |
| case DOT11F_EID_RSN: |
| hddLog (LOG1, "%s Set RSN IE (len %d)",__func__, eLen+2); |
| if ((eLen + 2) > (sizeof(pWextState->WPARSNIE))) |
| { |
| hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate genIE. " |
| "Need bigger buffer space"); |
| ret = -EINVAL; |
| VOS_ASSERT(0); |
| goto exit; |
| } |
| memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); |
| memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2)); |
| pWextState->roamProfile.pRSNReqIE = pWextState->WPARSNIE; |
| pWextState->roamProfile.nRSNReqIELength = eLen + 2; |
| break; |
| |
| default: |
| hddLog (LOGE, "%s Set UNKNOWN IE %X",__func__, elementId); |
| goto exit; |
| } |
| remLen -= eLen; |
| |
| /* Move genie only if next element is present */ |
| if (remLen >= 2) |
| genie += eLen; |
| } |
| exit: |
| EXIT(); |
| vos_mem_free(base_genie); |
| return ret; |
| } |
| |
| /** |
| * iw_set_genie() - SSR wrapper for __iw_set_genie() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_set_genie(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_set_genie(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_get_genie() - SIOCGIWGENIE ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_get_genie(struct net_device *dev, struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| hdd_wext_state_t *pWextState; |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); |
| eHalStatus status; |
| v_U32_t length = DOT11F_IE_RSN_MAX_LEN; |
| v_U8_t genIeBytes[DOT11F_IE_RSN_MAX_LEN]; |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| hddLog(LOG1,"getGEN_IE ioctl"); |
| |
| pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| |
| if( pHddStaCtx->conn_info.connState == eConnectionState_NotConnected) |
| { |
| return -ENXIO; |
| } |
| |
| // Return something ONLY if we are associated with an RSN or WPA network |
| if ( VOS_TRUE != hdd_IsAuthTypeRSN(WLAN_HDD_GET_HAL_CTX(pAdapter), |
| pWextState->roamProfile.negotiatedAuthType)) |
| { |
| return -ENXIO; |
| } |
| |
| // Actually retrieve the RSN IE from CSR. (We previously sent it down in the CSR Roam Profile.) |
| status = csrRoamGetWpaRsnReqIE(WLAN_HDD_GET_HAL_CTX(pAdapter), |
| pAdapter->sessionId, |
| &length, |
| genIeBytes); |
| if (eHAL_STATUS_SUCCESS != status) { |
| hddLog(LOGE, FL("failed to get WPA-RSN IE data")); |
| return -EFAULT; |
| } |
| |
| wrqu->data.length = length; |
| if (length > DOT11F_IE_RSN_MAX_LEN) { |
| hddLog(LOGE, |
| FL("invalid buffer length length:%d"), length); |
| return -E2BIG; |
| } |
| |
| vos_mem_copy( extra, (v_VOID_t*)genIeBytes, length); |
| |
| hddLog(LOG1, FL("RSN IE of %d bytes returned"), wrqu->data.length ); |
| |
| EXIT(); |
| |
| return 0; |
| } |
| |
| /** |
| * iw_get_genie() - SSR wrapper for __iw_get_genie() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_get_genie(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_get_genie(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_get_encode() - SIOCGIWENCODE ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @dwrq: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_get_encode(struct net_device *dev, struct iw_request_info *info, |
| struct iw_point *dwrq, char *extra) |
| { |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); |
| tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile); |
| int keyId; |
| eCsrAuthType authType = eCSR_AUTH_TYPE_NONE; |
| int i; |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| keyId = pRoamProfile->Keys.defaultIndex; |
| |
| if(keyId < 0 || keyId >= MAX_WEP_KEYS) |
| { |
| hddLog(LOG1,"%s: Invalid keyId : %d", __func__, keyId); |
| return -EINVAL; |
| } |
| |
| if(pRoamProfile->Keys.KeyLength[keyId] > 0) |
| { |
| dwrq->flags |= IW_ENCODE_ENABLED; |
| dwrq->length = pRoamProfile->Keys.KeyLength[keyId]; |
| vos_mem_copy(extra,&(pRoamProfile->Keys.KeyMaterial[keyId][0]),pRoamProfile->Keys.KeyLength[keyId]); |
| |
| dwrq->flags |= (keyId + 1); |
| |
| } |
| else |
| { |
| dwrq->flags |= IW_ENCODE_DISABLED; |
| } |
| |
| for(i=0; i < MAX_WEP_KEYS; i++) |
| { |
| if (pRoamProfile->Keys.KeyLength[i] == 0) |
| continue; |
| else |
| break; |
| } |
| |
| if(MAX_WEP_KEYS == i) |
| { |
| dwrq->flags |= IW_ENCODE_NOKEY; |
| } |
| |
| authType = ((hdd_station_ctx_t*)WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType; |
| |
| if(eCSR_AUTH_TYPE_OPEN_SYSTEM == authType) |
| { |
| dwrq->flags |= IW_ENCODE_OPEN; |
| } |
| else |
| { |
| dwrq->flags |= IW_ENCODE_RESTRICTED; |
| } |
| EXIT(); |
| return 0; |
| } |
| |
| /** |
| * iw_get_encode() - SSR wrapper for __iw_get_encode() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @dwrq: pointer to encoding information |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_get_encode(struct net_device *dev, struct iw_request_info *info, |
| struct iw_point *dwrq, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_get_encode(dev, info, dwrq, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| #define PAE_ROLE_AUTHENTICATOR 1 // =1 for authenticator, |
| #define PAE_ROLE_SUPPLICANT 0 // =0 for supplicant |
| |
| |
| /* |
| * This function sends a single 'key' to LIM at all time. |
| */ |
| |
| /** |
| * __iw_get_rts_threshold() - SIOCGIWRTS ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_get_rts_threshold(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| v_U32_t status = 0; |
| |
| status = hdd_wlan_get_rts_threshold(pAdapter,wrqu); |
| |
| return status; |
| } |
| |
| /** |
| * iw_get_rts_threshold() - SSR wrapper for __iw_get_rts_threshold() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_get_rts_threshold(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_get_rts_threshold(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_set_rts_threshold() - SIOCSIWRTS ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_set_rts_threshold(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
| tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); |
| hdd_context_t *hdd_ctx; |
| int ret; |
| |
| ENTER(); |
| |
| hdd_ctx = WLAN_HDD_GET_CTX(pAdapter); |
| ret = wlan_hdd_validate_context(hdd_ctx); |
| if (0 != ret) |
| return ret; |
| |
| if ( wrqu->rts.value < WNI_CFG_RTS_THRESHOLD_STAMIN || wrqu->rts.value > WNI_CFG_RTS_THRESHOLD_STAMAX ) |
| { |
| return -EINVAL; |
| } |
| |
| if ( ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, wrqu->rts.value, ccmCfgSetCallback, eANI_BOOLEAN_TRUE) != eHAL_STATUS_SUCCESS ) |
| { |
| VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, |
| FL("failed to set ini parameter, WNI_CFG_RTS_THRESHOLD")); |
| return -EIO; |
| } |
| |
| EXIT(); |
| |
| return 0; |
| } |
| |
| /** |
| * iw_set_rts_threshold() - SSR wrapper for __iw_set_rts_threshold() |
| * @dev: pointer to net_device |
| * @info: pointer to iw_request_info |
| * @wrqu: pointer to iwreq_data |
| * @extra: pointer to extra ioctl payload |
| * |
| * Return: 0 on success, error number otherwise |
| */ |
| static int iw_set_rts_threshold(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| int ret; |
| |
| vos_ssr_protect(__func__); |
| ret = __iw_set_rts_threshold(dev, info, wrqu, extra); |
| vos_ssr_unprotect(__func__); |
| |
| return ret; |
| } |
| |
| /** |
| * __iw_get_frag_threshold() - SIOCGIWFRAG ioctl handler |
| * @dev: device upon which the ioctl was received |
| * @info: ioctl request information |
| * @wrqu: ioctl request data |
| * @extra: ioctl extra data |
| * |
| * Return: 0 on success, non-zero on error |
| */ |
| static int __iw_get_frag_threshold(struct net_device *dev, |
| struct iw_request_info *info, |
| union iwreq_data *wrqu, char *extra) |
| { |
| hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); |
|